mirror of
https://github.com/JakeStanger/ironbar.git
synced 2024-11-21 19:42:48 +03:00
feat: module-level name
and class
options
BREAKING CHANGE: To allow for the `name` property, any widgets that were previously targeted by name should be targeted by class instead. This affects **all modules and all popups**, as well as several widgets inside modules. **This will break a lot of rules in your stylesheet**. To attempt to mitigate the damage, a migration script can be found [here](https://raw.githubusercontent.com/JakeStanger/ironbar/master/scripts/migrate-styles.sh) that should get you most of the way. Resolves #75.
This commit is contained in:
parent
528a8d6dd6
commit
dea66415c2
@ -310,9 +310,12 @@ For information on the `Script` type, and embedding scripts in strings, see [her
|
||||
| `transition_type` | `slide_start` or `slide_end` or `crossfade` or `none` | `slide_start` | The transition animation to use when showing/hiding the widget. |
|
||||
| `transition_duration` | `Integer` | `250` | The length of the transition animation to use when showing/hiding the widget. |
|
||||
|
||||
#### Other
|
||||
#### Appearance
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|-----------|--------------------|---------|-----------------------------------------------------------------------------------|
|
||||
| `tooltip` | `string` | `null` | Shows this text on hover. Supports embedding scripts between `{{double braces}}`. |
|
||||
| `name` | `string` | `null` | Sets the unique widget name, allowing you to style it using `#name`. |
|
||||
| `class` | `string` | `null` | Sets one or more CSS classes, allowing you to style it using `.class`. |
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|-------------------|--------------------|---------|--------------------------------------------------------------------------------------------------------------------|
|
||||
| `tooltip` | `string` | `null` | Shows this text on hover. Supports embedding scripts between `{{double braces}}`. |
|
||||
For more information on styling, please see the [styling guide](styling-guide).
|
@ -4,17 +4,37 @@ To style the bar, create a file at `~/.config/ironbar/style.css`.
|
||||
|
||||
Style changes are hot-loaded so there is no need to reload the bar.
|
||||
|
||||
A reminder: since the bar is GTK-based, it uses GTK's implementation of CSS,
|
||||
Since the bar is GTK-based, it uses [GTK's implementation of CSS](https://docs.gtk.org/gtk3/css-overview.html),
|
||||
which only includes a subset of the full web spec (plus a few non-standard properties).
|
||||
|
||||
The below table describes the selectors provided by the bar itself.
|
||||
Information on styling individual modules can be found on their pages in the sidebar.
|
||||
|
||||
| Selector | Description |
|
||||
|----------------|-------------------------------------------|
|
||||
| `.background` | Top-level window |
|
||||
| `#bar` | Bar root box |
|
||||
| `#bar #start` | Bar left or top modules container box |
|
||||
| `#bar #center` | Bar center modules container box |
|
||||
| `#bar #end` | Bar right or bottom modules container box |
|
||||
| `.container` | All of the above |
|
||||
| Selector | Description |
|
||||
|----------------|--------------------------------------------|
|
||||
| `.background` | Top-level window. |
|
||||
| `#bar` | Bar root box. |
|
||||
| `#bar #start` | Bar left or top modules container box. |
|
||||
| `#bar #center` | Bar center modules container box. |
|
||||
| `#bar #end` | Bar right or bottom modules container box. |
|
||||
| `.container` | All of the above. |
|
||||
| `.popup` | Any popup box. |
|
||||
|
||||
Every widget can be selected using a `kebab-case` class name matching its name.
|
||||
You can also target popups by prefixing `popup-` to the name. For example, you can use `.clock` and `.popup-clock` respectively.
|
||||
|
||||
Setting the `name` option on a widget allows you to target that specific instance using `#name`.
|
||||
You can also add additional classes to re-use styles. In both cases, `popup-` is automatically prefixed to the popup (`#popup-name` or `.popup-my-class`).
|
||||
|
||||
You can also target all GTK widgets of a certain type directly using their name. For example, `button:hover` will select the hover state on *all* buttons.
|
||||
These names are all lower case with no separator, so `MenuBar` -> `menubar`.
|
||||
|
||||
GTK CSS does not support custom properties, but it does have its own custom `@define-color` syntax which you can use for re-using colours:
|
||||
|
||||
```css
|
||||
@define-color color_bg #2d2d2d;
|
||||
|
||||
box, menubar {
|
||||
background-color: @color_bg;
|
||||
}
|
||||
```
|
@ -84,11 +84,13 @@ end:
|
||||
|
||||
| Selector | Description |
|
||||
|--------------------------------------|------------------------------------------------------|
|
||||
| `#clipboard` | Clipboard widget. |
|
||||
| `#clipboard .btn` | Clipboard widget button. |
|
||||
| `#popup-clipboard` | Clipboard popup box. |
|
||||
| `#popup-clipboard .item` | Clipboard row item inside the popup. |
|
||||
| `#popup-clipboard .item .btn` | Clipboard row item radio button. |
|
||||
| `#popup-clipboard .item .btn.text` | Clipboard row item radio button (text values only). |
|
||||
| `#popup-clipboard .item .btn.image` | Clipboard row item radio button (image values only). |
|
||||
| `#popup-clipboard .item .btn-remove` | Clipboard row item remove button. |
|
||||
| `.clipboard` | Clipboard widget. |
|
||||
| `.clipboard .btn` | Clipboard widget button. |
|
||||
| `.popup-clipboard` | Clipboard popup box. |
|
||||
| `.popup-clipboard .item` | Clipboard row item inside the popup. |
|
||||
| `.popup-clipboard .item .btn` | Clipboard row item radio button. |
|
||||
| `.popup-clipboard .item .btn.text` | Clipboard row item radio button (text values only). |
|
||||
| `.popup-clipboard .item .btn.image` | Clipboard row item radio button (image values only). |
|
||||
| `.popup-clipboard .item .btn-remove` | Clipboard row item remove button. |
|
||||
|
||||
For more information on styling, please see the [styling guide](styling-guide).
|
@ -71,7 +71,9 @@ end:
|
||||
|
||||
| Selector | Description |
|
||||
|--------------------------------|------------------------------------------------------------------------------------|
|
||||
| `#clock` | Clock widget button |
|
||||
| `#popup-clock` | Clock popup box |
|
||||
| `#popup-clock #calendar-clock` | Clock inside the popup |
|
||||
| `#popup-clock #calendar` | Calendar widget inside the popup. GTK provides some OOTB styling options for this. |
|
||||
| `.clock` | Clock widget button |
|
||||
| `.popup-clock` | Clock popup box |
|
||||
| `.popup-clock .calendar-clock` | Clock inside the popup |
|
||||
| `.popup-clock .calendar` | Calendar widget inside the popup. GTK provides some OOTB styling options for this. |
|
||||
|
||||
For more information on styling, please see the [styling guide](styling-guide).
|
@ -392,10 +392,13 @@ let {
|
||||
|
||||
## Styling
|
||||
|
||||
Since the widgets are all custom, you can use the `name` and `class` attributes, then target them using `#name` and `.class`.
|
||||
Since the widgets are all custom, you can use their `name` and `class` attributes, then target them using `#name` and `.class`.
|
||||
|
||||
The following top-level selector is always available:
|
||||
The following top-level selectors are always available:
|
||||
|
||||
| Selector | Description |
|
||||
|-----------|-------------------------|
|
||||
| `#custom` | Custom widget container |
|
||||
| Selector | Description |
|
||||
|-----------------|--------------------------------|
|
||||
| `.custom` | Custom widget container. |
|
||||
| `.popup-custom` | Custom widget popup container. |
|
||||
|
||||
For more information on styling, please see the [styling guide](styling-guide).
|
@ -86,8 +86,10 @@ end:
|
||||
|
||||
## Styling
|
||||
|
||||
| Selector | Description |
|
||||
|--------------------------|--------------------|
|
||||
| `#focused` | Focused widget box |
|
||||
| `#focused #icon` | App icon |
|
||||
| `#focused #label` | App name |
|
||||
| Selector | Description |
|
||||
|-------------------|--------------------|
|
||||
| `.focused` | Focused widget box |
|
||||
| `.focused .icon` | App icon |
|
||||
| `.focused .label` | App name |
|
||||
|
||||
For more information on styling, please see the [styling guide](styling-guide).
|
@ -65,6 +65,8 @@ end:
|
||||
|
||||
## Styling
|
||||
|
||||
| Selector | Description |
|
||||
|--------------------------------|------------------------------------------------------------------------------------|
|
||||
| `#label` | Label widget |
|
||||
| Selector | Description |
|
||||
|----------|------------------------------------------------------------------------------------|
|
||||
| `.label` | Label widget |
|
||||
|
||||
For more information on styling, please see the [styling guide](styling-guide).
|
@ -90,10 +90,12 @@ start:
|
||||
|
||||
| Selector | Description |
|
||||
|-------------------------------|--------------------------|
|
||||
| `#launcher` | Launcher widget box |
|
||||
| `#launcher .item` | App button |
|
||||
| `#launcher .item.open` | App button (open app) |
|
||||
| `#launcher .item.focused` | App button (focused app) |
|
||||
| `#launcher .item.urgent` | App button (urgent app) |
|
||||
| `#launcher-popup` | Popup container |
|
||||
| `#launcher-popup .popup-item` | Window button in popup |
|
||||
| `.launcher` | Launcher widget box |
|
||||
| `.launcher .item` | App button |
|
||||
| `.launcher .item.open` | App button (open app) |
|
||||
| `.launcher .item.focused` | App button (focused app) |
|
||||
| `.launcher .item.urgent` | App button (urgent app) |
|
||||
| `.popup-launcher` | Popup container |
|
||||
| `.popup-launcher .popup-item` | Window button in popup |
|
||||
|
||||
For more information on styling, please see the [styling guide](styling-guide).
|
@ -135,24 +135,26 @@ and will be replaced with values from the currently playing track:
|
||||
|
||||
| Selector | Description |
|
||||
|-------------------------------------|------------------------------------------|
|
||||
| `#music` | Tray widget button |
|
||||
| `#music #contents` | Tray widget button contents box |
|
||||
| `#popup-music` | Popup box |
|
||||
| `#popup-music #album-art` | Album art image inside popup box |
|
||||
| `#popup-music #title` | Track title container inside popup box |
|
||||
| `#popup-music #title .icon` | Track title icon label inside popup box |
|
||||
| `#popup-music #title .label` | Track title label inside popup box |
|
||||
| `#popup-music #album` | Track album container inside popup box |
|
||||
| `#popup-music #album .icon` | Track album icon label inside popup box |
|
||||
| `#popup-music #album .label` | Track album label inside popup box |
|
||||
| `#popup-music #artist` | Track artist container inside popup box |
|
||||
| `#popup-music #artist .icon` | Track artist icon label inside popup box |
|
||||
| `#popup-music #artist .label` | Track artist label inside popup box |
|
||||
| `#popup-music #controls` | Controls container inside popup box |
|
||||
| `#popup-music #controls #btn-prev` | Previous button inside popup box |
|
||||
| `#popup-music #controls #btn-play` | Play button inside popup box |
|
||||
| `#popup-music #controls #btn-pause` | Pause button inside popup box |
|
||||
| `#popup-music #controls #btn-next` | Next button inside popup box |
|
||||
| `#popup-music #volume` | Volume container inside popup box |
|
||||
| `#popup-music #volume #slider` | Volume slider popup box |
|
||||
| `#popup-music #volume .icon` | Volume icon label inside popup box |
|
||||
| `.music` | Tray widget button |
|
||||
| `.music .contents` | Tray widget button contents box |
|
||||
| `.popup-music` | Popup box |
|
||||
| `.popup-music .album-art` | Album art image inside popup box |
|
||||
| `.popup-music .title` | Track title container inside popup box |
|
||||
| `.popup-music .title .icon` | Track title icon label inside popup box |
|
||||
| `.popup-music .title .label` | Track title label inside popup box |
|
||||
| `.popup-music .album` | Track album container inside popup box |
|
||||
| `.popup-music .album .icon` | Track album icon label inside popup box |
|
||||
| `.popup-music .album .label` | Track album label inside popup box |
|
||||
| `.popup-music .artist` | Track artist container inside popup box |
|
||||
| `.popup-music .artist .icon` | Track artist icon label inside popup box |
|
||||
| `.popup-music .artist .label` | Track artist label inside popup box |
|
||||
| `.popup-music .controls` | Controls container inside popup box |
|
||||
| `.popup-music .controls .btn-prev` | Previous button inside popup box |
|
||||
| `.popup-music .controls .btn-play` | Play button inside popup box |
|
||||
| `.popup-music .controls .btn-pause` | Pause button inside popup box |
|
||||
| `.popup-music .controls .btn-next` | Next button inside popup box |
|
||||
| `.popup-music .volume` | Volume container inside popup box |
|
||||
| `.popup-music .volume .slider` | Volume slider popup box |
|
||||
| `.popup-music .volume .icon` | Volume icon label inside popup box |
|
||||
|
||||
For more information on styling, please see the [styling guide](styling-guide).
|
@ -82,6 +82,8 @@ end:
|
||||
|
||||
## Styling
|
||||
|
||||
| Selector | Description |
|
||||
|---------------|---------------------|
|
||||
| `#script` | Script widget label |
|
||||
| Selector | Description |
|
||||
|-----------|---------------------|
|
||||
| `.script` | Script widget label |
|
||||
|
||||
For more information on styling, please see the [styling guide](styling-guide).
|
@ -172,5 +172,7 @@ The following tokens can be used in the `format` configuration option:
|
||||
|
||||
| Selector | Description |
|
||||
|------------------|------------------------------|
|
||||
| `#sysinfo` | Sysinfo widget box |
|
||||
| `#sysinfo #item` | Individual information label |
|
||||
| `.sysinfo` | Sysinfo widget box |
|
||||
| `.sysinfo .item` | Individual information label |
|
||||
|
||||
For more information on styling, please see the [styling guide](styling-guide).
|
@ -60,5 +60,7 @@ end:
|
||||
|
||||
| Selector | Description |
|
||||
|---------------|------------------|
|
||||
| `#tray` | Tray widget box |
|
||||
| `#tray .item` | Tray icon button |
|
||||
| `.tray` | Tray widget box |
|
||||
| `.tray .item` | Tray icon button |
|
||||
|
||||
For more information on styling, please see the [styling guide](styling-guide).
|
@ -72,9 +72,11 @@ end:
|
||||
|
||||
| Selector | Description |
|
||||
|---------------------------------|-----------------------------|
|
||||
| `#upower` | Upower widget container. |
|
||||
| `#upower #icon` | Upower widget battery icon. |
|
||||
| `#upower #button` | Upower widget button. |
|
||||
| `#upower #button #label` | Upower widget button label. |
|
||||
| `#popup-upower` | Upower popup box. |
|
||||
| `#popup-upower #upower-details` | Label inside the popup. |
|
||||
| `.upower` | Upower widget container. |
|
||||
| `.upower .icon` | Upower widget battery icon. |
|
||||
| `.upower .button` | Upower widget button. |
|
||||
| `.upower .button .label` | Upower widget button label. |
|
||||
| `.popup-upower` | Upower popup box. |
|
||||
| `.popup-upower .upower-details` | Label inside the popup. |
|
||||
|
||||
For more information on styling, please see the [styling guide](styling-guide).
|
@ -91,6 +91,8 @@ end:
|
||||
|
||||
| Selector | Description |
|
||||
|-----------------------------|--------------------------------------|
|
||||
| `#workspaces` | Workspaces widget box |
|
||||
| `#workspaces .item` | Workspace button |
|
||||
| `#workspaces .item.focused` | Workspace button (workspace focused) |
|
||||
| `.workspaces` | Workspaces widget box |
|
||||
| `.workspaces .item` | Workspace button |
|
||||
| `.workspaces .item.focused` | Workspace button (workspace focused) |
|
||||
|
||||
For more information on styling, please see the [styling guide](styling-guide).
|
@ -14,16 +14,11 @@
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
box, menubar {
|
||||
box, menubar, button {
|
||||
background-color: @color_bg;
|
||||
}
|
||||
|
||||
button {
|
||||
color: @color_text;
|
||||
background-color: @color_bg;
|
||||
}
|
||||
|
||||
label {
|
||||
button, label {
|
||||
color: @color_text;
|
||||
}
|
||||
|
||||
@ -43,12 +38,12 @@ button:hover {
|
||||
|
||||
/* -- clipboard -- */
|
||||
|
||||
#clipboard {
|
||||
.clipboard {
|
||||
margin-left: 5px;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
#popup-clipboard .item {
|
||||
.popup-clipboard .item {
|
||||
padding-bottom: 0.3em;
|
||||
border-bottom: 1px solid @color_border;
|
||||
}
|
||||
@ -56,125 +51,125 @@ button:hover {
|
||||
|
||||
/* -- clock -- */
|
||||
|
||||
#clock {
|
||||
.clock {
|
||||
font-weight: bold;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
#calendar-clock {
|
||||
.popup-clock .calendar-clock {
|
||||
color: @color_text;
|
||||
font-size: 2.5em;
|
||||
padding-bottom: 0.1em;
|
||||
}
|
||||
|
||||
#popup-clock #calendar {
|
||||
.popup-clock .calendar {
|
||||
background-color: @color_bg;
|
||||
color: @color_text;
|
||||
}
|
||||
|
||||
#popup-clock #calendar .header {
|
||||
.popup-clock .calendar .header {
|
||||
padding-top: 1em;
|
||||
border-top: 1px solid @color_border;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
#popup-clock #calendar:selected {
|
||||
.popup-clock .calendar:selected {
|
||||
background-color: @color_border_active;
|
||||
}
|
||||
|
||||
|
||||
/* -- launcher -- */
|
||||
|
||||
#launcher .item {
|
||||
.launcher .item {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
#launcher .item:not(.focused):hover {
|
||||
.launcher .item:not(.focused):hover {
|
||||
background-color: @color_bg_dark;
|
||||
}
|
||||
|
||||
#launcher .open {
|
||||
border-bottom: 2px solid @color_text;
|
||||
.launcher .open {
|
||||
border-bottom: 1px solid @color_text;
|
||||
}
|
||||
|
||||
#launcher .focused {
|
||||
border-bottom-color: @color_border_active;
|
||||
.launcher .focused {
|
||||
border-bottom: 2px solid @color_border_active;
|
||||
}
|
||||
|
||||
#launcher .urgent {
|
||||
.launcher .urgent {
|
||||
border-bottom-color: @color_urgent;
|
||||
}
|
||||
|
||||
#popup-launcher {
|
||||
.popup-launcher {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#popup-launcher .popup-item:not(:first-child) {
|
||||
.popup-launcher .popup-item:not(:first-child) {
|
||||
border-top: 1px solid @color_border;
|
||||
}
|
||||
|
||||
|
||||
/* -- music -- */
|
||||
|
||||
#music:hover * {
|
||||
.music:hover * {
|
||||
background-color: @color_bg_dark;
|
||||
}
|
||||
|
||||
#popup-music #album-art {
|
||||
.popup-music .album-art {
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
#popup-music #title .icon *, #popup-music #title .label {
|
||||
.popup-music .title .icon *, .popup-music .title .label {
|
||||
font-size: 1.7em;
|
||||
}
|
||||
|
||||
#popup-music #controls *:disabled {
|
||||
.popup-music .controls *:disabled {
|
||||
color: @color_border;
|
||||
}
|
||||
|
||||
#popup-music #volume scale slider {
|
||||
.popup-music .volume scale slider {
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
/* volume icon */
|
||||
#popup-music #volume > box:last-child label {
|
||||
.popup-music .volume > box:last-child label {
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
|
||||
/* -- script -- */
|
||||
|
||||
#script {
|
||||
.script {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
|
||||
/* -- sys_info -- */
|
||||
|
||||
#sysinfo {
|
||||
.sysinfo {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
#sysinfo #item {
|
||||
.sysinfo .item {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
|
||||
/* -- tray -- */
|
||||
|
||||
#tray {
|
||||
.tray {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
|
||||
/* -- workspaces -- */
|
||||
|
||||
#workspaces .item.focused {
|
||||
.workspaces .item.focused {
|
||||
box-shadow: inset 0 -3px;
|
||||
background-color: @color_bg_dark;
|
||||
}
|
||||
|
||||
#workspaces .item:hover {
|
||||
.workspaces .item:hover {
|
||||
box-shadow: inset 0 -3px;
|
||||
}
|
||||
|
||||
@ -185,7 +180,7 @@ button:hover {
|
||||
font-size: 1.4em;
|
||||
padding-bottom: 0.4em;
|
||||
margin-bottom: 0.6em;
|
||||
border-bottom: 1px solid @color_border
|
||||
border-bottom: 1px solid @color_border;
|
||||
}
|
||||
|
||||
.popup-power-menu .power-btn {
|
||||
@ -196,3 +191,4 @@ button:hover {
|
||||
.popup-power-menu #buttons > *:nth-child(1) .power-btn {
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
|
72
scripts/migrate-styles.sh
Executable file
72
scripts/migrate-styles.sh
Executable file
@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Migrates CSS selectors from widget names to CSS classes.
|
||||
# These changed as part of the 0.12 release.
|
||||
|
||||
# ⚠ This script will **NOT** check for custom styles and may mangle them!
|
||||
# ⚠ It is *highly recommended* that you back up your existing styles before running this!
|
||||
|
||||
style_path="$HOME/.config/ironbar/style.css"
|
||||
|
||||
# general
|
||||
sed -i 's/#icon/.icon/g' "$style_path"
|
||||
sed -i 's/#label/.label/g' "$style_path"
|
||||
sed -i 's/#image/.image/g' "$style_path"
|
||||
|
||||
# clipboard
|
||||
sed -i 's/#clipboard/.clipboard/g' "$style_path"
|
||||
sed -i 's/#popup-clipboard/.popup-clipboard/g' "$style_path"
|
||||
|
||||
# clock
|
||||
sed -i 's/#clock/.clock/g' "$style_path"
|
||||
sed -i 's/#popup-clock/.popup-clock/g' "$style_path"
|
||||
sed -i 's/#calendar-clock/.calendar-clock/g' "$style_path"
|
||||
sed -i 's/#calendar/.calendar/g' "$style_path"
|
||||
|
||||
# custom
|
||||
sed -i 's/#custom/.custom/g' "$style_path"
|
||||
sed -i 's/#popup-custom/.popup-custom/g' "$style_path"
|
||||
|
||||
# focused
|
||||
sed -i 's/#focused/.focused/g' "$style_path"
|
||||
|
||||
# launcher
|
||||
sed -i 's/#launcher/.launcher/g' "$style_path"
|
||||
sed -i 's/#popup-launcher/.popup-launcher/g' "$style_path"
|
||||
sed -i 's/#launcher-popup/.popup-launcher/g' "$style_path" # was incorrect in docs
|
||||
|
||||
# music
|
||||
sed -i 's/#music/.music/g' "$style_path"
|
||||
sed -i 's/#contents/.contents/g' "$style_path"
|
||||
sed -i 's/#popup-music/.popup-music/g' "$style_path"
|
||||
sed -i 's/#album-art/.album-art/g' "$style_path"
|
||||
sed -i 's/#title/.title/g' "$style_path"
|
||||
sed -i 's/#album/.album/g' "$style_path"
|
||||
sed -i 's/#artist/.artist/g' "$style_path"
|
||||
sed -i 's/#controls/.controls/g' "$style_path"
|
||||
sed -i 's/#btn-prev/.btn-prev/g' "$style_path"
|
||||
sed -i 's/#btn-play/.btn-play/g' "$style_path"
|
||||
sed -i 's/#btn-pause/.btn-pause/g' "$style_path"
|
||||
sed -i 's/#btn-next/.btn-next/g' "$style_path"
|
||||
sed -i 's/#volume/.volume/g' "$style_path"
|
||||
sed -i 's/#slider/.slider/g' "$style_path"
|
||||
|
||||
# script
|
||||
sed -i 's/#script/.script/g' "$style_path"
|
||||
|
||||
# sys_info
|
||||
sed -i 's/#sysinfo/.sysinfo/g' "$style_path"
|
||||
sed -i 's/#item/.item/g' "$style_path"
|
||||
|
||||
# tray
|
||||
sed -i 's/#tray/.tray/g' "$style_path"
|
||||
|
||||
# upower
|
||||
sed -i 's/#upower/.upower/g' "$style_path"
|
||||
sed -i 's/#button/.button/g' "$style_path"
|
||||
sed -i 's/#popup-upower/.popup-upower/g' "$style_path"
|
||||
sed -i 's/#upower-details/.upower-details/g' "$style_path"
|
||||
|
||||
# workspaces
|
||||
sed -i 's/#workspaces/.workspaces/g' "$style_path"
|
||||
sed -i 's/#item/.item/g' "$style_path"
|
10
src/bar.rs
10
src/bar.rs
@ -1,5 +1,7 @@
|
||||
use crate::config::{BarPosition, MarginConfig, ModuleConfig};
|
||||
use crate::modules::{create_module, wrap_widget, ModuleInfo, ModuleLocation};
|
||||
use crate::modules::{
|
||||
create_module, set_widget_identifiers, wrap_widget, ModuleInfo, ModuleLocation,
|
||||
};
|
||||
use crate::popup::Popup;
|
||||
use crate::Config;
|
||||
use color_eyre::Result;
|
||||
@ -195,8 +197,10 @@ fn add_modules(
|
||||
macro_rules! add_module {
|
||||
($module:expr, $id:expr) => {{
|
||||
let common = $module.common.take().expect("Common config did not exist");
|
||||
let widget = create_module(*$module, $id, &info, &Arc::clone(&popup))?;
|
||||
let container = wrap_widget(&widget, common, orientation);
|
||||
let widget_parts = create_module(*$module, $id, &info, &Arc::clone(&popup))?;
|
||||
set_widget_identifiers(&widget_parts, &common);
|
||||
|
||||
let container = wrap_widget(&widget_parts.widget, common, orientation);
|
||||
content.add(&container);
|
||||
}};
|
||||
}
|
||||
|
@ -10,8 +10,11 @@ use tracing::trace;
|
||||
|
||||
/// Common configuration options
|
||||
/// which can be set on every module.
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
#[derive(Debug, Default, Deserialize, Clone)]
|
||||
pub struct CommonConfig {
|
||||
pub class: Option<String>,
|
||||
pub name: Option<String>,
|
||||
|
||||
pub show_if: Option<ScriptInput>,
|
||||
pub transition_type: Option<TransitionType>,
|
||||
pub transition_duration: Option<u32>,
|
||||
@ -54,7 +57,7 @@ impl TransitionType {
|
||||
|
||||
impl CommonConfig {
|
||||
/// Configures the module's container according to the common config options.
|
||||
pub fn install(mut self, container: &EventBox, revealer: &Revealer) {
|
||||
pub fn install_events(mut self, container: &EventBox, revealer: &Revealer) {
|
||||
self.install_show_if(container, revealer);
|
||||
|
||||
let left_click_script = self.on_click_left.map(Script::new_polling);
|
||||
|
8
src/gtk_helpers.rs
Normal file
8
src/gtk_helpers.rs
Normal file
@ -0,0 +1,8 @@
|
||||
use glib::IsA;
|
||||
use gtk::prelude::*;
|
||||
use gtk::Widget;
|
||||
|
||||
/// Adds a new CSS class to a widget.
|
||||
pub fn add_class<W: IsA<Widget>>(widget: &W, class: &str) {
|
||||
widget.style_context().add_class(class);
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
use super::ImageProvider;
|
||||
use crate::gtk_helpers::add_class;
|
||||
use gtk::prelude::*;
|
||||
use gtk::{Button, IconTheme, Image, Label, Orientation};
|
||||
use tracing::error;
|
||||
@ -9,7 +10,7 @@ pub fn new_icon_button(input: &str, icon_theme: &IconTheme, size: i32) -> Button
|
||||
|
||||
if ImageProvider::is_definitely_image_input(input) {
|
||||
let image = Image::new();
|
||||
image.set_widget_name("image");
|
||||
add_class(&image, "image");
|
||||
|
||||
match ImageProvider::parse(input, icon_theme, size)
|
||||
.and_then(|provider| provider.load_into_image(image.clone()))
|
||||
@ -36,7 +37,7 @@ pub fn new_icon_label(input: &str, icon_theme: &IconTheme, size: i32) -> gtk::Bo
|
||||
|
||||
if ImageProvider::is_definitely_image_input(input) {
|
||||
let image = Image::new();
|
||||
image.set_widget_name("image");
|
||||
add_class(&image, "image");
|
||||
|
||||
container.add(&image);
|
||||
|
||||
@ -47,7 +48,7 @@ pub fn new_icon_label(input: &str, icon_theme: &IconTheme, size: i32) -> gtk::Bo
|
||||
}
|
||||
} else {
|
||||
let label = Label::new(Some(input));
|
||||
label.set_widget_name("label");
|
||||
add_class(&label, "label");
|
||||
|
||||
container.add(&label);
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ mod config;
|
||||
mod desktop_file;
|
||||
mod dynamic_string;
|
||||
mod error;
|
||||
mod gtk_helpers;
|
||||
mod image;
|
||||
mod logging;
|
||||
mod macros;
|
||||
|
@ -154,11 +154,7 @@ impl Module<Button> for ClipboardModule {
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let container = gtk::Box::builder()
|
||||
.orientation(Orientation::Vertical)
|
||||
.spacing(10)
|
||||
.name("popup-clipboard")
|
||||
.build();
|
||||
let container = gtk::Box::new(Orientation::Vertical, 10);
|
||||
|
||||
let entries = gtk::Box::new(Orientation::Vertical, 5);
|
||||
container.add(&entries);
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::config::CommonConfig;
|
||||
use crate::gtk_helpers::add_class;
|
||||
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
||||
use crate::popup::Popup;
|
||||
use crate::{send_async, try_send};
|
||||
@ -96,20 +97,16 @@ impl Module<Button> for ClockModule {
|
||||
rx: glib::Receiver<Self::SendMessage>,
|
||||
_info: &ModuleInfo,
|
||||
) -> Option<gtk::Box> {
|
||||
let container = gtk::Box::builder()
|
||||
.orientation(Orientation::Vertical)
|
||||
.name("popup-clock")
|
||||
.build();
|
||||
let container = gtk::Box::new(Orientation::Vertical, 0);
|
||||
|
||||
let clock = Label::builder()
|
||||
.name("calendar-clock")
|
||||
.halign(Align::Center)
|
||||
.build();
|
||||
let clock = Label::builder().halign(Align::Center).build();
|
||||
add_class(&clock, "calendar-clock");
|
||||
let format = "%H:%M:%S";
|
||||
|
||||
container.add(&clock);
|
||||
|
||||
let calendar = Calendar::builder().name("calendar").build();
|
||||
let calendar = Calendar::new();
|
||||
add_class(&calendar, "calendar");
|
||||
container.add(&calendar);
|
||||
|
||||
{
|
||||
|
@ -28,8 +28,6 @@ use tracing::{debug, error};
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct CustomModule {
|
||||
/// Container class name
|
||||
class: Option<String>,
|
||||
/// Widgets to add to the bar container
|
||||
bar: Vec<WidgetConfig>,
|
||||
/// Widgets to add to the popup container
|
||||
@ -197,10 +195,6 @@ impl Module<gtk::Box> for CustomModule {
|
||||
let orientation = info.bar_position.get_orientation();
|
||||
let container = gtk::Box::builder().orientation(orientation).build();
|
||||
|
||||
if let Some(ref class) = self.class {
|
||||
container.style_context().add_class(class);
|
||||
}
|
||||
|
||||
let custom_context = CustomWidgetContext {
|
||||
tx: &context.controller_tx,
|
||||
bar_orientation: orientation,
|
||||
@ -230,13 +224,7 @@ impl Module<gtk::Box> for CustomModule {
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let container = gtk::Box::builder().name("popup-custom").build();
|
||||
|
||||
if let Some(class) = self.class {
|
||||
container
|
||||
.style_context()
|
||||
.add_class(format!("popup-{class}").as_str());
|
||||
}
|
||||
let container = gtk::Box::new(Orientation::Horizontal, 0);
|
||||
|
||||
if let Some(popup) = self.popup {
|
||||
let custom_context = CustomWidgetContext {
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::clients::wayland::{self, ToplevelEvent};
|
||||
use crate::config::{CommonConfig, TruncateMode};
|
||||
use crate::gtk_helpers::add_class;
|
||||
use crate::image::ImageProvider;
|
||||
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
||||
use crate::{send_async, try_send};
|
||||
@ -95,8 +96,11 @@ impl Module<gtk::Box> for FocusedModule {
|
||||
|
||||
let container = gtk::Box::new(info.bar_position.get_orientation(), 5);
|
||||
|
||||
let icon = gtk::Image::builder().name("icon").build();
|
||||
let label = Label::builder().name("label").build();
|
||||
let icon = gtk::Image::new();
|
||||
add_class(&icon, "icon");
|
||||
|
||||
let label = Label::new(None);
|
||||
add_class(&label, "label");
|
||||
|
||||
if let Some(truncate) = self.truncate {
|
||||
truncate.truncate_label(&label);
|
||||
|
@ -413,10 +413,7 @@ impl Module<gtk::Box> for LauncherModule {
|
||||
) -> Option<gtk::Box> {
|
||||
const MAX_WIDTH: i32 = 250;
|
||||
|
||||
let container = gtk::Box::builder()
|
||||
.orientation(Orientation::Vertical)
|
||||
.name("popup-launcher")
|
||||
.build();
|
||||
let container = gtk::Box::new(Orientation::Vertical, 0);
|
||||
|
||||
// we need some content to force the container to have a size
|
||||
let placeholder = Button::with_label("PLACEHOLDER");
|
||||
|
@ -120,7 +120,7 @@ pub fn create_module<TModule, TWidget, TSend, TRec>(
|
||||
id: usize,
|
||||
info: &ModuleInfo,
|
||||
popup: &Arc<RwLock<Popup>>,
|
||||
) -> Result<TWidget>
|
||||
) -> Result<ModuleWidget<TWidget>>
|
||||
where
|
||||
TModule: Module<TWidget, SendMessage = TSend, ReceiveMessage = TRec>,
|
||||
TWidget: IsA<Widget>,
|
||||
@ -145,17 +145,21 @@ where
|
||||
let name = TModule::name();
|
||||
|
||||
let module_parts = module.into_widget(context, info)?;
|
||||
module_parts.widget.set_widget_name(name);
|
||||
module_parts.widget.style_context().add_class(name);
|
||||
|
||||
let mut has_popup = false;
|
||||
if let Some(popup_content) = module_parts.popup {
|
||||
if let Some(popup_content) = module_parts.popup.clone() {
|
||||
popup_content
|
||||
.style_context()
|
||||
.add_class(&format!("popup-{name}"));
|
||||
|
||||
register_popup_content(popup, id, popup_content);
|
||||
has_popup = true;
|
||||
}
|
||||
|
||||
setup_receiver(channel, w_tx, p_tx, popup.clone(), name, id, has_popup);
|
||||
|
||||
Ok(module_parts.widget)
|
||||
Ok(module_parts)
|
||||
}
|
||||
|
||||
/// Registers the popup content with the popup.
|
||||
@ -234,6 +238,32 @@ fn setup_receiver<TSend>(
|
||||
});
|
||||
}
|
||||
|
||||
pub fn set_widget_identifiers<TWidget: IsA<Widget>>(
|
||||
widget_parts: &ModuleWidget<TWidget>,
|
||||
common: &CommonConfig,
|
||||
) {
|
||||
if let Some(ref name) = common.name {
|
||||
widget_parts.widget.set_widget_name(name);
|
||||
|
||||
if let Some(ref popup) = widget_parts.popup {
|
||||
popup.set_widget_name(&format!("popup-{name}"));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref class) = common.class {
|
||||
// gtk counts classes with spaces as the same class
|
||||
for part in class.split(' ') {
|
||||
widget_parts.widget.style_context().add_class(part);
|
||||
}
|
||||
|
||||
if let Some(ref popup) = widget_parts.popup {
|
||||
for part in class.split(' ') {
|
||||
popup.style_context().add_class(&format!("popup-{part}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Takes a widget and adds it into a new `gtk::EventBox`.
|
||||
/// The event box container is returned.
|
||||
pub fn wrap_widget<W: IsA<Widget>>(
|
||||
@ -241,14 +271,14 @@ pub fn wrap_widget<W: IsA<Widget>>(
|
||||
common: CommonConfig,
|
||||
orientation: Orientation,
|
||||
) -> EventBox {
|
||||
let transition_type = common
|
||||
.transition_type
|
||||
.as_ref()
|
||||
.unwrap_or(&TransitionType::SlideStart)
|
||||
.to_revealer_transition_type(orientation);
|
||||
|
||||
let revealer = Revealer::builder()
|
||||
.transition_type(
|
||||
common
|
||||
.transition_type
|
||||
.as_ref()
|
||||
.unwrap_or(&TransitionType::SlideStart)
|
||||
.to_revealer_transition_type(orientation),
|
||||
)
|
||||
.transition_type(transition_type)
|
||||
.transition_duration(common.transition_duration.unwrap_or(250))
|
||||
.build();
|
||||
|
||||
@ -259,7 +289,7 @@ pub fn wrap_widget<W: IsA<Widget>>(
|
||||
container.add_events(EventMask::SCROLL_MASK);
|
||||
container.add(&revealer);
|
||||
|
||||
common.install(&container, &revealer);
|
||||
common.install_events(&container, &revealer);
|
||||
|
||||
container
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
mod config;
|
||||
|
||||
use crate::clients::music::{self, MusicClient, PlayerState, PlayerUpdate, Status, Track};
|
||||
use crate::gtk_helpers::add_class;
|
||||
use crate::image::{new_icon_button, new_icon_label, ImageProvider};
|
||||
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
||||
use crate::popup::Popup;
|
||||
@ -135,7 +136,7 @@ impl Module<Button> for MusicModule {
|
||||
PlayerCommand::Play => client.play(),
|
||||
PlayerCommand::Pause => client.pause(),
|
||||
PlayerCommand::Next => client.next(),
|
||||
PlayerCommand::Volume(vol) => client.set_volume_percent(vol), // .unwrap_or_else(|_| error!("Failed to update player volume")),
|
||||
PlayerCommand::Volume(vol) => client.set_volume_percent(vol),
|
||||
};
|
||||
|
||||
if let Err(err) = res {
|
||||
@ -154,11 +155,8 @@ impl Module<Button> for MusicModule {
|
||||
info: &ModuleInfo,
|
||||
) -> Result<ModuleWidget<Button>> {
|
||||
let button = Button::new();
|
||||
let button_contents = gtk::Box::builder()
|
||||
.orientation(Orientation::Horizontal)
|
||||
.spacing(5)
|
||||
.name("contents")
|
||||
.build();
|
||||
let button_contents = gtk::Box::new(Orientation::Horizontal, 5);
|
||||
add_class(&button_contents, "contents");
|
||||
|
||||
button.add(&button_contents);
|
||||
|
||||
@ -243,17 +241,13 @@ impl Module<Button> for MusicModule {
|
||||
) -> Option<gtk::Box> {
|
||||
let icon_theme = info.icon_theme;
|
||||
|
||||
let container = gtk::Box::builder()
|
||||
.orientation(Orientation::Horizontal)
|
||||
.spacing(10)
|
||||
.name("popup-music")
|
||||
.build();
|
||||
let container = gtk::Box::new(Orientation::Horizontal, 10);
|
||||
|
||||
let album_image = gtk::Image::builder()
|
||||
.width_request(128)
|
||||
.height_request(128)
|
||||
.name("album-art")
|
||||
.build();
|
||||
add_class(&album_image, "album-art");
|
||||
|
||||
let icons = self.icons;
|
||||
|
||||
@ -262,27 +256,28 @@ impl Module<Button> for MusicModule {
|
||||
let album_label = IconLabel::new(&icons.album, None, icon_theme);
|
||||
let artist_label = IconLabel::new(&icons.artist, None, icon_theme);
|
||||
|
||||
title_label.container.set_widget_name("title");
|
||||
album_label.container.set_widget_name("album");
|
||||
artist_label.container.set_widget_name("artist");
|
||||
add_class(&title_label.container, "title");
|
||||
add_class(&album_label.container, "album");
|
||||
add_class(&artist_label.container, "artist");
|
||||
|
||||
info_box.add(&title_label.container);
|
||||
info_box.add(&album_label.container);
|
||||
info_box.add(&artist_label.container);
|
||||
|
||||
let controls_box = gtk::Box::builder().name("controls").build();
|
||||
let controls_box = gtk::Box::new(Orientation::Horizontal, 0);
|
||||
add_class(&controls_box, "controls");
|
||||
|
||||
let btn_prev = new_icon_button(&icons.prev, icon_theme, self.icon_size);
|
||||
btn_prev.set_widget_name("btn-prev");
|
||||
add_class(&btn_prev, "btn-prev");
|
||||
|
||||
let btn_play = new_icon_button(&icons.play, icon_theme, self.icon_size);
|
||||
btn_play.set_widget_name("btn-play");
|
||||
add_class(&btn_play, "btn-play");
|
||||
|
||||
let btn_pause = new_icon_button(&icons.pause, icon_theme, self.icon_size);
|
||||
btn_pause.set_widget_name("btn-pause");
|
||||
add_class(&btn_pause, "btn-pause");
|
||||
|
||||
let btn_next = new_icon_button(&icons.next, icon_theme, self.icon_size);
|
||||
btn_next.set_widget_name("btn-next");
|
||||
add_class(&btn_next, "btn-next");
|
||||
|
||||
controls_box.add(&btn_prev);
|
||||
controls_box.add(&btn_play);
|
||||
@ -291,18 +286,15 @@ impl Module<Button> for MusicModule {
|
||||
|
||||
info_box.add(&controls_box);
|
||||
|
||||
let volume_box = gtk::Box::builder()
|
||||
.orientation(Orientation::Vertical)
|
||||
.spacing(5)
|
||||
.name("volume")
|
||||
.build();
|
||||
let volume_box = gtk::Box::new(Orientation::Vertical, 5);
|
||||
add_class(&volume_box, "volume");
|
||||
|
||||
let volume_slider = Scale::with_range(Orientation::Vertical, 0.0, 100.0, 5.0);
|
||||
volume_slider.set_inverted(true);
|
||||
volume_slider.set_widget_name("slider");
|
||||
add_class(&volume_slider, "slider");
|
||||
|
||||
let volume_icon = new_icon_label(&icons.volume, icon_theme, self.icon_size);
|
||||
volume_icon.style_context().add_class("icon");
|
||||
add_class(&volume_icon, "icon");
|
||||
|
||||
volume_box.pack_start(&volume_slider, true, true, 0);
|
||||
volume_box.pack_end(&volume_icon, false, false, 0);
|
||||
@ -466,8 +458,8 @@ impl IconLabel {
|
||||
let icon = new_icon_label(icon_input, icon_theme, 24);
|
||||
let label = Label::new(label);
|
||||
|
||||
icon.style_context().add_class("icon");
|
||||
label.style_context().add_class("label");
|
||||
add_class(&icon, "icon");
|
||||
add_class(&label, "label");
|
||||
|
||||
container.add(&icon);
|
||||
container.add(&label);
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::config::CommonConfig;
|
||||
use crate::gtk_helpers::add_class;
|
||||
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
||||
use crate::send_async;
|
||||
use color_eyre::Result;
|
||||
@ -193,12 +194,11 @@ impl Module<gtk::Box> for SysInfoModule {
|
||||
let mut labels = Vec::new();
|
||||
|
||||
for format in &self.format {
|
||||
let label = Label::builder()
|
||||
.label(format)
|
||||
.use_markup(true)
|
||||
.name("item")
|
||||
.build();
|
||||
let label = Label::builder().label(format).use_markup(true).build();
|
||||
|
||||
add_class(&label, "item");
|
||||
label.set_angle(info.bar_position.get_angle());
|
||||
|
||||
container.add(&label);
|
||||
labels.push(label);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::clients::upower::get_display_proxy;
|
||||
use crate::config::CommonConfig;
|
||||
use crate::gtk_helpers::add_class;
|
||||
use crate::image::ImageProvider;
|
||||
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
||||
use crate::popup::Popup;
|
||||
@ -144,20 +145,20 @@ impl Module<gtk::Box> for UpowerModule {
|
||||
info: &ModuleInfo,
|
||||
) -> Result<ModuleWidget<gtk::Box>> {
|
||||
let icon_theme = info.icon_theme.clone();
|
||||
let icon = gtk::Image::builder().name("icon").build();
|
||||
let icon = gtk::Image::new();
|
||||
add_class(&icon, "icon");
|
||||
|
||||
let label = Label::builder()
|
||||
.label(&self.format)
|
||||
.use_markup(true)
|
||||
.name("label")
|
||||
.build();
|
||||
add_class(&label, "label");
|
||||
|
||||
let container = gtk::Box::builder()
|
||||
.orientation(Orientation::Horizontal)
|
||||
.name("upower")
|
||||
.build();
|
||||
let container = gtk::Box::new(Orientation::Horizontal, 0);
|
||||
add_class(&container, "upower");
|
||||
|
||||
let button = Button::builder().name("button").build();
|
||||
let button = Button::new();
|
||||
add_class(&button, "button");
|
||||
|
||||
button.add(&label);
|
||||
container.add(&button);
|
||||
@ -207,11 +208,10 @@ impl Module<gtk::Box> for UpowerModule {
|
||||
{
|
||||
let container = gtk::Box::builder()
|
||||
.orientation(Orientation::Horizontal)
|
||||
.name("popup-upower")
|
||||
.build();
|
||||
|
||||
let label = Label::builder().name("upower-details").build();
|
||||
container.add(&label);
|
||||
let label = Label::new(None);
|
||||
add_class(&label, "upower-details");
|
||||
|
||||
rx.attach(None, move |properties| {
|
||||
let mut format = String::new();
|
||||
|
Loading…
Reference in New Issue
Block a user