Implement custom icons per workspace. (#261)
* Implement custom icons per workspace. * Finish custom workspace icon implementation * Remove unsupported color definition.
This commit is contained in:
46
README.md
46
README.md
@@ -11,21 +11,26 @@
|
|||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
# HyprPanel 🚀
|
# HyprPanel 🚀
|
||||||
|
|
||||||
A panel built for Hyprland with [AGS](https://github.com/Aylur/ags)
|
A panel built for Hyprland with [AGS](https://github.com/Aylur/ags)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
The [HyprPanel Wiki](https://hyprpanel.com/getting_started/installation.html) contains in depth instructions for installing the panel and all of its dependencies. The instructions below are general instructions for installing the panel.
|
The [HyprPanel Wiki](https://hyprpanel.com/getting_started/installation.html) contains in depth instructions for installing the panel and all of its dependencies. The instructions below are general instructions for installing the panel.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
Bun
|
Bun
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
curl -fsSL https://bun.sh/install | bash && \
|
curl -fsSL https://bun.sh/install | bash && \
|
||||||
sudo ln -s $HOME/.bun/bin/bun /usr/local/bin/bun
|
sudo ln -s $HOME/.bun/bin/bun /usr/local/bin/bun
|
||||||
```
|
```
|
||||||
|
|
||||||
Additional dependencies:
|
Additional dependencies:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
pipewire
|
pipewire
|
||||||
libgtop
|
libgtop
|
||||||
@@ -45,6 +50,7 @@ gnome-bluetooth-3.0
|
|||||||
```
|
```
|
||||||
|
|
||||||
Optional Dependencies:
|
Optional Dependencies:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
## Used for Tracking GPU Usage in your Dashboard (NVidia only)
|
## Used for Tracking GPU Usage in your Dashboard (NVidia only)
|
||||||
python
|
python
|
||||||
@@ -58,11 +64,13 @@ pacman-contrib
|
|||||||
```
|
```
|
||||||
|
|
||||||
Arch (pacman):
|
Arch (pacman):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo pacman -S pipewire libgtop bluez bluez-utils btop networkmanager dart-sass wl-clipboard brightnessctl swww python gnome-bluetooth-3.0 pacman-contrib
|
sudo pacman -S pipewire libgtop bluez bluez-utils btop networkmanager dart-sass wl-clipboard brightnessctl swww python gnome-bluetooth-3.0 pacman-contrib
|
||||||
```
|
```
|
||||||
|
|
||||||
Arch (AUR):
|
Arch (AUR):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yay -S grimblast-git gpu-screen-recorder hyprpicker matugen-bin python-gpustat aylurs-gtk-shell-git
|
yay -S grimblast-git gpu-screen-recorder hyprpicker matugen-bin python-gpustat aylurs-gtk-shell-git
|
||||||
```
|
```
|
||||||
@@ -72,32 +80,43 @@ For NixOS/Home-Manager, see [NixOS & Home-Manager instructions](#nixos--home-man
|
|||||||
## Instructions
|
## Instructions
|
||||||
|
|
||||||
### AGS
|
### AGS
|
||||||
|
|
||||||
Once everything is installed you need to put the contents of this repo in `~/.config/ags`.
|
Once everything is installed you need to put the contents of this repo in `~/.config/ags`.
|
||||||
If you already have something in `~/.config/ags`, it's recommended that you back it up with:
|
If you already have something in `~/.config/ags`, it's recommended that you back it up with:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mv $HOME/.config/ags $HOME/.config/ags.bkup
|
mv $HOME/.config/ags $HOME/.config/ags.bkup
|
||||||
```
|
```
|
||||||
|
|
||||||
Otherwise you can use this command to install the panel:
|
Otherwise you can use this command to install the panel:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/Jas-SinghFSU/HyprPanel.git && \
|
git clone https://github.com/Jas-SinghFSU/HyprPanel.git && \
|
||||||
ln -s $(pwd)/HyprPanel $HOME/.config/ags
|
ln -s $(pwd)/HyprPanel $HOME/.config/ags
|
||||||
```
|
```
|
||||||
|
|
||||||
### Nerd Fonts
|
### Nerd Fonts
|
||||||
|
|
||||||
Additionally, you need to ensure that you have a [Nerd Font](https://www.nerdfonts.com/font-downloads) installed for your icons to render properly.
|
Additionally, you need to ensure that you have a [Nerd Font](https://www.nerdfonts.com/font-downloads) installed for your icons to render properly.
|
||||||
|
|
||||||
### Launch the panel
|
### Launch the panel
|
||||||
|
|
||||||
Afterwards you can run the panel with the following command in your terminal:
|
Afterwards you can run the panel with the following command in your terminal:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ags
|
ags
|
||||||
```
|
```
|
||||||
|
|
||||||
Or you can add it to your Hyprland config (hyprland.conf) to auto-start with:
|
Or you can add it to your Hyprland config (hyprland.conf) to auto-start with:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
exec-once = ags
|
exec-once = ags
|
||||||
```
|
```
|
||||||
|
|
||||||
### NixOS & Home-Manager
|
### NixOS & Home-Manager
|
||||||
|
|
||||||
Alternatively, if you're using NixOS and/or Home-Manager, you can setup AGS using the provided Nix Flake. First, add the repository to your Flake's inputs, and enable the overlay.
|
Alternatively, if you're using NixOS and/or Home-Manager, you can setup AGS using the provided Nix Flake. First, add the repository to your Flake's inputs, and enable the overlay.
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
# flake.nix
|
# flake.nix
|
||||||
|
|
||||||
@@ -105,7 +124,7 @@ Alternatively, if you're using NixOS and/or Home-Manager, you can setup AGS usin
|
|||||||
inputs.hyprpanel.url = "github:Jas-SinghFSU/HyprPanel";
|
inputs.hyprpanel.url = "github:Jas-SinghFSU/HyprPanel";
|
||||||
# ...
|
# ...
|
||||||
|
|
||||||
outputs = { self, nixpkgs, ... }@inputs:
|
outputs = { self, nixpkgs, ... }@inputs:
|
||||||
let
|
let
|
||||||
# ...
|
# ...
|
||||||
system = "x86_64-linux"; # change to whatever your system should be.
|
system = "x86_64-linux"; # change to whatever your system should be.
|
||||||
@@ -175,6 +194,7 @@ The panel is automatically scaled based on your font size in `Configuration > Ge
|
|||||||
### Specifying bar layouts per monitor
|
### Specifying bar layouts per monitor
|
||||||
|
|
||||||
To specify layouts for each monitor you can create a JSON object such as:
|
To specify layouts for each monitor you can create a JSON object such as:
|
||||||
|
|
||||||
```JSON
|
```JSON
|
||||||
{
|
{
|
||||||
"0": {
|
"0": {
|
||||||
@@ -229,19 +249,21 @@ To specify layouts for each monitor you can create a JSON object such as:
|
|||||||
```
|
```
|
||||||
|
|
||||||
Where each monitor is defined by its index (0, 1, 2 in this case) and each section (left, middle, right) contains one or more of the following modules:
|
Where each monitor is defined by its index (0, 1, 2 in this case) and each section (left, middle, right) contains one or more of the following modules:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
"battery"
|
'battery';
|
||||||
"dashboard"
|
'dashboard';
|
||||||
"workspaces"
|
'workspaces';
|
||||||
"windowtitle"
|
'windowtitle';
|
||||||
"media"
|
'media';
|
||||||
"notifications"
|
'notifications';
|
||||||
"volume"
|
'volume';
|
||||||
"network"
|
'network';
|
||||||
"bluetooth"
|
'bluetooth';
|
||||||
"clock"
|
'clock';
|
||||||
"systray"
|
'systray';
|
||||||
```
|
```
|
||||||
|
|
||||||
Since the text-box in the options dialog isn't sufficient, it is recommended that you create this JSON configuration in a text editor elsewhere and paste it into the layout text-box under Configuration > Bar > "Bar Layouts for Monitors".
|
Since the text-box in the options dialog isn't sufficient, it is recommended that you create this JSON configuration in a text editor elsewhere and paste it into the layout text-box under Configuration > Bar > "Bar Layouts for Monitors".
|
||||||
|
|
||||||
### Additional Configuration
|
### Additional Configuration
|
||||||
|
|||||||
142
lib/constants/colors.ts
Normal file
142
lib/constants/colors.ts
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
export const namedColors = new Set([
|
||||||
|
'alice blue',
|
||||||
|
'antique white',
|
||||||
|
'aqua',
|
||||||
|
'aquamarine',
|
||||||
|
'azure',
|
||||||
|
'beige',
|
||||||
|
'bisque',
|
||||||
|
'black',
|
||||||
|
'blanched almond',
|
||||||
|
'blue',
|
||||||
|
'blue violet',
|
||||||
|
'brown',
|
||||||
|
'burlywood',
|
||||||
|
'cadet blue',
|
||||||
|
'chartreuse',
|
||||||
|
'chocolate',
|
||||||
|
'coral',
|
||||||
|
'cornflower blue',
|
||||||
|
'cornsilk',
|
||||||
|
'crimson',
|
||||||
|
'cyan',
|
||||||
|
'dark blue',
|
||||||
|
'dark cyan',
|
||||||
|
'dark goldenrod',
|
||||||
|
'dark gray',
|
||||||
|
'dark green',
|
||||||
|
'dark khaki',
|
||||||
|
'dark magenta',
|
||||||
|
'dark olive green',
|
||||||
|
'dark orange',
|
||||||
|
'dark orchid',
|
||||||
|
'dark red',
|
||||||
|
'dark salmon',
|
||||||
|
'dark sea green',
|
||||||
|
'dark slate blue',
|
||||||
|
'dark slate gray',
|
||||||
|
'dark turquoise',
|
||||||
|
'dark violet',
|
||||||
|
'deep pink',
|
||||||
|
'deep sky blue',
|
||||||
|
'dim gray',
|
||||||
|
'dodger blue',
|
||||||
|
'firebrick',
|
||||||
|
'floral white',
|
||||||
|
'forest green',
|
||||||
|
'fuchsia',
|
||||||
|
'gainsboro',
|
||||||
|
'ghost white',
|
||||||
|
'gold',
|
||||||
|
'goldenrod',
|
||||||
|
'gray',
|
||||||
|
'green',
|
||||||
|
'green yellow',
|
||||||
|
'honeydew',
|
||||||
|
'hot pink',
|
||||||
|
'indian red',
|
||||||
|
'indigo',
|
||||||
|
'ivory',
|
||||||
|
'khaki',
|
||||||
|
'lavender',
|
||||||
|
'lavender blush',
|
||||||
|
'lawn green',
|
||||||
|
'lemon chiffon',
|
||||||
|
'light blue',
|
||||||
|
'light coral',
|
||||||
|
'light cyan',
|
||||||
|
'light goldenrod yellow',
|
||||||
|
'light green',
|
||||||
|
'light grey',
|
||||||
|
'light pink',
|
||||||
|
'light salmon',
|
||||||
|
'light sea green',
|
||||||
|
'light sky blue',
|
||||||
|
'light slate gray',
|
||||||
|
'light steel blue',
|
||||||
|
'light yellow',
|
||||||
|
'lime',
|
||||||
|
'lime green',
|
||||||
|
'linen',
|
||||||
|
'magenta',
|
||||||
|
'maroon',
|
||||||
|
'medium aquamarine',
|
||||||
|
'medium blue',
|
||||||
|
'medium orchid',
|
||||||
|
'medium purple',
|
||||||
|
'medium sea green',
|
||||||
|
'medium slate blue',
|
||||||
|
'medium spring green',
|
||||||
|
'medium turquoise',
|
||||||
|
'medium violet red',
|
||||||
|
'midnight blue',
|
||||||
|
'mint cream',
|
||||||
|
'misty rose',
|
||||||
|
'moccasin',
|
||||||
|
'navajo white',
|
||||||
|
'navy',
|
||||||
|
'old lace',
|
||||||
|
'olive',
|
||||||
|
'olive drab',
|
||||||
|
'orange',
|
||||||
|
'orange red',
|
||||||
|
'orchid',
|
||||||
|
'pale goldenrod',
|
||||||
|
'pale green',
|
||||||
|
'pale turquoise',
|
||||||
|
'pale violet red',
|
||||||
|
'papaya whip',
|
||||||
|
'peach puff',
|
||||||
|
'peru',
|
||||||
|
'pink',
|
||||||
|
'plum',
|
||||||
|
'powder blue',
|
||||||
|
'purple',
|
||||||
|
'red',
|
||||||
|
'rosy brown',
|
||||||
|
'royal blue',
|
||||||
|
'saddle brown',
|
||||||
|
'salmon',
|
||||||
|
'sandy brown',
|
||||||
|
'sea green',
|
||||||
|
'seashell',
|
||||||
|
'sienna',
|
||||||
|
'silver',
|
||||||
|
'sky blue',
|
||||||
|
'slate blue',
|
||||||
|
'slate gray',
|
||||||
|
'snow',
|
||||||
|
'spring green',
|
||||||
|
'steel blue',
|
||||||
|
'tan',
|
||||||
|
'teal',
|
||||||
|
'thistle',
|
||||||
|
'tomato',
|
||||||
|
'turquoise',
|
||||||
|
'violet',
|
||||||
|
'wheat',
|
||||||
|
'white',
|
||||||
|
'white smoke',
|
||||||
|
'yellow',
|
||||||
|
'yellow green',
|
||||||
|
]);
|
||||||
13
lib/types/workspace.d.ts
vendored
13
lib/types/workspace.d.ts
vendored
@@ -10,3 +10,16 @@ export type WorkspaceMap = {
|
|||||||
export type MonitorMap = {
|
export type MonitorMap = {
|
||||||
[key: number]: string;
|
[key: number]: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type WorkspaceIcons = {
|
||||||
|
[key: string]: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type WorkspaceIconsColored = {
|
||||||
|
[key: string]: {
|
||||||
|
color: string;
|
||||||
|
icon: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type WorkspaceIconMap = WorkspaceIcons | WorkspaceIconsColored;
|
||||||
|
|||||||
23
lib/utils.ts
23
lib/utils.ts
@@ -10,6 +10,7 @@ import GdkPixbuf from 'gi://GdkPixbuf';
|
|||||||
import { NotificationArgs } from 'types/utils/notify';
|
import { NotificationArgs } from 'types/utils/notify';
|
||||||
import { SubstituteKeys } from './types/utils';
|
import { SubstituteKeys } from './types/utils';
|
||||||
import { Window } from 'types/@girs/gtk-3.0/gtk-3.0.cjs';
|
import { Window } from 'types/@girs/gtk-3.0/gtk-3.0.cjs';
|
||||||
|
import { namedColors } from './constants/colors';
|
||||||
|
|
||||||
export type Binding<T> = import('types/service').Binding<any, any, T>;
|
export type Binding<T> = import('types/service').Binding<any, any, T>;
|
||||||
|
|
||||||
@@ -166,3 +167,25 @@ export function getPosition(pos: NotificationAnchor | OSDAnchor): ('top' | 'bott
|
|||||||
|
|
||||||
return positionMap[pos] || ['top'];
|
return positionMap[pos] || ['top'];
|
||||||
}
|
}
|
||||||
|
export const isValidGjsColor = (color: string): boolean => {
|
||||||
|
const colorLower = color.toLowerCase().trim();
|
||||||
|
|
||||||
|
if (namedColors.has(colorLower)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const hexColorRegex = /^#(?:[a-fA-F0-9]{3,4}|[a-fA-F0-9]{6,8})$/;
|
||||||
|
|
||||||
|
const rgbRegex = /^rgb\(\s*(\d{1,3}%?\s*,\s*){2}\d{1,3}%?\s*\)$/;
|
||||||
|
const rgbaRegex = /^rgba\(\s*(\d{1,3}%?\s*,\s*){3}(0|1|0?\.\d+)\s*\)$/;
|
||||||
|
|
||||||
|
if (hexColorRegex.test(color)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rgbRegex.test(colorLower) || rgbaRegex.test(colorLower)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,20 +1,10 @@
|
|||||||
const hyprland = await Service.import('hyprland');
|
|
||||||
import options from 'options';
|
import options from 'options';
|
||||||
import {
|
import { createThrottledScrollHandlers, getCurrentMonitorWorkspaces } from './helpers';
|
||||||
createThrottledScrollHandlers,
|
|
||||||
getCurrentMonitorWorkspaces,
|
|
||||||
getWorkspaceRules,
|
|
||||||
getWorkspacesForMonitor,
|
|
||||||
} from './helpers';
|
|
||||||
import { Workspace } from 'types/service/hyprland';
|
|
||||||
import { BoxWidget } from 'lib/types/widget';
|
|
||||||
import { BarBoxChild, SelfButton } from 'lib/types/bar';
|
import { BarBoxChild, SelfButton } from 'lib/types/bar';
|
||||||
|
import { occupiedWses } from './variants/occupied';
|
||||||
|
import { defaultWses } from './variants/default';
|
||||||
|
|
||||||
const { workspaces, monitorSpecific, workspaceMask, scroll_speed, spacing } = options.bar.workspaces;
|
const { workspaces, scroll_speed } = options.bar.workspaces;
|
||||||
|
|
||||||
function range(length: number, start = 1): number[] {
|
|
||||||
return Array.from({ length }, (_, i) => i + start);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Workspaces = (monitor = -1): BarBoxChild => {
|
const Workspaces = (monitor = -1): BarBoxChild => {
|
||||||
const currentMonitorWorkspaces = Variable(getCurrentMonitorWorkspaces(monitor));
|
const currentMonitorWorkspaces = Variable(getCurrentMonitorWorkspaces(monitor));
|
||||||
@@ -23,249 +13,12 @@ const Workspaces = (monitor = -1): BarBoxChild => {
|
|||||||
currentMonitorWorkspaces.value = getCurrentMonitorWorkspaces(monitor);
|
currentMonitorWorkspaces.value = getCurrentMonitorWorkspaces(monitor);
|
||||||
});
|
});
|
||||||
|
|
||||||
const renderClassnames = (
|
|
||||||
showIcons: boolean,
|
|
||||||
showNumbered: boolean,
|
|
||||||
numberedActiveIndicator: string,
|
|
||||||
i: number,
|
|
||||||
): string => {
|
|
||||||
if (showIcons) {
|
|
||||||
return `workspace-icon txt-icon bar`;
|
|
||||||
}
|
|
||||||
if (showNumbered) {
|
|
||||||
const numActiveInd = hyprland.active.workspace.id === i ? numberedActiveIndicator : '';
|
|
||||||
|
|
||||||
return `workspace-number can_${numberedActiveIndicator} ${numActiveInd}`;
|
|
||||||
}
|
|
||||||
return 'default';
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderLabel = (
|
|
||||||
showIcons: boolean,
|
|
||||||
available: string,
|
|
||||||
active: string,
|
|
||||||
occupied: string,
|
|
||||||
workspaceMask: boolean,
|
|
||||||
i: number,
|
|
||||||
index: number,
|
|
||||||
): string => {
|
|
||||||
if (showIcons) {
|
|
||||||
if (hyprland.active.workspace.id === i) {
|
|
||||||
return active;
|
|
||||||
}
|
|
||||||
if ((hyprland.getWorkspace(i)?.windows || 0) > 0) {
|
|
||||||
return occupied;
|
|
||||||
}
|
|
||||||
if (monitor !== -1) {
|
|
||||||
return available;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return workspaceMask ? `${index + 1}` : `${i}`;
|
|
||||||
};
|
|
||||||
const defaultWses = (): BoxWidget => {
|
|
||||||
return Widget.Box({
|
|
||||||
children: Utils.merge(
|
|
||||||
[workspaces.bind('value'), monitorSpecific.bind()],
|
|
||||||
(workspaces: number, monitorSpecific: boolean) => {
|
|
||||||
return range(workspaces || 8)
|
|
||||||
.filter((i) => {
|
|
||||||
if (!monitorSpecific) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
const workspaceRules = getWorkspaceRules();
|
|
||||||
return getWorkspacesForMonitor(i, workspaceRules, monitor);
|
|
||||||
})
|
|
||||||
.sort((a, b) => {
|
|
||||||
return a - b;
|
|
||||||
})
|
|
||||||
.map((i, index) => {
|
|
||||||
return Widget.Button({
|
|
||||||
class_name: 'workspace-button',
|
|
||||||
on_primary_click: () => {
|
|
||||||
hyprland.messageAsync(`dispatch workspace ${i}`);
|
|
||||||
},
|
|
||||||
child: Widget.Label({
|
|
||||||
attribute: i,
|
|
||||||
vpack: 'center',
|
|
||||||
css: spacing.bind('value').as((sp) => `margin: 0rem ${0.375 * sp}rem;`),
|
|
||||||
class_name: Utils.merge(
|
|
||||||
[
|
|
||||||
options.bar.workspaces.show_icons.bind('value'),
|
|
||||||
options.bar.workspaces.show_numbered.bind('value'),
|
|
||||||
options.bar.workspaces.numbered_active_indicator.bind('value'),
|
|
||||||
options.bar.workspaces.icons.available.bind('value'),
|
|
||||||
options.bar.workspaces.icons.active.bind('value'),
|
|
||||||
options.bar.workspaces.icons.occupied.bind('value'),
|
|
||||||
hyprland.active.workspace.bind('id'),
|
|
||||||
],
|
|
||||||
(
|
|
||||||
showIcons: boolean,
|
|
||||||
showNumbered: boolean,
|
|
||||||
numberedActiveIndicator: string,
|
|
||||||
) => {
|
|
||||||
if (showIcons) {
|
|
||||||
return `workspace-icon txt-icon bar`;
|
|
||||||
}
|
|
||||||
if (showNumbered) {
|
|
||||||
const numActiveInd =
|
|
||||||
hyprland.active.workspace.id === i ? numberedActiveIndicator : '';
|
|
||||||
|
|
||||||
return `workspace-number can_${numberedActiveIndicator} ${numActiveInd}`;
|
|
||||||
}
|
|
||||||
return 'default';
|
|
||||||
},
|
|
||||||
),
|
|
||||||
label: Utils.merge(
|
|
||||||
[
|
|
||||||
options.bar.workspaces.show_icons.bind('value'),
|
|
||||||
options.bar.workspaces.icons.available.bind('value'),
|
|
||||||
options.bar.workspaces.icons.active.bind('value'),
|
|
||||||
options.bar.workspaces.icons.occupied.bind('value'),
|
|
||||||
workspaceMask.bind('value'),
|
|
||||||
hyprland.active.workspace.bind('id'),
|
|
||||||
],
|
|
||||||
(
|
|
||||||
showIcons: boolean,
|
|
||||||
available: string,
|
|
||||||
active: string,
|
|
||||||
occupied: string,
|
|
||||||
workspaceMask: boolean,
|
|
||||||
) => {
|
|
||||||
if (showIcons) {
|
|
||||||
if (hyprland.active.workspace.id === i) {
|
|
||||||
return active;
|
|
||||||
}
|
|
||||||
if ((hyprland.getWorkspace(i)?.windows || 0) > 0) {
|
|
||||||
return occupied;
|
|
||||||
}
|
|
||||||
if (monitor !== -1) {
|
|
||||||
return available;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return workspaceMask ? `${index + 1}` : `${i}`;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
setup: (self) => {
|
|
||||||
self.hook(hyprland, () => {
|
|
||||||
self.toggleClassName('active', hyprland.active.workspace.id === i);
|
|
||||||
self.toggleClassName(
|
|
||||||
'occupied',
|
|
||||||
(hyprland.getWorkspace(i)?.windows || 0) > 0,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
const occupiedWses = (): BoxWidget => {
|
|
||||||
return Widget.Box({
|
|
||||||
children: Utils.merge(
|
|
||||||
[
|
|
||||||
monitorSpecific.bind('value'),
|
|
||||||
hyprland.bind('workspaces'),
|
|
||||||
workspaceMask.bind('value'),
|
|
||||||
workspaces.bind('value'),
|
|
||||||
options.bar.workspaces.show_icons.bind('value'),
|
|
||||||
options.bar.workspaces.icons.available.bind('value'),
|
|
||||||
options.bar.workspaces.icons.active.bind('value'),
|
|
||||||
options.bar.workspaces.icons.occupied.bind('value'),
|
|
||||||
options.bar.workspaces.show_numbered.bind('value'),
|
|
||||||
options.bar.workspaces.numbered_active_indicator.bind('value'),
|
|
||||||
spacing.bind('value'),
|
|
||||||
hyprland.active.workspace.bind('id'),
|
|
||||||
],
|
|
||||||
(
|
|
||||||
monitorSpecific: boolean,
|
|
||||||
wkSpaces: Workspace[],
|
|
||||||
workspaceMask: boolean,
|
|
||||||
totalWkspcs: number,
|
|
||||||
showIcons: boolean,
|
|
||||||
available: string,
|
|
||||||
active: string,
|
|
||||||
occupied: string,
|
|
||||||
showNumbered: boolean,
|
|
||||||
numberedActiveIndicator: string,
|
|
||||||
spacing: number,
|
|
||||||
activeId: number,
|
|
||||||
) => {
|
|
||||||
let allWkspcs = range(totalWkspcs || 8);
|
|
||||||
|
|
||||||
const activeWorkspaces = wkSpaces.map((w) => w.id);
|
|
||||||
const workspaceRules = getWorkspaceRules();
|
|
||||||
|
|
||||||
// Sometimes hyprland doesn't have all the monitors in the list
|
|
||||||
// so we complement it with monitors from the workspace list
|
|
||||||
const workspaceMonitorList = hyprland?.workspaces?.map((m) => ({
|
|
||||||
id: m.monitorID,
|
|
||||||
name: m.monitor,
|
|
||||||
}));
|
|
||||||
const curMonitor =
|
|
||||||
hyprland.monitors.find((m) => m.id === monitor) ||
|
|
||||||
workspaceMonitorList.find((m) => m.id === monitor);
|
|
||||||
|
|
||||||
// go through each key in workspaceRules and flatten the array
|
|
||||||
const workspacesWithRules = Object.keys(workspaceRules).reduce((acc: number[], k: string) => {
|
|
||||||
return [...acc, ...workspaceRules[k]];
|
|
||||||
}, [] as number[]);
|
|
||||||
|
|
||||||
const activesForMonitor = activeWorkspaces.filter((w) => {
|
|
||||||
if (
|
|
||||||
curMonitor &&
|
|
||||||
Object.hasOwnProperty.call(workspaceRules, curMonitor.name) &&
|
|
||||||
workspacesWithRules.includes(w)
|
|
||||||
) {
|
|
||||||
return workspaceRules[curMonitor.name].includes(w);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (monitorSpecific) {
|
|
||||||
const wrkspcsInRange = range(totalWkspcs).filter((w) => {
|
|
||||||
return getWorkspacesForMonitor(w, workspaceRules, monitor);
|
|
||||||
});
|
|
||||||
allWkspcs = [...new Set([...activesForMonitor, ...wrkspcsInRange])];
|
|
||||||
} else {
|
|
||||||
allWkspcs = [...new Set([...allWkspcs, ...activeWorkspaces])];
|
|
||||||
}
|
|
||||||
|
|
||||||
return allWkspcs
|
|
||||||
.sort((a, b) => {
|
|
||||||
return a - b;
|
|
||||||
})
|
|
||||||
.map((i, index) => {
|
|
||||||
return Widget.Button({
|
|
||||||
class_name: 'workspace-button',
|
|
||||||
on_primary_click: () => {
|
|
||||||
hyprland.messageAsync(`dispatch workspace ${i}`);
|
|
||||||
},
|
|
||||||
child: Widget.Label({
|
|
||||||
attribute: i,
|
|
||||||
vpack: 'center',
|
|
||||||
css: `margin: 0rem ${0.375 * spacing}rem;`,
|
|
||||||
class_name: renderClassnames(showIcons, showNumbered, numberedActiveIndicator, i),
|
|
||||||
label: renderLabel(showIcons, available, active, occupied, workspaceMask, i, index),
|
|
||||||
setup: (self) => {
|
|
||||||
self.toggleClassName('active', activeId === i);
|
|
||||||
self.toggleClassName('occupied', (hyprland.getWorkspace(i)?.windows || 0) > 0);
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
component: Widget.Box({
|
component: Widget.Box({
|
||||||
class_name: 'workspaces',
|
class_name: 'workspaces',
|
||||||
child: options.bar.workspaces.hideUnoccupied
|
child: options.bar.workspaces.hideUnoccupied
|
||||||
.bind('value')
|
.bind('value')
|
||||||
.as((hideUnoccupied) => (hideUnoccupied ? occupiedWses() : defaultWses())),
|
.as((hideUnoccupied) => (hideUnoccupied ? occupiedWses(monitor) : defaultWses(monitor))),
|
||||||
}),
|
}),
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
boxClass: 'workspaces',
|
boxClass: 'workspaces',
|
||||||
|
|||||||
@@ -1,18 +1,60 @@
|
|||||||
|
import { WorkspaceIconMap } from 'lib/types/workspace';
|
||||||
|
import { isValidGjsColor } from 'lib/utils';
|
||||||
|
|
||||||
const hyprland = await Service.import('hyprland');
|
const hyprland = await Service.import('hyprland');
|
||||||
|
|
||||||
|
const getWsIcon = (wsIconMap: WorkspaceIconMap, i: number): string => {
|
||||||
|
const iconEntry = wsIconMap[i];
|
||||||
|
|
||||||
|
if (!iconEntry) {
|
||||||
|
return `${i}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasIcon = typeof iconEntry === 'object' && 'icon' in iconEntry && iconEntry.icon !== '';
|
||||||
|
|
||||||
|
if (typeof iconEntry === 'string' && iconEntry !== '') {
|
||||||
|
return iconEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasIcon) {
|
||||||
|
return iconEntry.icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${i}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getWsColor = (wsIconMap: WorkspaceIconMap, i: number): string => {
|
||||||
|
const iconEntry = wsIconMap[i];
|
||||||
|
if (!iconEntry) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasColor = typeof iconEntry === 'object' && 'color' in iconEntry && iconEntry.color !== '';
|
||||||
|
if (hasColor && isValidGjsColor(iconEntry.color)) {
|
||||||
|
return `color: ${iconEntry.color}; border-bottom-color: ${iconEntry.color};`;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
|
||||||
export const renderClassnames = (
|
export const renderClassnames = (
|
||||||
showIcons: boolean,
|
showIcons: boolean,
|
||||||
showNumbered: boolean,
|
showNumbered: boolean,
|
||||||
numberedActiveIndicator: string,
|
numberedActiveIndicator: string,
|
||||||
|
showWsIcons: boolean,
|
||||||
i: number,
|
i: number,
|
||||||
): string => {
|
): string => {
|
||||||
if (showIcons) {
|
if (showIcons) {
|
||||||
return `workspace-icon txt-icon bar`;
|
return `workspace-icon txt-icon bar`;
|
||||||
}
|
}
|
||||||
if (showNumbered) {
|
if (showNumbered || showWsIcons) {
|
||||||
const numActiveInd = hyprland.active.workspace.id === i ? numberedActiveIndicator : '';
|
const numActiveInd = hyprland.active.workspace.id === i ? `${numberedActiveIndicator}` : '';
|
||||||
|
|
||||||
return `workspace-number can_${numberedActiveIndicator} ${numActiveInd}`;
|
const className =
|
||||||
|
`workspace-number can_${numberedActiveIndicator} ` +
|
||||||
|
`${numActiveInd} ` +
|
||||||
|
`${showWsIcons ? 'txt-icon' : ''}`;
|
||||||
|
|
||||||
|
return className;
|
||||||
}
|
}
|
||||||
return 'default';
|
return 'default';
|
||||||
};
|
};
|
||||||
@@ -23,6 +65,8 @@ export const renderLabel = (
|
|||||||
active: string,
|
active: string,
|
||||||
occupied: string,
|
occupied: string,
|
||||||
workspaceMask: boolean,
|
workspaceMask: boolean,
|
||||||
|
showWsIcons: boolean,
|
||||||
|
wsIconMap: WorkspaceIconMap,
|
||||||
i: number,
|
i: number,
|
||||||
index: number,
|
index: number,
|
||||||
monitor: number,
|
monitor: number,
|
||||||
@@ -38,6 +82,8 @@ export const renderLabel = (
|
|||||||
return available;
|
return available;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (showWsIcons) {
|
||||||
|
return getWsIcon(wsIconMap, i);
|
||||||
|
}
|
||||||
return workspaceMask ? `${index + 1}` : `${i}`;
|
return workspaceMask ? `${index + 1}` : `${i}`;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import options from 'options';
|
|||||||
import { getWorkspaceRules, getWorkspacesForMonitor } from '../helpers';
|
import { getWorkspaceRules, getWorkspacesForMonitor } from '../helpers';
|
||||||
import { range } from 'lib/utils';
|
import { range } from 'lib/utils';
|
||||||
import { BoxWidget } from 'lib/types/widget';
|
import { BoxWidget } from 'lib/types/widget';
|
||||||
|
import { getWsColor, renderClassnames, renderLabel } from '../utils';
|
||||||
|
import { WorkspaceIconMap } from 'lib/types/workspace';
|
||||||
|
|
||||||
const { workspaces, monitorSpecific, workspaceMask, spacing } = options.bar.workspaces;
|
const { workspaces, monitorSpecific, workspaceMask, spacing } = options.bar.workspaces;
|
||||||
export const defaultWses = (monitor: number): BoxWidget => {
|
export const defaultWses = (monitor: number): BoxWidget => {
|
||||||
@@ -30,28 +32,48 @@ export const defaultWses = (monitor: number): BoxWidget => {
|
|||||||
child: Widget.Label({
|
child: Widget.Label({
|
||||||
attribute: i,
|
attribute: i,
|
||||||
vpack: 'center',
|
vpack: 'center',
|
||||||
css: spacing.bind('value').as((sp) => `margin: 0rem ${0.375 * sp}rem;`),
|
css: Utils.merge(
|
||||||
|
[
|
||||||
|
spacing.bind('value'),
|
||||||
|
options.bar.workspaces.showWsIcons.bind('value'),
|
||||||
|
options.bar.workspaces.workspaceIconMap.bind('value'),
|
||||||
|
options.theme.matugen.bind('value'),
|
||||||
|
],
|
||||||
|
(
|
||||||
|
sp: number,
|
||||||
|
showWsIcons: boolean,
|
||||||
|
workspaceIconMap: WorkspaceIconMap,
|
||||||
|
matugen: boolean,
|
||||||
|
) => {
|
||||||
|
return (
|
||||||
|
`margin: 0rem ${0.375 * sp}rem;` +
|
||||||
|
`${showWsIcons && !matugen ? getWsColor(workspaceIconMap, i) : ''}`
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
class_name: Utils.merge(
|
class_name: Utils.merge(
|
||||||
[
|
[
|
||||||
options.bar.workspaces.show_icons.bind('value'),
|
options.bar.workspaces.show_icons.bind('value'),
|
||||||
options.bar.workspaces.show_numbered.bind('value'),
|
options.bar.workspaces.show_numbered.bind('value'),
|
||||||
options.bar.workspaces.numbered_active_indicator.bind('value'),
|
options.bar.workspaces.numbered_active_indicator.bind('value'),
|
||||||
|
options.bar.workspaces.showWsIcons.bind('value'),
|
||||||
options.bar.workspaces.icons.available.bind('value'),
|
options.bar.workspaces.icons.available.bind('value'),
|
||||||
options.bar.workspaces.icons.active.bind('value'),
|
options.bar.workspaces.icons.active.bind('value'),
|
||||||
options.bar.workspaces.icons.occupied.bind('value'),
|
|
||||||
hyprland.active.workspace.bind('id'),
|
hyprland.active.workspace.bind('id'),
|
||||||
],
|
],
|
||||||
(showIcons: boolean, showNumbered: boolean, numberedActiveIndicator: string) => {
|
(
|
||||||
if (showIcons) {
|
showIcons: boolean,
|
||||||
return `workspace-icon txt-icon bar`;
|
showNumbered: boolean,
|
||||||
}
|
numberedActiveIndicator: string,
|
||||||
if (showNumbered) {
|
showWsIcons: boolean,
|
||||||
const numActiveInd =
|
) => {
|
||||||
hyprland.active.workspace.id === i ? numberedActiveIndicator : '';
|
return renderClassnames(
|
||||||
|
showIcons,
|
||||||
return `workspace-number can_${numberedActiveIndicator} ${numActiveInd}`;
|
showNumbered,
|
||||||
}
|
numberedActiveIndicator,
|
||||||
return 'default';
|
showWsIcons,
|
||||||
|
i,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
label: Utils.merge(
|
label: Utils.merge(
|
||||||
@@ -60,6 +82,8 @@ export const defaultWses = (monitor: number): BoxWidget => {
|
|||||||
options.bar.workspaces.icons.available.bind('value'),
|
options.bar.workspaces.icons.available.bind('value'),
|
||||||
options.bar.workspaces.icons.active.bind('value'),
|
options.bar.workspaces.icons.active.bind('value'),
|
||||||
options.bar.workspaces.icons.occupied.bind('value'),
|
options.bar.workspaces.icons.occupied.bind('value'),
|
||||||
|
options.bar.workspaces.workspaceIconMap.bind('value'),
|
||||||
|
options.bar.workspaces.showWsIcons.bind('value'),
|
||||||
workspaceMask.bind('value'),
|
workspaceMask.bind('value'),
|
||||||
hyprland.active.workspace.bind('id'),
|
hyprland.active.workspace.bind('id'),
|
||||||
],
|
],
|
||||||
@@ -68,20 +92,22 @@ export const defaultWses = (monitor: number): BoxWidget => {
|
|||||||
available: string,
|
available: string,
|
||||||
active: string,
|
active: string,
|
||||||
occupied: string,
|
occupied: string,
|
||||||
|
wsIconMap: WorkspaceIconMap,
|
||||||
|
showWsIcons: boolean,
|
||||||
workspaceMask: boolean,
|
workspaceMask: boolean,
|
||||||
) => {
|
) => {
|
||||||
if (showIcons) {
|
return renderLabel(
|
||||||
if (hyprland.active.workspace.id === i) {
|
showIcons,
|
||||||
return active;
|
available,
|
||||||
}
|
active,
|
||||||
if ((hyprland.getWorkspace(i)?.windows || 0) > 0) {
|
occupied,
|
||||||
return occupied;
|
workspaceMask,
|
||||||
}
|
showWsIcons,
|
||||||
if (monitor !== -1) {
|
wsIconMap,
|
||||||
return available;
|
i,
|
||||||
}
|
index,
|
||||||
}
|
monitor,
|
||||||
return workspaceMask ? `${index + 1}` : `${i}`;
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
setup: (self) => {
|
setup: (self) => {
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ const hyprland = await Service.import('hyprland');
|
|||||||
import options from 'options';
|
import options from 'options';
|
||||||
import { getWorkspaceRules, getWorkspacesForMonitor } from '../helpers';
|
import { getWorkspaceRules, getWorkspacesForMonitor } from '../helpers';
|
||||||
import { Workspace } from 'types/service/hyprland';
|
import { Workspace } from 'types/service/hyprland';
|
||||||
import { renderClassnames, renderLabel } from '../utils';
|
import { getWsColor, renderClassnames, renderLabel } from '../utils';
|
||||||
import { range } from 'lib/utils';
|
import { range } from 'lib/utils';
|
||||||
import { BoxWidget } from 'lib/types/widget';
|
import { BoxWidget } from 'lib/types/widget';
|
||||||
|
import { WorkspaceIconMap } from 'lib/types/workspace';
|
||||||
|
|
||||||
const { workspaces, monitorSpecific, workspaceMask, spacing } = options.bar.workspaces;
|
const { workspaces, monitorSpecific, workspaceMask, spacing } = options.bar.workspaces;
|
||||||
|
|
||||||
@@ -24,6 +25,9 @@ export const occupiedWses = (monitor: number): BoxWidget => {
|
|||||||
options.bar.workspaces.numbered_active_indicator.bind('value'),
|
options.bar.workspaces.numbered_active_indicator.bind('value'),
|
||||||
spacing.bind('value'),
|
spacing.bind('value'),
|
||||||
hyprland.active.workspace.bind('id'),
|
hyprland.active.workspace.bind('id'),
|
||||||
|
options.bar.workspaces.workspaceIconMap.bind('value'),
|
||||||
|
options.bar.workspaces.showWsIcons.bind('value'),
|
||||||
|
options.theme.matugen.bind('value'),
|
||||||
],
|
],
|
||||||
(
|
(
|
||||||
monitorSpecific: boolean,
|
monitorSpecific: boolean,
|
||||||
@@ -38,6 +42,9 @@ export const occupiedWses = (monitor: number): BoxWidget => {
|
|||||||
numberedActiveIndicator: string,
|
numberedActiveIndicator: string,
|
||||||
spacing: number,
|
spacing: number,
|
||||||
activeId: number,
|
activeId: number,
|
||||||
|
wsIconMap: WorkspaceIconMap,
|
||||||
|
showWsIcons: boolean,
|
||||||
|
matugen: boolean,
|
||||||
) => {
|
) => {
|
||||||
let allWkspcs = range(totalWkspcs || 8);
|
let allWkspcs = range(totalWkspcs || 8);
|
||||||
|
|
||||||
@@ -46,7 +53,10 @@ export const occupiedWses = (monitor: number): BoxWidget => {
|
|||||||
|
|
||||||
// Sometimes hyprland doesn't have all the monitors in the list
|
// Sometimes hyprland doesn't have all the monitors in the list
|
||||||
// so we complement it with monitors from the workspace list
|
// so we complement it with monitors from the workspace list
|
||||||
const workspaceMonitorList = hyprland?.workspaces?.map((m) => ({ id: m.monitorID, name: m.monitor }));
|
const workspaceMonitorList = hyprland?.workspaces?.map((m) => ({
|
||||||
|
id: m.monitorID,
|
||||||
|
name: m.monitor,
|
||||||
|
}));
|
||||||
const curMonitor =
|
const curMonitor =
|
||||||
hyprland.monitors.find((m) => m.id === monitor) ||
|
hyprland.monitors.find((m) => m.id === monitor) ||
|
||||||
workspaceMonitorList.find((m) => m.id === monitor);
|
workspaceMonitorList.find((m) => m.id === monitor);
|
||||||
@@ -89,14 +99,24 @@ export const occupiedWses = (monitor: number): BoxWidget => {
|
|||||||
child: Widget.Label({
|
child: Widget.Label({
|
||||||
attribute: i,
|
attribute: i,
|
||||||
vpack: 'center',
|
vpack: 'center',
|
||||||
css: `margin: 0rem ${0.375 * spacing}rem;`,
|
css:
|
||||||
class_name: renderClassnames(showIcons, showNumbered, numberedActiveIndicator, i),
|
`margin: 0rem ${0.375 * spacing}rem;` +
|
||||||
|
`${showWsIcons && !matugen ? getWsColor(wsIconMap, i) : ''}`,
|
||||||
|
class_name: renderClassnames(
|
||||||
|
showIcons,
|
||||||
|
showNumbered,
|
||||||
|
numberedActiveIndicator,
|
||||||
|
showWsIcons,
|
||||||
|
i,
|
||||||
|
),
|
||||||
label: renderLabel(
|
label: renderLabel(
|
||||||
showIcons,
|
showIcons,
|
||||||
available,
|
available,
|
||||||
active,
|
active,
|
||||||
occupied,
|
occupied,
|
||||||
workspaceMask,
|
workspaceMask,
|
||||||
|
showWsIcons,
|
||||||
|
wsIconMap,
|
||||||
i,
|
i,
|
||||||
index,
|
index,
|
||||||
monitor,
|
monitor,
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import {
|
|||||||
} from 'lib/types/options';
|
} from 'lib/types/options';
|
||||||
import { MatugenScheme, MatugenTheme, MatugenVariations } from 'lib/types/options';
|
import { MatugenScheme, MatugenTheme, MatugenVariations } from 'lib/types/options';
|
||||||
import { UnitType } from 'lib/types/weather';
|
import { UnitType } from 'lib/types/weather';
|
||||||
|
import { WorkspaceIcons, WorkspaceIconsColored } from 'lib/types/workspace';
|
||||||
|
|
||||||
// WARN: CHANGING THESE VALUES WILL PREVENT MATUGEN COLOR GENERATION FOR THE CHANGED VALUE
|
// WARN: CHANGING THESE VALUES WILL PREVENT MATUGEN COLOR GENERATION FOR THE CHANGED VALUE
|
||||||
export const colors = {
|
export const colors = {
|
||||||
@@ -191,6 +192,7 @@ const options = mkOptions(OPTIONS, {
|
|||||||
numbered_active_highlighted_text_color: opt(colors.mantle),
|
numbered_active_highlighted_text_color: opt(colors.mantle),
|
||||||
numbered_active_underline_color: opt(colors.pink),
|
numbered_active_underline_color: opt(colors.pink),
|
||||||
spacing: opt('0.5em'),
|
spacing: opt('0.5em'),
|
||||||
|
fontSize: opt('1.2em'),
|
||||||
},
|
},
|
||||||
windowtitle: {
|
windowtitle: {
|
||||||
background: opt(colors.base2),
|
background: opt(colors.base2),
|
||||||
@@ -810,12 +812,14 @@ const options = mkOptions(OPTIONS, {
|
|||||||
workspaces: {
|
workspaces: {
|
||||||
show_icons: opt(false),
|
show_icons: opt(false),
|
||||||
show_numbered: opt(false),
|
show_numbered: opt(false),
|
||||||
|
showWsIcons: opt(false),
|
||||||
numbered_active_indicator: opt<ActiveWsIndicator>('underline'),
|
numbered_active_indicator: opt<ActiveWsIndicator>('underline'),
|
||||||
icons: {
|
icons: {
|
||||||
available: opt(''),
|
available: opt(''),
|
||||||
active: opt(''),
|
active: opt(''),
|
||||||
occupied: opt(''),
|
occupied: opt(''),
|
||||||
},
|
},
|
||||||
|
workspaceIconMap: opt<WorkspaceIcons | WorkspaceIconsColored>({}),
|
||||||
workspaces: opt(10),
|
workspaces: opt(10),
|
||||||
spacing: opt(1),
|
spacing: opt(1),
|
||||||
monitorSpecific: opt(true),
|
monitorSpecific: opt(true),
|
||||||
|
|||||||
@@ -1,81 +1,82 @@
|
|||||||
.workspaces {
|
.workspaces {
|
||||||
label {
|
label {
|
||||||
font-size: 0.2em;
|
font-size: 0.2em;
|
||||||
min-width: 4em;
|
min-width: 4em;
|
||||||
min-height: 4em;
|
min-height: 4em;
|
||||||
border-radius: 1.9rem * .6;
|
border-radius: 1.9rem * 0.6;
|
||||||
transition: 300ms * .5;
|
transition: 300ms * 0.5;
|
||||||
background-color: if($bar-buttons-monochrome, $bar-buttons-icon, $bar-buttons-workspaces-available);
|
background-color: if($bar-buttons-monochrome, $bar-buttons-icon, $bar-buttons-workspaces-available);
|
||||||
color: if($bar-buttons-monochrome, $bar-buttons-icon, $bar-buttons-workspaces-available);
|
color: if($bar-buttons-monochrome, $bar-buttons-icon, $bar-buttons-workspaces-available);
|
||||||
|
|
||||||
&.occupied {
|
&.occupied {
|
||||||
background-color: if($bar-buttons-monochrome, $bar-buttons-icon, $bar-buttons-workspaces-occupied);
|
background-color: if($bar-buttons-monochrome, $bar-buttons-icon, $bar-buttons-workspaces-occupied);
|
||||||
color: if($bar-buttons-monochrome, $bar-buttons-icon, $bar-buttons-workspaces-occupied);
|
color: if($bar-buttons-monochrome, $bar-buttons-icon, $bar-buttons-workspaces-occupied);
|
||||||
min-width: 4em;
|
min-width: 4em;
|
||||||
min-height: 4em;
|
min-height: 4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
color: if($bar-buttons-monochrome, $bar-buttons-icon, $bar-buttons-workspaces-active);
|
color: if($bar-buttons-monochrome, $bar-buttons-icon, $bar-buttons-workspaces-active);
|
||||||
background-color: if($bar-buttons-monochrome, $bar-buttons-icon, $bar-buttons-workspaces-active);
|
background-color: if($bar-buttons-monochrome, $bar-buttons-icon, $bar-buttons-workspaces-active);
|
||||||
min-width: 12em;
|
min-width: 12em;
|
||||||
min-height: 4em;
|
min-height: 4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.workspace-icon {
|
&.workspace-icon {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
min-width: 0em;
|
min-width: 0em;
|
||||||
min-height: 0em;
|
min-height: 0em;
|
||||||
border-radius: 0em;
|
border-radius: 0em;
|
||||||
transition: 300ms * .5;
|
transition: 300ms * 0.5;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.workspace-number {
|
&.workspace-number {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
min-width: 0em;
|
min-width: 0em;
|
||||||
min-height: 0em;
|
min-height: 0em;
|
||||||
border-radius: 0em;
|
border-radius: 0em;
|
||||||
transition: 0ms;
|
transition: 0ms;
|
||||||
padding: 0em 0.2em;
|
padding: 0em 0.2em;
|
||||||
font-size: 1.2em;
|
font-size: $bar-buttons-workspaces-fontSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.underline {
|
&.underline {
|
||||||
border-top: 0.1em solid transparent;
|
border-top: 0.1em solid transparent;
|
||||||
border-bottom: 0.1em solid $bar-buttons-workspaces-numbered_active_underline_color;
|
border-bottom: 0.1em solid $bar-buttons-workspaces-numbered_active_underline_color;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.highlight {
|
&.highlight {
|
||||||
color: $bar-buttons-workspaces-numbered_active_highlighted_text_color;
|
color: $bar-buttons-workspaces-numbered_active_highlighted_text_color;
|
||||||
border-radius: $bar-buttons-workspaces-numbered_active_highlight_border;
|
border-radius: $bar-buttons-workspaces-numbered_active_highlight_border;
|
||||||
background-color: $bar-buttons-workspaces-active;
|
background-color: $bar-buttons-workspaces-active;
|
||||||
padding: 0em $bar-buttons-workspaces-numbered_active_highlight_padding;
|
padding: 0em $bar-buttons-workspaces-numbered_active_highlight_padding;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.workspace-button {
|
.workspace-button {
|
||||||
&:hover label {
|
&:hover label {
|
||||||
color: $bar-buttons-workspaces-hover;
|
color: $bar-buttons-workspaces-hover;
|
||||||
|
|
||||||
&.default {
|
&.default {
|
||||||
background-color: $bar-buttons-workspaces-hover;
|
background-color: $bar-buttons-workspaces-hover;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
&:hover .can_underline {
|
&:hover .can_underline {
|
||||||
border-top: 0.1em solid transparent;
|
border-top: 0.1em solid transparent;
|
||||||
border-bottom: 0.1em solid if($bar-buttons-monochrome, $bar-buttons-workspaces-hover, $bar-buttons-workspaces-hover);
|
border-bottom: 0.1em solid
|
||||||
}
|
if($bar-buttons-monochrome, $bar-buttons-workspaces-hover, $bar-buttons-workspaces-hover);
|
||||||
|
}
|
||||||
|
|
||||||
&:hover .can_highlight {
|
&:hover .can_highlight {
|
||||||
background-color: $bar-buttons-workspaces-hover;
|
background-color: $bar-buttons-workspaces-hover;
|
||||||
color: $bar-buttons-workspaces-numbered_active_highlighted_text_color;
|
color: $bar-buttons-workspaces-numbered_active_highlighted_text_color;
|
||||||
border-radius: $bar-buttons-workspaces-numbered_active_highlight_border;
|
border-radius: $bar-buttons-workspaces-numbered_active_highlight_border;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.style2.workspaces {
|
.style2.workspaces {
|
||||||
padding: $bar-buttons-padding_y $bar-buttons-padding_x;
|
padding: $bar-buttons-padding_y $bar-buttons-padding_x;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,6 +136,14 @@ export const BarSettings = (): Scrollable<Gtk.Widget, Gtk.Widget> => {
|
|||||||
******************************
|
******************************
|
||||||
*/
|
*/
|
||||||
Header('Workspaces'),
|
Header('Workspaces'),
|
||||||
|
Option({
|
||||||
|
opt: options.theme.bar.buttons.workspaces.fontSize,
|
||||||
|
title: 'Indicator Size',
|
||||||
|
subtitle:
|
||||||
|
'Only applicable to numbered workspaces and mapped icons\n' +
|
||||||
|
'Adjust with caution as it may cause the bar to expand',
|
||||||
|
type: 'string',
|
||||||
|
}),
|
||||||
Option({
|
Option({
|
||||||
opt: options.bar.workspaces.show_icons,
|
opt: options.bar.workspaces.show_icons,
|
||||||
title: 'Show Workspace Icons',
|
title: 'Show Workspace Icons',
|
||||||
@@ -180,6 +188,16 @@ export const BarSettings = (): Scrollable<Gtk.Widget, Gtk.Widget> => {
|
|||||||
subtitle: 'Only applicable if Workspace Numbers are enabled',
|
subtitle: 'Only applicable if Workspace Numbers are enabled',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
}),
|
}),
|
||||||
|
Option({
|
||||||
|
opt: options.bar.workspaces.showWsIcons,
|
||||||
|
title: 'Map Workspaces to Icons',
|
||||||
|
type: 'boolean',
|
||||||
|
}),
|
||||||
|
Option({
|
||||||
|
opt: options.bar.workspaces.workspaceIconMap,
|
||||||
|
title: 'Workspace Icon Mappings',
|
||||||
|
type: 'object',
|
||||||
|
}),
|
||||||
Option({
|
Option({
|
||||||
opt: options.bar.workspaces.spacing,
|
opt: options.bar.workspaces.spacing,
|
||||||
title: 'Spacing',
|
title: 'Spacing',
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import options from 'options';
|
import options from 'options';
|
||||||
|
|
||||||
const { show_numbered, show_icons } = options.bar.workspaces;
|
const { show_numbered, show_icons, showWsIcons } = options.bar.workspaces;
|
||||||
const { monochrome: monoBar } = options.theme.bar.buttons;
|
const { monochrome: monoBar } = options.theme.bar.buttons;
|
||||||
const { monochrome: monoMenu } = options.theme.bar.menus;
|
const { monochrome: monoMenu } = options.theme.bar.menus;
|
||||||
const { matugen } = options.theme;
|
const { matugen } = options.theme;
|
||||||
@@ -8,12 +8,21 @@ const { matugen } = options.theme;
|
|||||||
show_numbered.connect('changed', ({ value }) => {
|
show_numbered.connect('changed', ({ value }) => {
|
||||||
if (value === true) {
|
if (value === true) {
|
||||||
show_icons.value = false;
|
show_icons.value = false;
|
||||||
|
showWsIcons.value = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
show_icons.connect('changed', ({ value }) => {
|
show_icons.connect('changed', ({ value }) => {
|
||||||
if (value === true) {
|
if (value === true) {
|
||||||
show_numbered.value = false;
|
show_numbered.value = false;
|
||||||
|
showWsIcons.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
showWsIcons.connect('changed', ({ value }) => {
|
||||||
|
if (value === true) {
|
||||||
|
show_numbered.value = false;
|
||||||
|
show_icons.value = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user