Skip to main content

lgui_core/window/
manager.rs

1use std::sync::{Arc, RwLock};
2
3use crate::{
4    core::{Element, InputEvent, RenderCx},
5    platform::dpi::ScalePreference,
6};
7
8use super::{WindowCommand, WindowId, WindowMode, WindowOptions};
9
10type WindowCommandHandler = Arc<dyn Fn(WindowCommand) + Send + Sync>;
11
12#[derive(Clone)]
13pub struct WindowManager {
14    inner: Arc<WindowManagerInner>,
15}
16
17struct WindowManagerInner {
18    command: RwLock<Option<WindowCommandHandler>>,
19}
20
21impl WindowManager {
22    pub(crate) fn new() -> Self {
23        Self {
24            inner: Arc::new(WindowManagerInner {
25                command: RwLock::new(None),
26            }),
27        }
28    }
29
30    pub(crate) fn install(&self, command: impl Fn(WindowCommand) + Send + Sync + 'static) {
31        *self.inner.command.write().expect("window manager poisoned") = Some(Arc::new(command));
32    }
33
34    pub fn show(
35        &self,
36        options: WindowOptions,
37        view: impl for<'scope, 'context> Fn(&mut RenderCx<'scope, 'context>) -> Element
38            + Send
39            + Sync
40            + 'static,
41    ) -> bool {
42        self.send(WindowCommand::Show {
43            options,
44            view: Arc::new(view),
45        })
46    }
47
48    pub fn hide(&self, id: impl Into<WindowId>) -> bool {
49        self.send(WindowCommand::Hide(id.into()))
50    }
51
52    pub fn toggle(
53        &self,
54        options: WindowOptions,
55        view: impl for<'scope, 'context> Fn(&mut RenderCx<'scope, 'context>) -> Element
56            + Send
57            + Sync
58            + 'static,
59    ) -> bool {
60        self.send(WindowCommand::Toggle {
61            options,
62            view: Arc::new(view),
63        })
64    }
65
66    pub fn close(&self, id: impl Into<WindowId>) -> bool {
67        self.send(WindowCommand::Close(id.into()))
68    }
69
70    pub fn request_close(&self, id: impl Into<WindowId>) -> bool {
71        self.send(WindowCommand::RequestClose(id.into()))
72    }
73
74    pub fn minimize(&self, id: impl Into<WindowId>) -> bool {
75        self.send(WindowCommand::Minimize(id.into()))
76    }
77
78    pub fn set_scale_preference(&self, preference: ScalePreference) -> bool {
79        self.send(WindowCommand::SetScalePreference(preference))
80    }
81
82    pub fn set_mode(&self, id: impl Into<WindowId>, mode: WindowMode) -> bool {
83        self.send(WindowCommand::SetMode {
84            id: id.into(),
85            mode,
86        })
87    }
88
89    pub fn send_input(&self, id: impl Into<WindowId>, input: InputEvent) -> bool {
90        self.send(WindowCommand::Input {
91            id: id.into(),
92            input,
93        })
94    }
95
96    pub fn exit(&self) -> bool {
97        self.send(WindowCommand::Exit)
98    }
99
100    fn send(&self, command: WindowCommand) -> bool {
101        let handler = self
102            .inner
103            .command
104            .read()
105            .expect("window manager poisoned")
106            .clone();
107        let Some(handler) = handler else {
108            return false;
109        };
110        handler(command);
111        true
112    }
113}
114
115impl PartialEq for WindowManager {
116    fn eq(&self, other: &Self) -> bool {
117        Arc::ptr_eq(&self.inner, &other.inner)
118    }
119}
120
121#[derive(Clone)]
122pub struct WindowHandle {
123    id: WindowId,
124    windows: WindowManager,
125}
126
127impl WindowHandle {
128    pub(crate) fn new(id: WindowId, windows: WindowManager) -> Self {
129        Self { id, windows }
130    }
131
132    pub fn id(&self) -> &WindowId {
133        &self.id
134    }
135
136    pub fn close(&self) -> bool {
137        self.windows.close(self.id.clone())
138    }
139
140    pub fn request_close(&self) -> bool {
141        self.windows.request_close(self.id.clone())
142    }
143
144    pub fn minimize(&self) -> bool {
145        self.windows.minimize(self.id.clone())
146    }
147
148    pub fn hide(&self) -> bool {
149        self.windows.hide(self.id.clone())
150    }
151
152    pub fn set_mode(&self, mode: WindowMode) -> bool {
153        self.windows.set_mode(self.id.clone(), mode)
154    }
155}