soundboard/src/ui.rs
2024-06-10 23:51:47 +02:00

208 lines
7.0 KiB
Rust

use eframe::egui;
use raw_window_handle::{HasWindowHandle, RawWindowHandle};
use std::borrow::BorrowMut;
use std::sync::Mutex;
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
};
use tokio::sync::mpsc;
use tray_item::TrayItem;
use crate::server::{ServerMessage, ServerSettings};
pub enum UIMessage {
ServerHasQuit,
}
pub fn run_ui(
settings: Arc<Mutex<ServerSettings>>,
should_run: Arc<Mutex<bool>>,
tx: mpsc::Sender<ServerMessage>,
rx: mpsc::Receiver<UIMessage>,
) {
// Initialize visibility as AtomicBool
let visible = Arc::new(AtomicBool::new(true));
let icon = crate::icon::load_app_icon("icon-soundboard");
let native_options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default().with_icon(icon),
..Default::default()
};
let visible_for_tray = Arc::clone(&visible);
eframe::run_native(
"App",
native_options,
Box::new(|cc| {
let window_handle = cc.window_handle().unwrap();
let window_handle = window_handle.as_raw();
let mut tray = TrayItem::new(
"Soundboard",
tray_item::IconSource::Resource("icon-soundboard"),
)
.unwrap();
if let RawWindowHandle::Win32(handle) = window_handle {
#[cfg(windows)]
{
use windows::Win32::Foundation::HWND;
use windows::Win32::UI::WindowsAndMessaging::{
ShowWindow, SW_HIDE, SW_RESTORE,
};
tray.add_label("Server Control").unwrap();
let window_handle = HWND(handle.hwnd.into());
tray.add_menu_item("Show/Hide", {
//let visible_for_tray = Arc::clone(&visible_for_tray);
move || {
let is_visible = visible_for_tray.load(Ordering::SeqCst);
if is_visible {
unsafe {
_ = ShowWindow(window_handle, SW_HIDE);
}
visible_for_tray.store(false, Ordering::SeqCst);
} else {
unsafe {
_ = ShowWindow(window_handle, SW_RESTORE);
}
visible_for_tray.store(true, Ordering::SeqCst);
}
}
})
.unwrap();
}
} else {
println!("Unsupported platform for tray icon.");
}
let my_tx = tx.clone();
tray.add_menu_item("Quit", move || {
my_tx.try_send(ServerMessage::Shutdown).unwrap_or_else(|_| {
eprintln!("Failed to send Shutdown message");
});
//std::process::exit(0);
})
.unwrap();
let app = NativeApp {
settings,
should_run,
tx,
rx,
tray,
};
Box::new(app)
}),
)
.expect("Error running UI.");
}
struct NativeApp {
settings: Arc<Mutex<ServerSettings>>,
#[allow(dead_code)]
should_run: Arc<Mutex<bool>>,
tx: mpsc::Sender<ServerMessage>,
rx: mpsc::Receiver<UIMessage>,
#[allow(dead_code)]
tray: TrayItem,
}
impl eframe::App for NativeApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
if let Ok(message) = self.rx.try_recv() {
match message {
UIMessage::ServerHasQuit => {
eprintln!("Server has quit!!!?");
}
_ => {}
}
}
egui::CentralPanel::default().show(ctx, |ui| {
egui::TopBottomPanel::top("top_panel")
.resizable(true)
.min_height(32.0)
.show_inside(ui, |ui| {
egui::ScrollArea::vertical().show(ui, |ui| {
ui.vertical_centered(|ui| {
ui.heading("Soundboard");
});
});
});
egui::SidePanel::left("left_panel")
.resizable(true)
.default_width(180.0)
.width_range(80.0..=220.0)
.show_inside(ui, |ui| {
ui.vertical_centered(|ui| {
ui.vertical(|ui| {
ui.heading("Menu");
if ui.button("Status").clicked() {}
if ui.button("Devices").clicked() {}
if ui.button("Pages").clicked() {}
if ui.button("Server Settings").clicked() {}
if ui.button("Sound Settings").clicked() {}
});
});
egui::ScrollArea::vertical().show(ui, |ui| {});
});
let mut settings = self.settings.lock().unwrap();
ui.heading("Server Settings");
egui::Frame {
inner_margin: 12.0.into(),
outer_margin: 24.0.into(),
rounding: 14.0.into(),
shadow: egui::epaint::Shadow::NONE,
fill: egui::Color32::from_rgba_unmultiplied(97, 0, 255, 128),
stroke: egui::Stroke::new(1.0, egui::Color32::GRAY),
}
.show(ui, |ui| {
ui.label(egui::RichText::new("3311").color(egui::Color32::WHITE));
});
ui.horizontal(|ui| {
ui.label("Port:");
if ui.text_edit_singleline(&mut settings.port).changed() {}
});
if ui.button("Apply").clicked() {
if self
.tx
.try_send(ServerMessage::UpdateSettings(settings.clone()))
.is_err()
{
eprintln!("Failed to send settings update");
}
}
if ui.button("Interact").clicked() {
if self.tx.try_send(ServerMessage::Interact).is_err() {
eprintln!("Failed to send interaction message");
}
}
if ui.button("Shutdown Server").clicked() {
if self.tx.try_send(ServerMessage::Shutdown).is_err() {
eprintln!("Failed to send shutdown message");
}
}
drop(settings);
});
}
fn on_exit(&mut self, _gl: Option<&eframe::glow::Context>) {
if self.tx.try_send(ServerMessage::Shutdown).is_err() {
eprintln!("Failed to send shutdown message");
}
}
}