From 8334323af873dcee520b9ab87f3e6892e323517c Mon Sep 17 00:00:00 2001 From: Joshua Strobl Date: Thu, 27 May 2021 15:47:45 +0300 Subject: [PATCH] Implement support for dedicated theme CSS files from our gresource. Properly implement light and gruvbox themes. Yay! --- src/koto-window.c | 12 +-- src/koto.gresource.xml | 4 +- src/meson.build | 2 +- src/pages/music/album-view.c | 6 +- theme/_button.scss | 6 ++ theme/_disc-view.scss | 32 ++++++-- theme/{main.scss => _main.scss} | 8 +- theme/_player-bar.scss | 15 ++++ theme/_primary-nav.scss | 1 + theme/_vars.scss | 3 +- theme/components/_cover-art-button.scss | 11 +++ theme/components/_gtk-overrides.scss | 88 ++++++++++++++++++++-- theme/koto-builtin-dark.scss | 5 ++ theme/koto-builtin-gruvbox.scss | 5 ++ theme/koto-builtin-light.scss | 5 ++ theme/meson.build | 30 +++++--- theme/pages/_music-local.scss | 4 + theme/pages/_playlist-page.scss | 10 ++- theme/variants/dark/_cover-art-button.scss | 7 -- theme/variants/dark/_disc-view.scss | 21 ------ theme/variants/dark/_main.scss | 21 ------ theme/variants/dark/_music-local.scss | 7 -- theme/variants/dark/_player-bar.scss | 15 ---- theme/variants/dark/_playlist-page.scss | 13 ---- theme/variants/dark/_vars.scss | 25 ++++++ theme/variants/gruvbox/_vars.scss | 25 ++++++ theme/variants/light/_vars.scss | 25 ++++++ 27 files changed, 285 insertions(+), 121 deletions(-) rename theme/{main.scss => _main.scss} (73%) create mode 100644 theme/components/_cover-art-button.scss create mode 100644 theme/koto-builtin-dark.scss create mode 100644 theme/koto-builtin-gruvbox.scss create mode 100644 theme/koto-builtin-light.scss delete mode 100644 theme/variants/dark/_cover-art-button.scss delete mode 100644 theme/variants/dark/_disc-view.scss delete mode 100644 theme/variants/dark/_main.scss delete mode 100644 theme/variants/dark/_music-local.scss delete mode 100644 theme/variants/dark/_player-bar.scss delete mode 100644 theme/variants/dark/_playlist-page.scss create mode 100644 theme/variants/dark/_vars.scss create mode 100644 theme/variants/gruvbox/_vars.scss create mode 100644 theme/variants/light/_vars.scss diff --git a/src/koto-window.c b/src/koto-window.c index 2ead509..16e0ff6 100644 --- a/src/koto-window.c +++ b/src/koto-window.c @@ -75,8 +75,6 @@ static void koto_window_init (KotoWindow * self) { current_playlist = koto_current_playlist_new(); playback_engine = koto_playback_engine_new(); - self->provider = gtk_css_provider_new(); - gtk_css_provider_load_from_resource(self->provider, "/com/github/joshstrobl/koto/style.css"); koto_window_manage_style(config, 0, self); // Immediately apply the theme g_signal_connect(config, "notify::ui-theme-desired", G_CALLBACK(koto_window_manage_style), self); // Handle changes to desired theme g_signal_connect(config, "notify::ui-theme-override", G_CALLBACK(koto_window_manage_style), self); // Handle changes to theme overriding @@ -184,12 +182,14 @@ void koto_window_manage_style( desired_theme = "dark"; } - GtkStyleContext * context = gtk_widget_get_style_context(GTK_WIDGET(self)); + if (!GTK_IS_CSS_PROVIDER(self->provider)) { // Don't have a CSS provider yet + self->provider = gtk_css_provider_new(); + } + + gtk_css_provider_load_from_resource(self->provider, g_strdup_printf("/com/github/joshstrobl/koto/koto-builtin-%s.css", desired_theme)); if (!overriding_theme) { // If we are not overriding the theme - if (!gtk_style_context_has_class(context, "koto-theme-dark")) { // Don't have our css class for a theme - gtk_style_context_add_provider_for_display(gdk_display_get_default(), GTK_STYLE_PROVIDER(self->provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - } + gtk_style_context_add_provider_for_display(gdk_display_get_default(), GTK_STYLE_PROVIDER(self->provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); GList * themes = NULL; themes = g_list_append(themes, "dark"); diff --git a/src/koto.gresource.xml b/src/koto.gresource.xml index 0edd239..60a81d4 100644 --- a/src/koto.gresource.xml +++ b/src/koto.gresource.xml @@ -1,6 +1,8 @@ - ../theme/style.css + ../theme/koto-builtin-dark.css + ../theme/koto-builtin-gruvbox.css + ../theme/koto-builtin-light.css diff --git a/src/meson.build b/src/meson.build index 514adc2..4011c07 100644 --- a/src/meson.build +++ b/src/meson.build @@ -55,7 +55,7 @@ gnome = import('gnome') koto_sources += gnome.compile_resources('koto-resources', 'koto.gresource.xml', - dependencies: [ theme ], + dependencies: themes, c_name: 'koto', ) diff --git a/src/pages/music/album-view.c b/src/pages/music/album-view.c index 28f36c5..aa80d6a 100644 --- a/src/pages/music/album-view.c +++ b/src/pages/music/album-view.c @@ -105,7 +105,11 @@ static void koto_album_view_init(KotoAlbumView * self) { gtk_box_append(GTK_BOX(self->album_tracks_box), self->discs); // Add the discs list box to the albums tracks box self->album_cover = koto_cover_art_button_new(220, 220, NULL); - gtk_box_prepend(GTK_BOX(self->main), koto_cover_art_button_get_main(self->album_cover)); + GtkWidget * album_cover_main = koto_cover_art_button_get_main(self->album_cover); + + gtk_widget_set_valign(album_cover_main, GTK_ALIGN_START); + + gtk_box_prepend(GTK_BOX(self->main), album_cover_main); KotoButton * cover_art_button = koto_cover_art_button_get_button(self->album_cover); // Get the button for the cover art koto_button_add_click_handler(cover_art_button, KOTO_BUTTON_CLICK_TYPE_PRIMARY, G_CALLBACK(koto_album_view_toggle_album_playback), self); } diff --git a/theme/_button.scss b/theme/_button.scss index 9b95dc6..a283d47 100644 --- a/theme/_button.scss +++ b/theme/_button.scss @@ -1,10 +1,16 @@ @import "vars"; .koto-button { + border-width: 0; + & > image { margin-right: 10px; } + &:not(.active) { + color: $text-color-bright; + } + &.active > image { color: $green; } diff --git a/theme/_disc-view.scss b/theme/_disc-view.scss index f1b18ae..2b613e4 100644 --- a/theme/_disc-view.scss +++ b/theme/_disc-view.scss @@ -1,8 +1,30 @@ @import "vars"; -.disc-view { - & > box { // Horizontal box with image and disc label - color: #ccc; - margin: 10px 0; +.discs-list { + background-color: transparent; + border-color: transparent; + border-width: 0; + + .disc-view { + & > box { // Horizontal box with image and disc label + color: $text-color-faded; + margin: 10px 0; + } + + & .track-list { + & > row { + &:not(:active):not(:selected) { // Neither active nor selected, see gtk overrides + color: $text-color-bright; + + &:nth-child(odd):not(:hover) { + background-color: $bg-primary; + } + + &:nth-child(even), &:hover { + background-color: $bg-secondary; + } + } + } + } } -} +} \ No newline at end of file diff --git a/theme/main.scss b/theme/_main.scss similarity index 73% rename from theme/main.scss rename to theme/_main.scss index 6265502..7359286 100644 --- a/theme/main.scss +++ b/theme/_main.scss @@ -1,7 +1,7 @@ +@import 'components/cover-art-button'; @import 'components/gtk-overrides'; @import 'pages/music-local'; @import 'pages/playlist-page'; -@import 'variants/dark/main'; @import 'button'; @import 'disc-view'; @@ -9,14 +9,18 @@ @import 'player-bar'; @import 'primary-nav'; @import 'track-item'; -@import 'vars'; window { + color: $text-color-bright; + background-color: $bg-primary; + & > headerbar, & > headerbar:active { + background-color: $bg-secondary; background-image: none; } .koto-dialog-container { + background-color: transparentize($bg-secondary, 0.25); padding: 20px; } diff --git a/theme/_player-bar.scss b/theme/_player-bar.scss index a41b4f1..99e9338 100644 --- a/theme/_player-bar.scss +++ b/theme/_player-bar.scss @@ -1,13 +1,28 @@ @import 'vars'; .player-bar { + background-color: $bg-secondary; background-image: none; padding: $halvedpadding; + .koto-button { + &:not(.toggled) { + color: $player-bar-icon-color; + } + + &.toggled { + color: $text-color-bright; + } + } + .playerbar-info { // Central info section & > box { // Info labels margin-left: 2ex; + & > image { + color: $text-color-faded; + } + & > label { margin-top: 6px; margin-bottom: 6px; diff --git a/theme/_primary-nav.scss b/theme/_primary-nav.scss index e1a2f21..da6abf3 100644 --- a/theme/_primary-nav.scss +++ b/theme/_primary-nav.scss @@ -14,6 +14,7 @@ & > .expander { & > .expander-header { + color: $text-color-faded; margin-bottom: 10px; } } diff --git a/theme/_vars.scss b/theme/_vars.scss index fc9994a..28ea9b1 100644 --- a/theme/_vars.scss +++ b/theme/_vars.scss @@ -1,4 +1,3 @@ -$grey: #2e2e2e; $midnight: #1d1d1d; $darkgrey: #666666; $green: #60E078; @@ -6,4 +5,4 @@ $palewhite: #cccccc; $red : #FF4652; $itempadding: 40px; -$halvedpadding: $itempadding / 2; +$halvedpadding: $itempadding / 2; \ No newline at end of file diff --git a/theme/components/_cover-art-button.scss b/theme/components/_cover-art-button.scss new file mode 100644 index 0000000..4bd5d20 --- /dev/null +++ b/theme/components/_cover-art-button.scss @@ -0,0 +1,11 @@ +.cover-art-button { + &:hover { + & > image { + opacity: 0.75; + } + + & > revealer > box { // Inner controls + background-color: transparentize($bg-secondary, 0.25); + } + } +} \ No newline at end of file diff --git a/theme/components/_gtk-overrides.scss b/theme/components/_gtk-overrides.scss index 07e6e5c..0eccc9e 100644 --- a/theme/components/_gtk-overrides.scss +++ b/theme/components/_gtk-overrides.scss @@ -1,8 +1,8 @@ @import '../vars'; @mixin selected-row-styling { - color: $midnight; - background-color: $green; + color: $selected-row-color-text; + background-color: $selected-row-color-bg; border: 0; // Don't have a border border-image: none; // GTK uses an image which is weird border-image-width: 0; @@ -12,15 +12,61 @@ } button { + .text-button { + &:not(.destructive-action):not(.suggested-action) { // Is just a plain ol' normal text button + color: $button-normal-color-text; + background: $button-normal-color-bg; + border-color: $button-normal-color-border; + } + } + &.destructive-action { - background-color: $red; + color: $button-destructive-color-text; + background-color: $button-destructive-color-bg; background-image: none; + border-width: 0; } &.suggested-action { // Adwaita makes it blue but we want it green - color: $midnight; - background-color: $green; + color: $button-suggested-color-text; + background-color: $button-suggested-color-bg; background-image: none; + border-width: 0; + } +} + +checkbutton { + color: $text-color-bright; + + &:active { + background-color: transparent; + } +} + +check { + background-image: none; + + &:not(:checked) { // Not checked + color: $text-color-faded; + } + + &:active { + background-color: transparent; + } + + &:checked { // Checked but not actively pressing on it + color: $text-color-bright; + background-color: $koto-primary-color; + } +} + +entry { + color: $text-color-bright; + background: $input-background; + border-color: $border-color; + + placeholder { // Placeholder text + color: $text-color-faded; } } @@ -42,11 +88,26 @@ list:not(.discs-list), listview { } } +popover.background { + & > arrow, & > contents { + background-color: $bg-primary; + border-color: $border-color; + } + + & > contents { + color: $text-color-bright; + } +} + range { &.dragging { // Dragging a range & > trough { + highlight { + border-color: $koto-primary-color; + } + & > slider { - background-color: $green; + background-color: $koto-primary-color; } } } @@ -54,10 +115,21 @@ range { scale { // Progress bar highlight { - background-color: $green; + background-color: $koto-primary-color; + border-color: $koto-primary-color; } slider { // Slider - outline-color: $green; + outline-color: $koto-primary-color; + } +} + +scalebutton { + &, button, image { + color: $player-bar-icon-color; + } + + &:active, &:checked, &:hover, button:active, button:checked, button:hover { + background-color: transparent; } } \ No newline at end of file diff --git a/theme/koto-builtin-dark.scss b/theme/koto-builtin-dark.scss new file mode 100644 index 0000000..f697902 --- /dev/null +++ b/theme/koto-builtin-dark.scss @@ -0,0 +1,5 @@ +$variant : 'dark'; + +@import 'vars'; // Root vars +@import 'variants/dark/vars'; // Dark variant vars +@import 'main'; \ No newline at end of file diff --git a/theme/koto-builtin-gruvbox.scss b/theme/koto-builtin-gruvbox.scss new file mode 100644 index 0000000..f64fdf7 --- /dev/null +++ b/theme/koto-builtin-gruvbox.scss @@ -0,0 +1,5 @@ +$variant : 'gruvbox'; + +@import 'vars'; // Root vars +@import 'variants/gruvbox/vars'; // Grubox variant vars +@import 'main'; \ No newline at end of file diff --git a/theme/koto-builtin-light.scss b/theme/koto-builtin-light.scss new file mode 100644 index 0000000..8a33e8a --- /dev/null +++ b/theme/koto-builtin-light.scss @@ -0,0 +1,5 @@ +$variant : 'light'; + +@import 'vars'; // Root vars +@import 'variants/light/vars'; // Light variant vars +@import 'main'; \ No newline at end of file diff --git a/theme/meson.build b/theme/meson.build index 134c5db..1d6a97a 100644 --- a/theme/meson.build +++ b/theme/meson.build @@ -1,12 +1,22 @@ sassc = find_program('sassc', required: true) -theme = custom_target('Theme generation', - input: 'main.scss', - output: 'style.css', - command: [ - sassc, - [ '-a', '-M', '-t', 'compact' ], - '@INPUT@', '@OUTPUT@', - ], - build_by_default: true, -) +builtin_variants = [ + 'dark', + 'gruvbox', + 'light' +] + +themes = [] + +foreach variant: builtin_variants + themes += custom_target('@0@ theme generation'.format(variant), + input: 'koto-builtin-@0@.scss'.format(variant), + output: 'koto-builtin-@0@.css'.format(variant), + command: [ + sassc, + [ '-a', '-M', '-t', 'compact' ], + '@INPUT@', '@OUTPUT@', + ], + build_by_default: true, + ) +endforeach \ No newline at end of file diff --git a/theme/pages/_music-local.scss b/theme/pages/_music-local.scss index 5e37821..b044777 100644 --- a/theme/pages/_music-local.scss +++ b/theme/pages/_music-local.scss @@ -2,6 +2,10 @@ .page-music-local { & > .artist-list { + &, & > viewport, & > viewport > list { + background-color: $artist-list-bg; + } + & > viewport > list { & > row { padding: $halvedpadding; diff --git a/theme/pages/_playlist-page.scss b/theme/pages/_playlist-page.scss index dbd6924..f8f2924 100644 --- a/theme/pages/_playlist-page.scss +++ b/theme/pages/_playlist-page.scss @@ -6,7 +6,7 @@ margin-left: 40px; & > label { // All labels - color: $palewhite; + color: $text-color-faded; } & > label:nth-child(1) { // First item (type of playlist) @@ -55,6 +55,14 @@ & > .track-list-columned { // Column content & > row { + &:not(:selected) { + color: $text-color-bright; + } + + &:nth-child(odd):not(:selected) { + background-color: $bg-secondary; + } + & > .track-list-columned-item { // Track rows font-size: x-large; } diff --git a/theme/variants/dark/_cover-art-button.scss b/theme/variants/dark/_cover-art-button.scss deleted file mode 100644 index 6ad7e75..0000000 --- a/theme/variants/dark/_cover-art-button.scss +++ /dev/null @@ -1,7 +0,0 @@ -@import '../../vars'; - -.cover-art-button { - & > revealer > box { // Inner controls - background-color: rgba(0,0,0,0.75); - } -} \ No newline at end of file diff --git a/theme/variants/dark/_disc-view.scss b/theme/variants/dark/_disc-view.scss deleted file mode 100644 index 96e88c3..0000000 --- a/theme/variants/dark/_disc-view.scss +++ /dev/null @@ -1,21 +0,0 @@ -@import '../../vars'; - -.disc-view { - & > box { // Horizontal box with image and disc label - color: #ccc; - } - - & .track-list { - & > row { - &:not(:active):not(:selected) { // Neither active nor selected, see gtk overrides - &:nth-child(odd):not(:hover) { - background-color: $midnight; - } - - &:nth-child(even), &:hover { - background-color: $grey; - } - } - } - } -} \ No newline at end of file diff --git a/theme/variants/dark/_main.scss b/theme/variants/dark/_main.scss deleted file mode 100644 index 8b03705..0000000 --- a/theme/variants/dark/_main.scss +++ /dev/null @@ -1,21 +0,0 @@ -@import '../../vars'; - -window { - &.koto-theme-dark { - background-color: $grey; - - & > headerbar, & > headerbar:active { - background-color: $midnight; - } - - .koto-dialog-container { - background-color: transparentize($midnight, 0.75); - } - - @import 'cover-art-button'; - @import 'disc-view'; - @import 'music-local'; - @import 'player-bar'; - @import 'playlist-page'; - } -} \ No newline at end of file diff --git a/theme/variants/dark/_music-local.scss b/theme/variants/dark/_music-local.scss deleted file mode 100644 index 0d1346c..0000000 --- a/theme/variants/dark/_music-local.scss +++ /dev/null @@ -1,7 +0,0 @@ -.page-music-local { - & > .artist-list { - &, & > viewport, & > viewport > list { - background-color: $midnight; - } - } -} \ No newline at end of file diff --git a/theme/variants/dark/_player-bar.scss b/theme/variants/dark/_player-bar.scss deleted file mode 100644 index 0e84278..0000000 --- a/theme/variants/dark/_player-bar.scss +++ /dev/null @@ -1,15 +0,0 @@ -@import '../../vars'; - -.player-bar { - background-color: $midnight; - - .koto-button { - &:not(.toggled) { - color: $darkgrey; - } - - &.toggled { - color: white; - } - } -} \ No newline at end of file diff --git a/theme/variants/dark/_playlist-page.scss b/theme/variants/dark/_playlist-page.scss deleted file mode 100644 index fca60d8..0000000 --- a/theme/variants/dark/_playlist-page.scss +++ /dev/null @@ -1,13 +0,0 @@ -@import '../../vars'; - -.playlist-page { - .track-list-content { // Our Track List - & > .track-list-columned { // Column content - & > row { - &:nth-child(odd):not(:selected) { - background-color: $midnight; - } - } - } - } -} \ No newline at end of file diff --git a/theme/variants/dark/_vars.scss b/theme/variants/dark/_vars.scss new file mode 100644 index 0000000..8f4df04 --- /dev/null +++ b/theme/variants/dark/_vars.scss @@ -0,0 +1,25 @@ +$koto-primary-color: $green; + +$bg-primary : #2e2e2e; +$bg-secondary : $midnight; + +$border-color: black; + +$text-color-bright: white; +$text-color-faded: $palewhite; + +$button-destructive-color-bg: $red; +$button-destructive-color-text: white; +$button-suggested-color-bg: $koto-primary-color; +$button-suggested-color-text: $midnight; +$button-normal-color-bg: $midnight; +$button-normal-color-text: $text-color-bright; +$button-normal-color-border: black; + +$input-background: $bg-primary; + +$artist-list-bg: $bg-secondary; +$player-bar-icon-color: $darkgrey; + +$selected-row-color-bg : $koto-primary-color; +$selected-row-color-text : $midnight; \ No newline at end of file diff --git a/theme/variants/gruvbox/_vars.scss b/theme/variants/gruvbox/_vars.scss new file mode 100644 index 0000000..ad5362a --- /dev/null +++ b/theme/variants/gruvbox/_vars.scss @@ -0,0 +1,25 @@ +$koto-primary-color: #ba5923; + +$bg-primary : #2C2826; +$bg-secondary : #211e1c; + +$border-color: black; + +$text-color-bright: white; +$text-color-faded: $palewhite; + +$button-destructive-color-bg: $red; +$button-destructive-color-text: white; +$button-suggested-color-bg: $koto-primary-color; +$button-suggested-color-text: $midnight; +$button-normal-color-bg: $midnight; +$button-normal-color-text: $text-color-bright; +$button-normal-color-border: black; + +$input-background: $bg-primary; + +$artist-list-bg: $bg-secondary; +$player-bar-icon-color: #423C3A; + +$selected-row-color-bg : $koto-primary-color; +$selected-row-color-text : $midnight; \ No newline at end of file diff --git a/theme/variants/light/_vars.scss b/theme/variants/light/_vars.scss new file mode 100644 index 0000000..08ddbc6 --- /dev/null +++ b/theme/variants/light/_vars.scss @@ -0,0 +1,25 @@ +$koto-primary-color: $green; + +$bg-primary : #fafafa; +$bg-secondary : $palewhite; + +$border-color: $darkgrey; + +$text-color-bright: $midnight; +$text-color-faded: $darkgrey; + +$button-destructive-color-bg: $red; +$button-destructive-color-text: white; +$button-suggested-color-bg: $koto-primary-color; +$button-suggested-color-text: $midnight; +$button-normal-color-bg: white; +$button-normal-color-text: $text-color-bright; +$button-normal-color-border: $darkgrey; + +$input-background: $bg-primary; + +$artist-list-bg: $bg-secondary; +$player-bar-icon-color: $darkgrey; + +$selected-row-color-bg : $koto-primary-color; +$selected-row-color-text : $midnight; \ No newline at end of file