From b29caa58b4e122963bb2a11a9723c72ed28837ba Mon Sep 17 00:00:00 2001 From: MCorange Date: Fri, 15 Nov 2024 14:58:09 +0200 Subject: [PATCH] Settings panel ui --- .gitignore | 1 + xmpd-gui/src/components/left_nav.rs | 3 +- xmpd-gui/src/components/song_list/mod.rs | 18 +++-- xmpd-gui/src/components/top_nav.rs | 5 +- xmpd-gui/src/lib.rs | 16 +---- xmpd-gui/src/main_window.rs | 91 ++++++++++++++---------- xmpd-gui/src/windows/error.rs | 2 +- xmpd-gui/src/windows/mod.rs | 21 ++++-- xmpd-gui/src/windows/settings.rs | 41 ++++++++++- xmpd-settings/src/lib.rs | 2 +- 10 files changed, 132 insertions(+), 68 deletions(-) diff --git a/.gitignore b/.gitignore index b83d222..ca25715 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target/ +settings.toml diff --git a/xmpd-gui/src/components/left_nav.rs b/xmpd-gui/src/components/left_nav.rs index 1c3c7e5..11d1b63 100644 --- a/xmpd-gui/src/components/left_nav.rs +++ b/xmpd-gui/src/components/left_nav.rs @@ -43,7 +43,7 @@ impl CompUi for LeftNav { } fn add_playlist_tab(ui: &mut egui::Ui, pid: &Option, title: &str, author: Option<&str>, song_count: usize, width: f32) { - let theme = handle_error_ui!(xmpd_settings::Settings::get()).theme.clone(); + let theme = &handle_error_ui!(xmpd_settings::Settings::get()).theme; let wdg_rect = ui.horizontal(|ui| { ui.set_width(width); ui.add_space(5.0); @@ -63,6 +63,7 @@ fn add_playlist_tab(ui: &mut egui::Ui, pid: &Option, title: &str, au } else { ui.label( RichText::new(title) + .color(theme.text_color) .size(10.0) ); } diff --git a/xmpd-gui/src/components/song_list/mod.rs b/xmpd-gui/src/components/song_list/mod.rs index 7a03587..13e052c 100644 --- a/xmpd-gui/src/components/song_list/mod.rs +++ b/xmpd-gui/src/components/song_list/mod.rs @@ -59,10 +59,10 @@ impl CompUi for SongList { let query = {handle_error_ui!(song_list_nav::SongListNav::get()).parse_search()}.clone(); for (sid, song) in songs { let should_display = match query { - SearchType::Source(ref s) if !s.is_empty() && format!("{:?}", &song.source_type()).to_lowercase().contains(s) => true, - SearchType::Author(ref s) if !s.is_empty() && song.author().to_lowercase().contains(s) => true, - SearchType::Name(ref s) if !s.is_empty() && song.name().to_owned().contains(s) => true, - _ => false + SearchType::Source(ref s) if !s.is_empty() => format!("{:?}", &song.source_type()).to_lowercase().contains(s), + SearchType::Author(ref s) if !s.is_empty() => song.author().to_lowercase().contains(s), + SearchType::Name(ref s) if !s.is_empty() => song.name().to_owned().contains(s), + _ => true }; if should_display { display_song_tab(ui, sid, song); @@ -89,9 +89,15 @@ fn display_song_tab(ui: &mut egui::Ui, sid: &uuid::Uuid, song: &Song) { ui.vertical(|ui| { let selected_song_id = {handle_error_ui!(SongList::get()).selected_song_id}; if selected_song_id == *sid { - ui.label(RichText::new(song.name()).color(theme.accent_color)); + ui.label( + RichText::new(song.name()) + .color(theme.accent_color) + ); } else { - ui.label(song.name()); + ui.label( + RichText::new(song.name()) + .color(theme.text_color) + ); }; ui.monospace( RichText::new(format!("By {}", song.author())) diff --git a/xmpd-gui/src/components/top_nav.rs b/xmpd-gui/src/components/top_nav.rs index 4ac30d4..b665c4f 100644 --- a/xmpd-gui/src/components/top_nav.rs +++ b/xmpd-gui/src/components/top_nav.rs @@ -1,3 +1,5 @@ +use crate::windows::WindowId; + use super::CompUi; #[derive(Debug, Default)] @@ -11,8 +13,7 @@ impl CompUi for TopNav { egui::menu::bar(ui, |ui| { ui.menu_button("File", |ui| { if ui.button("Settings").clicked() { - - + state.windows.toggle(&WindowId::Settings, true); } }); ui.menu_button("Manifest", |ui| { diff --git a/xmpd-gui/src/lib.rs b/xmpd-gui/src/lib.rs index 731c335..ef49f07 100644 --- a/xmpd-gui/src/lib.rs +++ b/xmpd-gui/src/lib.rs @@ -21,20 +21,8 @@ pub fn start(manifest_path: PathBuf) -> Result<()> { let theme = xmpd_settings::Settings::get()?.theme.clone(); let res = eframe::run_simple_native(W_NAME, options, move |ctx, _frame| { egui_extras::install_image_loaders(ctx); - state.windows.clone().draw_all(ctx, &mut state); - egui::CentralPanel::default() - .frame( - egui::Frame::none() - .fill(theme.primary_bg_color) - .stroke(egui::Stroke::new( - 1.0, - theme.secondary_bg_color, - )), - ) - .show(ctx, |ui| { - ui.style_mut().visuals.override_text_color = Some(theme.text_color); - main_window::draw(ui, &mut state) - }); + state.windows.clone().draw_all(ctx, &mut state); + handle_error_ui!(main_window::draw(ctx, &mut state)); ctx.request_repaint_after(Duration::from_millis(500)); }); if let Err(e) = res { // dumb err value by eframe diff --git a/xmpd-gui/src/main_window.rs b/xmpd-gui/src/main_window.rs index 220131d..eb8a8af 100644 --- a/xmpd-gui/src/main_window.rs +++ b/xmpd-gui/src/main_window.rs @@ -1,49 +1,66 @@ +use xmpd_settings::theme::Theme; + use crate::{components::CompUi, GuiState}; -pub fn draw(ui: &mut egui::Ui, state: &mut GuiState) -> crate::Result<()> { +pub fn draw(ctx: &egui::Context, state: &mut GuiState) -> crate::Result<()> { // The central panel the region left after adding TopPanel's and SidePanel's // ui.heading(format!("Songs ({})", self.manifest.get_song_count())); let theme = xmpd_settings::Settings::get()?.theme.clone(); - let avail = ui.available_size(); - ui.vertical(|ui| { - handle_error_ui!(crate::components::top_nav::TopNav::draw(ui, state)); - crate::utils::super_separator(ui, theme.accent_color, avail.x, 2.0); - let avail = ui.available_size(); - let main_height = avail.y * 0.91; - - ui.horizontal(|ui| { - ui.set_height(main_height); - ui.group(|ui| { - ui.set_height(main_height); - ui.set_max_width((avail.x * 0.25).clamp(0.0, 200.0)); - handle_error_ui!(crate::components::left_nav::LeftNav::draw(ui, state)); - }); + egui::TopBottomPanel::new(egui::panel::TopBottomSide::Top, "top_nav") + .frame(get_themed_frame(&theme)) + .show(ctx, |ui| { + ui.style_mut().visuals.override_text_color = Some(theme.text_color); + handle_error_ui!(crate::components::top_nav::TopNav::draw(ui, state)); + } + ); + egui::CentralPanel::default() + .frame(get_themed_frame(&theme)) + .show(ctx, |ui| { + let avail = ui.available_size(); ui.vertical(|ui| { - ui.group(|ui| { - ui.set_width(avail.x * 0.75); - handle_error_ui!(crate::components::song_list::song_list_nav::SongListNav::draw(ui, state)); - }); - ui.group(|ui| { - handle_error_ui!(crate::components::song_list::SongList::draw(ui, state)); - }); - }); - }); - egui::TopBottomPanel::new(egui::panel::TopBottomSide::Bottom, "player") - .frame( - egui::Frame::none() - .fill(theme.primary_bg_color) - .stroke(egui::Stroke::new( - 1.0, - theme.secondary_bg_color, - )), - ) - .show(ui.ctx(), |ui| { + crate::utils::super_separator(ui, theme.accent_color, avail.x, 2.0); + let avail = ui.available_size(); + let main_height = avail.y * 0.91; - ui.style_mut().visuals.override_text_color = Some(theme.accent_color); + ui.horizontal(|ui| { + ui.set_height(main_height); + ui.group(|ui| { + ui.set_height(main_height); + ui.set_max_width((avail.x * 0.25).clamp(0.0, 200.0)); + handle_error_ui!(crate::components::left_nav::LeftNav::draw(ui, state)); + }); + ui.vertical(|ui| { + ui.group(|ui| { + ui.set_width(avail.x * 0.75); + handle_error_ui!(crate::components::song_list::song_list_nav::SongListNav::draw(ui, state)); + }); + ui.group(|ui| { + handle_error_ui!(crate::components::song_list::SongList::draw(ui, state)); + }); + }); + }); + + }); + } + ); + + egui::TopBottomPanel::new(egui::panel::TopBottomSide::Bottom, "player") + .frame(get_themed_frame(&theme)) + .show(ctx, |ui| { + ui.style_mut().visuals.override_text_color = Some(theme.text_color); handle_error_ui!(crate::components::player::Player::draw(ui, state)); - }); - }); + } + ); Ok(()) } +fn get_themed_frame(theme: &Theme) -> egui::Frame { + egui::Frame::none() + .fill(theme.primary_bg_color) + .stroke(egui::Stroke::new( + 1.0, + theme.secondary_bg_color, + )) +} + diff --git a/xmpd-gui/src/windows/error.rs b/xmpd-gui/src/windows/error.rs index 5992f74..3c9b055 100644 --- a/xmpd-gui/src/windows/error.rs +++ b/xmpd-gui/src/windows/error.rs @@ -7,7 +7,7 @@ pub struct ErrorW { } impl Window for ErrorW { - fn draw(&self, ui: &mut egui::Ui, _: &mut crate::GuiState) -> crate::Result<()> { + fn draw(&mut self, ui: &mut egui::Ui, _: &mut crate::GuiState) -> crate::Result<()> { ui.label("Hello from other window!"); Ok(()) } diff --git a/xmpd-gui/src/windows/mod.rs b/xmpd-gui/src/windows/mod.rs index c6cfd8d..126e007 100644 --- a/xmpd-gui/src/windows/mod.rs +++ b/xmpd-gui/src/windows/mod.rs @@ -12,7 +12,7 @@ lazy_static::lazy_static!( ); pub trait Window: std::fmt::Debug + Send { - fn draw(&self, ui: &mut egui::Ui, state: &mut GuiState) -> crate::Result<()>; + fn draw(&mut self, ui: &mut egui::Ui, state: &mut GuiState) -> crate::Result<()>; } #[derive(Debug, Clone, Hash, PartialEq, PartialOrd, Ord, Eq)] @@ -36,25 +36,38 @@ impl Windows { } pub fn add_all_windows(&mut self) { - self.add_new_window(WindowId::Error, "Error!", Box::::default()) + self.add_new_window(WindowId::Error, "Error!", Box::::default()); + self.add_new_window(WindowId::Settings, "Settings", Box::::default()); } pub fn add_new_window(&mut self, id: WindowId, title: &str, cb: Box) { let builder = ViewportBuilder::default() + .with_window_type(egui::X11WindowType::Dialog) .with_title(title); self.windows.insert(id.clone(), (ViewportId::from_hash_of(id.clone()), builder)); WINDOWS.lock().unwrap().insert(id, cb); } pub fn draw_all(&mut self, ctx: &egui::Context, state: &mut GuiState) { + let theme = handle_error_ui!(xmpd_settings::Settings::get()).theme.clone(); for (win_id, (vp_id, builder)) in &self.windows { if self.is_open(&win_id) { ctx.show_viewport_immediate(vp_id.clone(), builder.clone(), |ctx, _vp_class| { ctx.input(|inp| { self.toggle(win_id, !inp.viewport().close_requested()); }); - egui::CentralPanel::default().show(ctx, |ui| { - WINDOWS.lock().unwrap().get(&win_id).unwrap().draw(ui, state) + egui::CentralPanel::default() + .frame( + egui::Frame::none() + .fill(theme.primary_bg_color) + .stroke(egui::Stroke::new( + 1.0, + theme.secondary_bg_color, + )), + ) + .show(ctx, |ui| { + ui.style_mut().visuals.override_text_color = Some(theme.text_color); + WINDOWS.lock().unwrap().get_mut(&win_id).unwrap().draw(ui, state) }) }); } diff --git a/xmpd-gui/src/windows/settings.rs b/xmpd-gui/src/windows/settings.rs index 8baf21e..d831384 100644 --- a/xmpd-gui/src/windows/settings.rs +++ b/xmpd-gui/src/windows/settings.rs @@ -3,12 +3,49 @@ use super::Window; #[derive(Debug, Clone)] pub struct SettingsW { - + accent_color: egui::Color32, + primary_bg_color: egui::Color32, + secondary_bg_color: egui::Color32, + text_color: egui::Color32, + dim_text_color: egui::Color32, } +impl Default for SettingsW { + fn default() -> Self { + let def = xmpd_settings::theme::Theme::default(); + Self { + accent_color: def.accent_color, + primary_bg_color: def.primary_bg_color, + secondary_bg_color: def.secondary_bg_color, + text_color: def.text_color, + dim_text_color: def.dim_text_color + } + } + +} impl Window for SettingsW { - fn draw(&self, ui: &mut egui::Ui, _: &mut crate::GuiState) -> crate::Result<()> { + fn draw(&mut self, ui: &mut egui::Ui, _: &mut crate::GuiState) -> crate::Result<()> { + let theme = &mut xmpd_settings::Settings::get()?.theme; + ui.group(|ui| { + ui.vertical(|ui| { + ui.heading("Theme"); + Self::add_theme_button(&mut theme.accent_color, ui, "Accent"); + Self::add_theme_button(&mut theme.primary_bg_color, ui, "Primary BG"); + Self::add_theme_button(&mut theme.secondary_bg_color, ui, "Secondary BG"); + Self::add_theme_button(&mut theme.text_color, ui, "Text"); + Self::add_theme_button(&mut theme.dim_text_color, ui, "Dim Text"); + }); + }); Ok(()) } } + +impl SettingsW { + fn add_theme_button(rf: &mut egui::Color32, ui: &mut egui::Ui, name: &str) { + ui.horizontal(|ui| { + ui.label(format!("{name}: ")); + ui.color_edit_button_srgba(rf); + }); + } +} diff --git a/xmpd-settings/src/lib.rs b/xmpd-settings/src/lib.rs index 46729a9..36978bf 100644 --- a/xmpd-settings/src/lib.rs +++ b/xmpd-settings/src/lib.rs @@ -2,7 +2,7 @@ use std::{path::PathBuf, sync::{Arc, Mutex, MutexGuard}}; use serde::{Deserialize, Serialize}; use theme::Theme; -mod theme; +pub mod theme; lazy_static::lazy_static!( static ref SETTINGS: Arc> = Arc::new(Mutex::new(Settings::default()));