use super::config::WindowConfig;
use crate::gui::content::Content;
use crate::gui::effect::{PresetEffect, PresetEffectOptions};
use crate::gui::menu_bar::{MenuBarIcon, MenuBarItem};
use crate::gui::widget::{WidgetDef, WidgetEvent};
use std::sync::mpsc::{Receiver, Sender, channel};
use std::sync::{Arc, RwLock};
use winit::window::WindowId;
#[derive(Debug, Clone, Default)]
pub struct FileDialogOptions {
pub title: Option<String>,
pub directory: Option<String>,
pub default_name: Option<String>,
pub filters: Vec<(String, Vec<String>)>,
pub multiple: bool,
}
#[derive(Debug, Clone)]
pub struct FileDialogResult {
pub paths: Vec<String>,
pub cancelled: bool,
}
pub type WidgetEventSender = Sender<(String, WidgetEvent)>;
pub enum WindowCommand {
Create { config: WindowConfig, effect: Option<(PresetEffect, PresetEffectOptions)> },
Close { id: WindowId },
CloseByName { name: String },
UpdateEffectOptions { id: WindowId, options: PresetEffectOptions },
CloseAll,
AddMenuBarItem { item: MenuBarItem },
RemoveMenuBarItem { id: String },
UpdateMenuBarIcon { id: String, icon: MenuBarIcon },
UpdateMenuBarTooltip { id: String, tooltip: String },
UpdateContent { id: WindowId, content: Option<Content> },
StartScreenshotMode { enabled_actions: Vec<String> },
ExitScreenshotMode,
ExitApplication,
StartClickHelperMode,
ExitClickHelperMode,
SetWidgetContent { id: WindowId, content: WidgetDef },
UpdateWidget { widget_id: String, update: WidgetUpdate },
RegisterEventCallback { window_name: String, event_sender: WidgetEventSender },
ShowOpenFileDialog { request_id: String, window_name: String, options: FileDialogOptions },
ShowSaveFileDialog { request_id: String, window_name: String, options: FileDialogOptions },
ShowFolderDialog { request_id: String, window_name: String, options: FileDialogOptions },
}
impl std::fmt::Debug for WindowCommand {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Create { config, effect } => {
f.debug_struct("Create").field("config", config).field("effect", effect).finish()
}
Self::Close { id } => f.debug_struct("Close").field("id", id).finish(),
Self::CloseByName { name } => {
f.debug_struct("CloseByName").field("name", name).finish()
}
Self::UpdateEffectOptions { id, options } => f
.debug_struct("UpdateEffectOptions")
.field("id", id)
.field("options", options)
.finish(),
Self::CloseAll => write!(f, "CloseAll"),
Self::AddMenuBarItem { item } => {
f.debug_struct("AddMenuBarItem").field("item", item).finish()
}
Self::RemoveMenuBarItem { id } => {
f.debug_struct("RemoveMenuBarItem").field("id", id).finish()
}
Self::UpdateMenuBarIcon { id, icon } => {
f.debug_struct("UpdateMenuBarIcon").field("id", id).field("icon", icon).finish()
}
Self::UpdateMenuBarTooltip { id, tooltip } => f
.debug_struct("UpdateMenuBarTooltip")
.field("id", id)
.field("tooltip", tooltip)
.finish(),
Self::UpdateContent { id, content } => {
f.debug_struct("UpdateContent").field("id", id).field("content", content).finish()
}
Self::StartScreenshotMode { enabled_actions } => f
.debug_struct("StartScreenshotMode")
.field("enabled_actions", enabled_actions)
.finish(),
Self::ExitScreenshotMode => write!(f, "ExitScreenshotMode"),
Self::ExitApplication => write!(f, "ExitApplication"),
Self::StartClickHelperMode => write!(f, "StartClickHelperMode"),
Self::ExitClickHelperMode => write!(f, "ExitClickHelperMode"),
Self::SetWidgetContent { id, content } => f
.debug_struct("SetWidgetContent")
.field("id", id)
.field("content", content)
.finish(),
Self::UpdateWidget { widget_id, update } => f
.debug_struct("UpdateWidget")
.field("widget_id", widget_id)
.field("update", update)
.finish(),
Self::RegisterEventCallback { window_name, .. } => f
.debug_struct("RegisterEventCallback")
.field("window_name", window_name)
.field("event_sender", &"<Sender>")
.finish(),
Self::ShowOpenFileDialog { request_id, window_name, options } => f
.debug_struct("ShowOpenFileDialog")
.field("request_id", request_id)
.field("window_name", window_name)
.field("options", options)
.finish(),
Self::ShowSaveFileDialog { request_id, window_name, options } => f
.debug_struct("ShowSaveFileDialog")
.field("request_id", request_id)
.field("window_name", window_name)
.field("options", options)
.finish(),
Self::ShowFolderDialog { request_id, window_name, options } => f
.debug_struct("ShowFolderDialog")
.field("request_id", request_id)
.field("window_name", window_name)
.field("options", options)
.finish(),
}
}
}
pub type CommandSender = Sender<WindowCommand>;
pub type CommandReceiver = Receiver<WindowCommand>;
pub fn create_command_channel() -> (CommandSender, CommandReceiver) {
channel()
}
#[derive(Debug, Clone)]
pub struct WindowInfo {
pub id: WindowId,
pub name: String,
pub size: (u32, u32),
pub effect: Option<PresetEffect>,
pub options: Option<PresetEffectOptions>,
}
#[derive(Debug, Clone, Default)]
pub struct WindowRegistry {
windows: Arc<RwLock<Vec<WindowInfo>>>,
next_id: Arc<RwLock<usize>>,
}
impl WindowRegistry {
pub fn new() -> Self {
Self::default()
}
pub fn register(
&self,
id: WindowId,
name: String,
size: (u32, u32),
effect: Option<PresetEffect>,
options: Option<PresetEffectOptions>,
) {
let mut windows = self.windows.write().unwrap();
windows.push(WindowInfo { id, name, size, effect, options });
}
pub fn unregister(&self, id: WindowId) {
let mut windows = self.windows.write().unwrap();
windows.retain(|w| w.id != id);
}
pub fn list(&self) -> Vec<WindowInfo> {
self.windows.read().unwrap().clone()
}
pub fn generate_name(&self) -> String {
let mut id = self.next_id.write().unwrap();
let name = format!("Window {}", *id + 1);
*id += 1;
name
}
pub fn find_by_name(&self, name: &str) -> Option<WindowId> {
let windows = self.windows.read().unwrap();
windows.iter().find(|w| w.name == name).map(|w| w.id)
}
pub fn update_options(&self, id: WindowId, options: PresetEffectOptions) {
let mut windows = self.windows.write().unwrap();
if let Some(window) = windows.iter_mut().find(|w| w.id == id) {
window.options = Some(options);
}
}
pub fn clear(&self) {
self.windows.write().unwrap().clear();
}
}
#[derive(Debug, Clone)]
pub enum WidgetUpdate {
SetText(String),
SetChecked(bool),
SetValue(f32),
SetVisible(bool),
SetEnabled(bool),
}