From 69b79f5d63fe52170de31aec8f8443b5ac4b8ab6 Mon Sep 17 00:00:00 2001 From: KoffeinFlummi Date: Fri, 22 Mar 2019 01:08:29 +0100 Subject: [PATCH] Add configurable theme --- src/config.rs | 20 ++++++++++++++++++++ src/main.rs | 6 ++++-- src/theme.rs | 33 +++++++++++++++++++++++++++++---- src/ui/layout.rs | 23 +++++++++++++++++++---- src/ui/listview.rs | 12 +++++++++--- src/ui/statusbar.rs | 12 +++++++++--- 6 files changed, 90 insertions(+), 16 deletions(-) diff --git a/src/config.rs b/src/config.rs index 6355a76..9971966 100644 --- a/src/config.rs +++ b/src/config.rs @@ -11,6 +11,26 @@ pub struct Config { pub username: String, pub password: String, pub keybindings: Option>, + pub theme: Option, +} + +#[derive(Serialize, Deserialize, Debug, Default, Clone)] +pub struct ConfigTheme { + pub background: Option, + pub primary: Option, + pub secondary: Option, + pub title: Option, + pub playing: Option, + pub playing_bg: Option, + pub highlight: Option, + pub highlight_bg: Option, + pub error: Option, + pub error_bg: Option, + pub statusbar_progress: Option, + pub statusbar: Option, + pub statusbar_bg: Option, + pub cmdline: Option, + pub cmdline_bg: Option, } pub fn config_path() -> PathBuf { diff --git a/src/main.rs b/src/main.rs index c1b7420..ec9cede 100644 --- a/src/main.rs +++ b/src/main.rs @@ -72,10 +72,12 @@ fn main() { }) }; + let theme = theme::load(&cfg); + let logview = DebugView::new(); let mut cursive = Cursive::default(); - cursive.set_theme(theme::default()); + cursive.set_theme(theme.clone()); let event_manager = EventManager::new(cursive.cb_sink().clone()); @@ -118,7 +120,7 @@ fn main() { let status = ui::statusbar::StatusBar::new(queue.clone(), spotify.clone()); - let mut layout = ui::layout::Layout::new(status, &event_manager) + let mut layout = ui::layout::Layout::new(status, &event_manager, theme) .view("search", search.with_id("search"), "Search") .view("log", logview_scroller, "Debug Log") .view("playlists", playlistsview, "Playlists") diff --git a/src/theme.rs b/src/theme.rs index d506f3a..86837c3 100644 --- a/src/theme.rs +++ b/src/theme.rs @@ -1,14 +1,39 @@ use cursive::theme::Color::*; use cursive::theme::PaletteColor::*; +use cursive::theme::BaseColor::*; use cursive::theme::*; -pub fn default() -> Theme { +use config::Config; + +macro_rules! load_color { + ( $cfg: expr, $member: ident, $default: expr ) => { + $cfg.theme.as_ref() + .and_then(|t| t.$member.clone()) + .map(|c| Color::parse(c.as_ref()).expect(&format!("Failed to parse color \"{}\"", c))) + .unwrap_or($default) + } +} + +pub fn load(cfg: &Config) -> Theme { let mut palette = Palette::default(); let borders = BorderStyle::None; - palette[Background] = TerminalDefault; - palette[View] = TerminalDefault; - palette[Primary] = TerminalDefault; + palette[Background] = load_color!(cfg, background, TerminalDefault); + palette[View] = load_color!(cfg, background, TerminalDefault); + palette[Primary] = load_color!(cfg, primary, TerminalDefault); + palette[Secondary] = load_color!(cfg, secondary, Dark(Blue)); + palette[TitlePrimary] = load_color!(cfg, title, Dark(Red)); + palette[Tertiary] = load_color!(cfg, highlight, TerminalDefault); + palette[Highlight] = load_color!(cfg, highlight_bg, Dark(Red)); + palette.set_color("playing", load_color!(cfg, playing, Dark(Blue))); + palette.set_color("playing_bg", load_color!(cfg, playing_bg, TerminalDefault)); + palette.set_color("error", load_color!(cfg, error, TerminalDefault)); + palette.set_color("error_bg", load_color!(cfg, error_bg, Dark(Red))); + palette.set_color("statusbar_progress", load_color!(cfg, statusbar_progress, Dark(Blue))); + palette.set_color("statusbar", load_color!(cfg, statusbar, Dark(Yellow))); + palette.set_color("statusbar_bg", load_color!(cfg, statusbar_bg, TerminalDefault)); + palette.set_color("cmdline", load_color!(cfg, cmdline, TerminalDefault)); + palette.set_color("cmdline_bg", load_color!(cfg, cmdline_bg, TerminalDefault)); Theme { shadow: false, diff --git a/src/ui/layout.rs b/src/ui/layout.rs index e1cd651..7c5ffe9 100644 --- a/src/ui/layout.rs +++ b/src/ui/layout.rs @@ -4,7 +4,7 @@ use std::time::{Duration, SystemTime}; use cursive::align::HAlign; use cursive::direction::Direction; use cursive::event::{AnyCb, Event, EventResult}; -use cursive::theme::ColorStyle; +use cursive::theme::{Theme, ColorStyle, ColorType}; use cursive::traits::View; use cursive::vec::Vec2; use cursive::view::{IntoBoxedView, Selector}; @@ -30,21 +30,32 @@ pub struct Layout { error_time: Option, screenchange: bool, ev: events::EventManager, + theme: Theme } impl Layout { - pub fn new(status: T, ev: &events::EventManager) -> Layout { + pub fn new( + status: T, + ev: &events::EventManager, + theme: Theme + ) -> Layout { + let style = ColorStyle::new( + ColorType::Color(*theme.palette.custom("cmdline_bg").unwrap()), + ColorType::Color(*theme.palette.custom("cmdline").unwrap()), + ); + Layout { views: HashMap::new(), title: String::new(), statusbar: status.as_boxed_view(), focus: None, - cmdline: EditView::new().filler(" "), + cmdline: EditView::new().filler(" ").style(style), cmdline_focus: false, error: None, error_time: None, ev: ev.clone(), screenchange: true, + theme: theme, } } @@ -135,7 +146,11 @@ impl View for Layout { .draw(&printer.offset((0, printer.size.y - 2 - cmdline_height))); if let Some(e) = error { - printer.with_color(ColorStyle::highlight(), |printer| { + let style = ColorStyle::new( + ColorType::Color(*self.theme.palette.custom("error").unwrap()), + ColorType::Color(*self.theme.palette.custom("error_bg").unwrap()), + ); + printer.with_color(style, |printer| { printer.print_hline((0, printer.size.y - cmdline_height), printer.size.x, " "); printer.print( (0, printer.size.y - cmdline_height), diff --git a/src/ui/listview.rs b/src/ui/listview.rs index 1caf1b8..d73347d 100644 --- a/src/ui/listview.rs +++ b/src/ui/listview.rs @@ -3,7 +3,7 @@ use std::sync::{Arc, RwLock}; use cursive::align::HAlign; use cursive::event::{Event, EventResult, MouseButton, MouseEvent}; -use cursive::theme::ColorStyle; +use cursive::theme::{ColorStyle, ColorType, PaletteColor}; use cursive::traits::View; use cursive::view::ScrollBase; use cursive::{Printer, Rect, Vec2}; @@ -64,9 +64,15 @@ impl View for ListView { let item = &content[i]; let style = if self.selected == i { - ColorStyle::highlight() + ColorStyle::new( + ColorType::Palette(PaletteColor::Tertiary), + ColorType::Palette(PaletteColor::Highlight) + ) } else if item.is_playing(self.queue.clone()) { - ColorStyle::secondary() + ColorStyle::new( + ColorType::Color(*printer.theme.palette.custom("playing").unwrap()), + ColorType::Color(*printer.theme.palette.custom("playing_bg").unwrap()) + ) } else { ColorStyle::primary() }; diff --git a/src/ui/statusbar.rs b/src/ui/statusbar.rs index ffa10f1..2e2854d 100644 --- a/src/ui/statusbar.rs +++ b/src/ui/statusbar.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use cursive::align::HAlign; -use cursive::theme::ColorStyle; +use cursive::theme::{ColorStyle, ColorType, PaletteColor}; use cursive::traits::View; use cursive::vec::Vec2; use cursive::Printer; @@ -30,8 +30,14 @@ impl View for StatusBar { return; } - let style_bar = ColorStyle::secondary(); - let style = ColorStyle::title_secondary(); + let style_bar = ColorStyle::new( + ColorType::Color(*printer.theme.palette.custom("statusbar_progress").unwrap()), + ColorType::Palette(PaletteColor::Background), + ); + let style = ColorStyle::new( + ColorType::Color(*printer.theme.palette.custom("statusbar").unwrap()), + ColorType::Color(*printer.theme.palette.custom("statusbar_bg").unwrap()), + ); printer.print( (0, 0),