115 lines
3.9 KiB
Rust
115 lines
3.9 KiB
Rust
use std::{collections::{HashMap, HashSet}, sync::{Arc, Mutex}};
|
|
use egui::{ViewportBuilder, ViewportId};
|
|
use crate::GuiState;
|
|
|
|
#[cfg(debug_assertions)]
|
|
pub mod debug;
|
|
pub mod error;
|
|
pub mod settings;
|
|
pub mod add_song;
|
|
pub mod new_song;
|
|
pub mod new_playlist;
|
|
|
|
lazy_static::lazy_static!(
|
|
pub static ref WINDOWS: Arc<Mutex<HashMap<WindowId, Box<dyn Window>>>> = Arc::new(Mutex::new(HashMap::new()));
|
|
static ref OPEN_WINDOWS: Arc<Mutex<HashSet<WindowId>>> = Arc::new(Mutex::new(HashSet::new()));
|
|
);
|
|
|
|
pub trait Window: std::fmt::Debug + Send {
|
|
fn draw(&mut self, ui: &mut egui::Ui, state: &mut GuiState) -> crate::Result<()>;
|
|
fn id() -> WindowId where Self: Sized;
|
|
fn default_title() -> &'static str where Self: Sized;
|
|
fn close(&self) where Self: Sized{
|
|
OPEN_WINDOWS.lock().unwrap().remove(&Self::id());
|
|
}
|
|
fn set_value<V>(&mut self, k: String, v: Box<V>) where Self: Sized;
|
|
}
|
|
|
|
#[derive(Debug, Clone, Hash, PartialEq, PartialOrd, Ord, Eq)]
|
|
pub enum WindowId {
|
|
Settings,
|
|
Error,
|
|
#[cfg(debug_assertions)]
|
|
Debug,
|
|
NewPlaylist,
|
|
NewSong,
|
|
AddSongToPl,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct Windows {
|
|
windows: HashMap<WindowId, (ViewportId, ViewportBuilder)>,
|
|
}
|
|
|
|
impl Windows {
|
|
pub fn new() -> Self {
|
|
let mut s = Self {
|
|
windows: HashMap::new(),
|
|
};
|
|
s.add_all_windows();
|
|
s
|
|
}
|
|
|
|
pub fn add_all_windows(&mut self) {
|
|
#[cfg(debug_assertions)]
|
|
self.add_new_window::<debug::DebugW>();
|
|
self.add_new_window::<error::ErrorW>();
|
|
self.add_new_window::<settings::SettingsW>();
|
|
self.add_new_window::<add_song::AddSongW>();
|
|
self.add_new_window::<new_song::NewSongW>();
|
|
self.add_new_window::<new_playlist::NewPlaylistW>();
|
|
}
|
|
|
|
pub fn add_new_window<WT: Window + Default + 'static>(&mut self) {
|
|
let builder = ViewportBuilder::default()
|
|
.with_window_type(egui::X11WindowType::Dialog)
|
|
.with_title(WT::default_title());
|
|
self.windows.insert(WT::id(), (ViewportId::from_hash_of(WT::id()), builder));
|
|
WINDOWS.lock().unwrap().insert(WT::id(), Box::<WT>::default());
|
|
}
|
|
|
|
pub fn draw_all(ctx: &egui::Context, state: &mut GuiState) {
|
|
let theme = handle_error_ui!(xmpd_settings::Settings::get()).theme.clone();
|
|
for (win_id, (vp_id, builder)) in state.windows.windows.clone().into_iter() {
|
|
if state.windows.is_open(&win_id) {
|
|
ctx.show_viewport_immediate(vp_id.clone(), builder.clone(), |ctx, _vp_class| {
|
|
ctx.input(|inp| {
|
|
state.windows.toggle(&win_id, !inp.viewport().close_requested());
|
|
});
|
|
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)
|
|
})
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn toggle(&self, id: &WindowId, status: bool) {
|
|
if status {
|
|
OPEN_WINDOWS.lock().unwrap().insert(id.clone());
|
|
} else {
|
|
OPEN_WINDOWS.lock().unwrap().remove(id);
|
|
}
|
|
}
|
|
|
|
pub fn is_open(&self, id: &WindowId) -> bool {
|
|
OPEN_WINDOWS.lock().unwrap().contains(&id)
|
|
}
|
|
|
|
pub fn set_value(&self, id: &WindowId, k: impl ToString, v: impl ToString) -> crate::Result<()> {
|
|
// WINDOWS.lock().unwrap().get_mut(&win_id).unwrap().set_value();
|
|
//
|
|
Ok(())
|
|
}
|
|
}
|