Skip to main content

appcui/ui/window/
modal_window.rs

1use self::{common::StatusFlags, keyselector::events::KeySelectorEvents};
2
3use super::{events::ModalWindowMethods, Flags, Window};
4use crate::prelude::*;
5use std::ops::{Deref, DerefMut};
6
7#[repr(C)]
8pub struct ModalWindow<T: Sized> {
9    base: Window,
10    result: Option<T>,
11}
12impl<T> Deref for ModalWindow<T> {
13    type Target = Window;
14
15    fn deref(&self) -> &Self::Target {
16        &self.base
17    }
18}
19impl<T> DerefMut for ModalWindow<T> {
20    fn deref_mut(&mut self) -> &mut Self::Target {
21        &mut self.base
22    }
23}
24impl<T> ModalWindow<T> {
25    /// Creates a new Modal Window with the specified title, layout, and flags.
26    /// The window type is set be the one associated with the current theme and the background to `Normal` by default.
27    ///
28    /// A Modal Window does not have an implicit close button
29    /// as exiting has to be done from either `exit(...)` or `exit_with(...)` methods.
30    ///
31    /// # Parameters
32    /// * `title` - The title of the window
33    /// * `layout` - The layout of the window (position and size)
34    /// * `flags` - The initialization flags for the window
35    pub fn new(title: &str, layout: Layout, flags: Flags) -> Self {
36        // a Modal Window does not have an implicit close button
37        // as exiting has to be done from either exit(...) or exit_with(...) method.
38        Self {
39            base: Window::internal_create(
40                title,
41                layout,
42                flags | Flags::NoCloseButton,
43                None,
44                window::Background::Normal,
45                StatusFlags::ModalWindow | StatusFlags::ThemeType,
46            ),
47            result: None,
48        }
49    }
50
51    /// Creates a new Modal Window with the specified title, layout, flags and background.
52    /// The background can be one of `Normal`, `Error`, `Warning` or `Notification`.
53    /// The window type is set be the one associated with the current theme.
54    /// 
55    /// A Modal Window does not have an implicit close button
56    /// as exiting has to be done from either `exit(...)` or `exit_with(...)` methods.
57    /// 
58    /// # Parameters
59    /// * `title` - The title of the window
60    /// * `layout` - The layout of the window (position and size)
61    /// * `flags` - The initialization flags for the window
62    /// * `background` - The background of the window (Normal, Error, Warning, Notification)
63    pub fn with_background(title: &str, layout: Layout, flags: Flags, background: window::Background) -> Self {
64        // a Modal Window does not have an implicit close button
65        // as exiting has to be done from either exit(...) or exit_with(...) method.
66        Self {
67            base: Window::internal_create(
68                title,
69                layout,
70                flags | Flags::NoCloseButton,
71                None,
72                background,
73                StatusFlags::ModalWindow | StatusFlags::ThemeType,
74            ),
75            result: None,
76        }
77    }
78
79    /// Creates a new Modal Window with the specified title, layout, flags, window type and background.
80    /// The window type can be one of `Classic`, `Rounded` or `Panel`.
81    /// The background can be one of `Normal`, `Error`, `Warning` or `Notification`.
82    ///
83    /// A Modal Window does not have an implicit close button
84    /// as exiting has to be done from either `exit(...)` or `exit_with(...)` methods.
85    ///
86    /// # Parameters
87    /// * `title` - The title of the window
88    /// * `layout` - The layout of the window (position and size)
89    /// * `flags` - The initialization flags for the window
90    /// * `window_type` - The type of the window (Classic, Rounded, Panel)
91    /// * `background` - The background of the window (Normal, Error, Warning, Notification)
92    pub fn with_type(title: &str, layout: Layout, flags: Flags, window_type: window::Type, background: window::Background) -> Self {
93        // a Modal Window does not have an implicit close button
94        // as exiting has to be done from either exit(...) or exit_with(...) method.
95        Self {
96            base: Window::internal_create(
97                title,
98                layout,
99                flags | Flags::NoCloseButton,
100                Some(window_type),
101                background,
102                StatusFlags::ModalWindow,
103            ),
104            result: None,
105        }
106    }
107
108    /// Displays the modal window and runs its event loop.
109    /// This method will block until the window is closed, either by calling `exit_with`
110    /// or `exit` methods.
111    /// Returns an `Option<T>` containing the result set by `exit_with` method,
112    /// or `None` if the window was closed using the `exit` method or if it was cancelled.
113    pub fn show<U>(object: U) -> Option<T>
114    where
115        U: Control + WindowControl + ModalWindowMethods<T> + 'static,
116        U: DerefMut<Target = ModalWindow<T>>,
117    {
118        let handle = RuntimeManager::get().add_modal_window(object);
119        // safety check - if we did not manage to add the window
120        if handle.is_none() {
121            return None;
122        }
123        // run the loop (the method will determine if it runs in a modal way or not)
124        RuntimeManager::get().run();
125        // the loop has ended , lets grab the results
126        if let Some(obj) = RuntimeManager::get().get_control_mut(handle) {
127            // move the result
128            return obj.result.take();
129        }
130        None
131    }
132}
133impl<T: 'static> Control for ModalWindow<T> {}
134impl<T> OnThemeChanged for ModalWindow<T> {}
135impl<T> GenericMenuEvents for ModalWindow<T> {}
136impl<T> AppBarEvents for ModalWindow<T> {}
137impl<T> DesktopEvents for ModalWindow<T> {}
138impl<T> ToolBarEvents for ModalWindow<T> {}
139impl<T> WindowEvents for ModalWindow<T> {}
140impl<T> GenericCommandBarEvents for ModalWindow<T> {}
141impl<T> CheckBoxEvents for ModalWindow<T> {}
142impl<T> RadioBoxEvents for ModalWindow<T> {}
143impl<T> PasswordEvents for ModalWindow<T> {}
144impl<T> KeySelectorEvents for ModalWindow<T> {}
145impl<T> TextFieldEvents for ModalWindow<T> {}
146impl<T> ButtonEvents for ModalWindow<T> {}
147impl<T> ToggleButtonEvents for ModalWindow<T> {}
148impl<T> ColorPickerEvents for ModalWindow<T> {}
149impl<T> CharPickerEvents for ModalWindow<T> {}
150impl<T> ComboBoxEvents for ModalWindow<T> {}
151impl<T> DatePickerEvents for ModalWindow<T> {}
152impl<T> TimePickerEvents for ModalWindow<T> {}
153impl<T> ListBoxEvents for ModalWindow<T> {}
154impl<T> CustomEvents for ModalWindow<T> {}
155impl<T> GenericSelectorEvents for ModalWindow<T> {}
156impl<T> GenericDropDownListEvents for ModalWindow<T> {}
157impl<T> GenericNumericSelectorEvents for ModalWindow<T> {}
158impl<T> GenericListViewEvents for ModalWindow<T> {}
159impl<T> GenericTreeViewEvents for ModalWindow<T> {}
160impl<T> GenericBackgroundTaskEvents for ModalWindow<T> {}
161impl<T> GenericGraphViewEvents for ModalWindow<T> {}
162impl<T> OnDefaultAction for ModalWindow<T> {}
163impl<T> WindowControl for ModalWindow<T> {}
164impl<T> OnExpand for ModalWindow<T> {}
165impl<T> ThreeStateBoxEvents for ModalWindow<T> {}
166impl<T> OnSiblingSelected for ModalWindow<T> {}
167impl<T> PathFinderEvents for ModalWindow<T> {}
168impl<T> TimerEvents for ModalWindow<T> {}
169impl<T> MarkdownEvents for ModalWindow<T> {}
170impl<T> AccordionEvents for ModalWindow<T> {}
171impl<T> TabEvents for ModalWindow<T> {}
172
173// events routed to base window
174impl<T> OnFocus for ModalWindow<T> {
175    fn on_focus(&mut self) {
176        OnFocus::on_focus(&mut self.base);
177    }
178
179    fn on_lose_focus(&mut self) {
180        OnFocus::on_lose_focus(&mut self.base);
181    }
182}
183impl<T> OnPaint for ModalWindow<T> {
184    fn on_paint(&self, surface: &mut Surface, theme: &Theme) {
185        OnPaint::on_paint(&self.base, surface, theme);
186    }
187}
188impl<T> OnResize for ModalWindow<T> {
189    fn on_resize(&mut self, old_size: Size, new_size: Size) {
190        OnResize::on_resize(&mut self.base, old_size, new_size);
191    }
192}
193impl<T: 'static> OnKeyPressed for ModalWindow<T> {
194    fn on_key_pressed(&mut self, key: Key, character: char) -> EventProcessStatus {
195        if !self.base.is_in_resize_mode() {
196            match key.value() {
197                key!("Enter") => {
198                    if let Some(interface) = self.interface_mut() {
199                        WindowEvents::on_accept(interface);
200                    }
201                    EventProcessStatus::Processed
202                }
203                key!("Escape") => {
204                    if let Some(interface) = self.interface_mut() {
205                        let result = WindowEvents::on_cancel(interface);
206                        if result == ActionRequest::Allow {
207                            // force the exit with None
208                            self.exit();
209                        } else {
210                            // clean the result
211                            self.result = None;
212                            RuntimeManager::get().cancel_exit_from_execution_loop();
213                        }
214                    }
215                    EventProcessStatus::Processed
216                }
217                _ => OnKeyPressed::on_key_pressed(&mut self.base, key, character),
218            }
219        } else {
220            OnKeyPressed::on_key_pressed(&mut self.base, key, character)
221        }
222    }
223}
224impl<T> OnMouseEvent for ModalWindow<T> {
225    fn on_mouse_event(&mut self, event: &MouseEvent) -> EventProcessStatus {
226        OnMouseEvent::on_mouse_event(&mut self.base, event)
227    }
228}
229impl<T> OnWindowRegistered for ModalWindow<T> {
230    fn on_registered(&mut self) {
231        self.base.on_registered();
232    }
233}
234impl<T: 'static> ModalWindowMethods<T> for ModalWindow<T> {
235    fn show(self) -> Option<T> {
236        // do nothing
237        None
238    }
239
240    fn exit_with(&mut self, result: T) {
241        self.result = Some(result);
242        RuntimeManager::get().exit_execution_loop();
243    }
244
245    fn exit(&mut self) {
246        self.result = None;
247        RuntimeManager::get().exit_execution_loop();
248    }
249
250    fn close(&mut self) {
251        self.exit();
252    }
253}