Settings panel ui
This commit is contained in:
parent
a060161c64
commit
b29caa58b4
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +1,2 @@
|
||||||
/target/
|
/target/
|
||||||
|
settings.toml
|
||||||
|
|
|
@ -43,7 +43,7 @@ impl CompUi for LeftNav {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_playlist_tab(ui: &mut egui::Ui, pid: &Option<uuid::Uuid>, title: &str, author: Option<&str>, song_count: usize, width: f32) {
|
fn add_playlist_tab(ui: &mut egui::Ui, pid: &Option<uuid::Uuid>, 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| {
|
let wdg_rect = ui.horizontal(|ui| {
|
||||||
ui.set_width(width);
|
ui.set_width(width);
|
||||||
ui.add_space(5.0);
|
ui.add_space(5.0);
|
||||||
|
@ -63,6 +63,7 @@ fn add_playlist_tab(ui: &mut egui::Ui, pid: &Option<uuid::Uuid>, title: &str, au
|
||||||
} else {
|
} else {
|
||||||
ui.label(
|
ui.label(
|
||||||
RichText::new(title)
|
RichText::new(title)
|
||||||
|
.color(theme.text_color)
|
||||||
.size(10.0)
|
.size(10.0)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,10 +59,10 @@ impl CompUi for SongList {
|
||||||
let query = {handle_error_ui!(song_list_nav::SongListNav::get()).parse_search()}.clone();
|
let query = {handle_error_ui!(song_list_nav::SongListNav::get()).parse_search()}.clone();
|
||||||
for (sid, song) in songs {
|
for (sid, song) in songs {
|
||||||
let should_display = match query {
|
let should_display = match query {
|
||||||
SearchType::Source(ref s) if !s.is_empty() && format!("{:?}", &song.source_type()).to_lowercase().contains(s) => true,
|
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) => true,
|
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,
|
SearchType::Name(ref s) if !s.is_empty() => song.name().to_owned().contains(s),
|
||||||
_ => false
|
_ => true
|
||||||
};
|
};
|
||||||
if should_display {
|
if should_display {
|
||||||
display_song_tab(ui, sid, song);
|
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| {
|
ui.vertical(|ui| {
|
||||||
let selected_song_id = {handle_error_ui!(SongList::get()).selected_song_id};
|
let selected_song_id = {handle_error_ui!(SongList::get()).selected_song_id};
|
||||||
if selected_song_id == *sid {
|
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 {
|
} else {
|
||||||
ui.label(song.name());
|
ui.label(
|
||||||
|
RichText::new(song.name())
|
||||||
|
.color(theme.text_color)
|
||||||
|
);
|
||||||
};
|
};
|
||||||
ui.monospace(
|
ui.monospace(
|
||||||
RichText::new(format!("By {}", song.author()))
|
RichText::new(format!("By {}", song.author()))
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use crate::windows::WindowId;
|
||||||
|
|
||||||
use super::CompUi;
|
use super::CompUi;
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
@ -11,8 +13,7 @@ impl CompUi for TopNav {
|
||||||
egui::menu::bar(ui, |ui| {
|
egui::menu::bar(ui, |ui| {
|
||||||
ui.menu_button("File", |ui| {
|
ui.menu_button("File", |ui| {
|
||||||
if ui.button("Settings").clicked() {
|
if ui.button("Settings").clicked() {
|
||||||
|
state.windows.toggle(&WindowId::Settings, true);
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ui.menu_button("Manifest", |ui| {
|
ui.menu_button("Manifest", |ui| {
|
||||||
|
|
|
@ -21,20 +21,8 @@ pub fn start(manifest_path: PathBuf) -> Result<()> {
|
||||||
let theme = xmpd_settings::Settings::get()?.theme.clone();
|
let theme = xmpd_settings::Settings::get()?.theme.clone();
|
||||||
let res = eframe::run_simple_native(W_NAME, options, move |ctx, _frame| {
|
let res = eframe::run_simple_native(W_NAME, options, move |ctx, _frame| {
|
||||||
egui_extras::install_image_loaders(ctx);
|
egui_extras::install_image_loaders(ctx);
|
||||||
state.windows.clone().draw_all(ctx, &mut state);
|
state.windows.clone().draw_all(ctx, &mut state);
|
||||||
egui::CentralPanel::default()
|
handle_error_ui!(main_window::draw(ctx, &mut state));
|
||||||
.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)
|
|
||||||
});
|
|
||||||
ctx.request_repaint_after(Duration::from_millis(500));
|
ctx.request_repaint_after(Duration::from_millis(500));
|
||||||
});
|
});
|
||||||
if let Err(e) = res { // dumb err value by eframe
|
if let Err(e) = res { // dumb err value by eframe
|
||||||
|
|
|
@ -1,49 +1,66 @@
|
||||||
|
use xmpd_settings::theme::Theme;
|
||||||
|
|
||||||
use crate::{components::CompUi, GuiState};
|
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
|
// The central panel the region left after adding TopPanel's and SidePanel's
|
||||||
// ui.heading(format!("Songs ({})", self.manifest.get_song_count()));
|
// ui.heading(format!("Songs ({})", self.manifest.get_song_count()));
|
||||||
let theme = xmpd_settings::Settings::get()?.theme.clone();
|
let theme = xmpd_settings::Settings::get()?.theme.clone();
|
||||||
let avail = ui.available_size();
|
egui::TopBottomPanel::new(egui::panel::TopBottomSide::Top, "top_nav")
|
||||||
ui.vertical(|ui| {
|
.frame(get_themed_frame(&theme))
|
||||||
handle_error_ui!(crate::components::top_nav::TopNav::draw(ui, state));
|
.show(ctx, |ui| {
|
||||||
crate::utils::super_separator(ui, theme.accent_color, avail.x, 2.0);
|
ui.style_mut().visuals.override_text_color = Some(theme.text_color);
|
||||||
let avail = ui.available_size();
|
handle_error_ui!(crate::components::top_nav::TopNav::draw(ui, state));
|
||||||
let main_height = avail.y * 0.91;
|
}
|
||||||
|
);
|
||||||
ui.horizontal(|ui| {
|
egui::CentralPanel::default()
|
||||||
ui.set_height(main_height);
|
.frame(get_themed_frame(&theme))
|
||||||
ui.group(|ui| {
|
.show(ctx, |ui| {
|
||||||
ui.set_height(main_height);
|
let avail = ui.available_size();
|
||||||
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.vertical(|ui| {
|
||||||
ui.group(|ui| {
|
crate::utils::super_separator(ui, theme.accent_color, avail.x, 2.0);
|
||||||
ui.set_width(avail.x * 0.75);
|
let avail = ui.available_size();
|
||||||
handle_error_ui!(crate::components::song_list::song_list_nav::SongListNav::draw(ui, state));
|
let main_height = avail.y * 0.91;
|
||||||
});
|
|
||||||
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| {
|
|
||||||
|
|
||||||
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));
|
handle_error_ui!(crate::components::player::Player::draw(ui, state));
|
||||||
});
|
}
|
||||||
});
|
);
|
||||||
Ok(())
|
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,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ pub struct ErrorW {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Window for 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!");
|
ui.label("Hello from other window!");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ lazy_static::lazy_static!(
|
||||||
);
|
);
|
||||||
|
|
||||||
pub trait Window: std::fmt::Debug + Send {
|
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)]
|
#[derive(Debug, Clone, Hash, PartialEq, PartialOrd, Ord, Eq)]
|
||||||
|
@ -36,25 +36,38 @@ impl Windows {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_all_windows(&mut self) {
|
pub fn add_all_windows(&mut self) {
|
||||||
self.add_new_window(WindowId::Error, "Error!", Box::<error::ErrorW>::default())
|
self.add_new_window(WindowId::Error, "Error!", Box::<error::ErrorW>::default());
|
||||||
|
self.add_new_window(WindowId::Settings, "Settings", Box::<settings::SettingsW>::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_new_window(&mut self, id: WindowId, title: &str, cb: Box<dyn Window>) {
|
pub fn add_new_window(&mut self, id: WindowId, title: &str, cb: Box<dyn Window>) {
|
||||||
let builder = ViewportBuilder::default()
|
let builder = ViewportBuilder::default()
|
||||||
|
.with_window_type(egui::X11WindowType::Dialog)
|
||||||
.with_title(title);
|
.with_title(title);
|
||||||
self.windows.insert(id.clone(), (ViewportId::from_hash_of(id.clone()), builder));
|
self.windows.insert(id.clone(), (ViewportId::from_hash_of(id.clone()), builder));
|
||||||
WINDOWS.lock().unwrap().insert(id, cb);
|
WINDOWS.lock().unwrap().insert(id, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_all(&mut self, ctx: &egui::Context, state: &mut GuiState) {
|
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 {
|
for (win_id, (vp_id, builder)) in &self.windows {
|
||||||
if self.is_open(&win_id) {
|
if self.is_open(&win_id) {
|
||||||
ctx.show_viewport_immediate(vp_id.clone(), builder.clone(), |ctx, _vp_class| {
|
ctx.show_viewport_immediate(vp_id.clone(), builder.clone(), |ctx, _vp_class| {
|
||||||
ctx.input(|inp| {
|
ctx.input(|inp| {
|
||||||
self.toggle(win_id, !inp.viewport().close_requested());
|
self.toggle(win_id, !inp.viewport().close_requested());
|
||||||
});
|
});
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default()
|
||||||
WINDOWS.lock().unwrap().get(&win_id).unwrap().draw(ui, state)
|
.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)
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,49 @@ use super::Window;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct SettingsW {
|
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 {
|
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(())
|
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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::{path::PathBuf, sync::{Arc, Mutex, MutexGuard}};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use theme::Theme;
|
use theme::Theme;
|
||||||
|
|
||||||
mod theme;
|
pub mod theme;
|
||||||
|
|
||||||
lazy_static::lazy_static!(
|
lazy_static::lazy_static!(
|
||||||
static ref SETTINGS: Arc<Mutex<Settings>> = Arc::new(Mutex::new(Settings::default()));
|
static ref SETTINGS: Arc<Mutex<Settings>> = Arc::new(Mutex::new(Settings::default()));
|
||||||
|
|
Loading…
Reference in New Issue
Block a user