Skip to main content

lgui_core/core/input/
event_context.rs

1use std::{future::Future, sync::Arc};
2
3use crate::{
4    application::ApplicationContext,
5    window::{WindowHandle, WindowId, WindowManager},
6};
7use crate::{
8    command::{Command, CommandHandle},
9    events::Event,
10};
11
12#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
13pub struct UiEventFlags {
14    pub consumed: bool,
15    pub changed: bool,
16    pub route_changed: bool,
17    pub needs_frame: bool,
18    pub default_prevented: bool,
19}
20
21/// Generic application, Store, Router, task and window access passed to every event handler.
22pub struct UiEventContext {
23    application: ApplicationContext,
24    window: WindowHandle,
25    flags: UiEventFlags,
26    propagation_stopped: bool,
27}
28
29#[derive(Clone)]
30pub struct UiAsyncContext {
31    application: ApplicationContext,
32    window: Option<WindowHandle>,
33}
34
35impl UiEventContext {
36    pub fn new(application: ApplicationContext, window_id: WindowId) -> Self {
37        let window = WindowHandle::new(window_id, application.windows());
38        Self {
39            application,
40            window,
41            flags: UiEventFlags::default(),
42            propagation_stopped: false,
43        }
44    }
45
46    pub fn application(&self) -> ApplicationContext {
47        self.application.clone()
48    }
49
50    pub fn resource<T>(&self) -> Arc<T>
51    where
52        T: Send + Sync + 'static,
53    {
54        self.application.resource::<T>()
55    }
56
57    pub fn try_resource<T>(&self) -> Option<Arc<T>>
58    where
59        T: Send + Sync + 'static,
60    {
61        self.application.try_resource::<T>()
62    }
63
64    pub fn command<C>(&self) -> CommandHandle<C>
65    where
66        C: Command,
67    {
68        self.application.command::<C>()
69    }
70
71    pub fn emit<E>(&self, event: E) -> usize
72    where
73        E: Event,
74    {
75        self.application.emit(event)
76    }
77
78    pub fn spawn(&mut self, task: impl Future<Output = ()> + Send + 'static) -> bool {
79        self.mark_consumed();
80        self.application.spawn(task)
81    }
82
83    pub fn spawn_or_else(
84        &mut self,
85        task: impl Future<Output = ()> + Send + 'static,
86        unavailable: impl FnOnce(),
87    ) {
88        if !self.spawn(task) {
89            unavailable();
90        }
91    }
92
93    pub fn spawn_async<Fut>(&mut self, handler: impl FnOnce(UiAsyncContext) -> Fut + Send + 'static)
94    where
95        Fut: Future<Output = ()> + Send + 'static,
96    {
97        let context = self.async_context();
98        let _ = self.spawn(handler(context));
99    }
100
101    pub fn async_context(&self) -> UiAsyncContext {
102        UiAsyncContext {
103            application: self.application.clone(),
104            window: Some(self.window.clone()),
105        }
106    }
107
108    pub fn window(&self) -> WindowHandle {
109        self.window.clone()
110    }
111
112    pub fn windows(&self) -> WindowManager {
113        self.application.windows()
114    }
115
116    pub fn stop_propagation(&mut self) {
117        self.propagation_stopped = true;
118        self.flags.consumed = true;
119    }
120
121    pub fn prevent_default(&mut self) {
122        self.flags.default_prevented = true;
123        self.flags.consumed = true;
124    }
125
126    pub fn propagation_stopped(&self) -> bool {
127        self.propagation_stopped
128    }
129
130    pub fn default_prevented(&self) -> bool {
131        self.flags.default_prevented
132    }
133
134    pub fn flags(&self) -> UiEventFlags {
135        self.flags
136    }
137
138    pub fn mark_consumed(&mut self) {
139        self.flags.consumed = true;
140    }
141
142    pub fn mark_changed(&mut self, route_changed: bool) {
143        self.flags.consumed = true;
144        self.flags.changed = true;
145        self.flags.route_changed |= route_changed;
146    }
147
148    pub fn request_frame(&mut self) {
149        self.flags.needs_frame = true;
150    }
151}
152
153impl UiAsyncContext {
154    pub(crate) fn application_only(application: ApplicationContext) -> Self {
155        Self {
156            application,
157            window: None,
158        }
159    }
160
161    pub fn application(&self) -> ApplicationContext {
162        self.application.clone()
163    }
164
165    pub fn resource<T>(&self) -> Arc<T>
166    where
167        T: Send + Sync + 'static,
168    {
169        self.application.resource::<T>()
170    }
171
172    pub fn try_resource<T>(&self) -> Option<Arc<T>>
173    where
174        T: Send + Sync + 'static,
175    {
176        self.application.try_resource::<T>()
177    }
178
179    pub fn command<C>(&self) -> CommandHandle<C>
180    where
181        C: Command,
182    {
183        self.application.command::<C>()
184    }
185
186    pub async fn invoke<C>(&self, args: C::Args) -> Result<C::Output, C::Error>
187    where
188        C: Command,
189    {
190        self.application.invoke::<C>(args).await
191    }
192
193    pub fn emit<E>(&self, event: E) -> usize
194    where
195        E: Event,
196    {
197        self.application.emit(event)
198    }
199
200    pub fn window(&self) -> Option<WindowHandle> {
201        self.window.clone()
202    }
203
204    pub fn windows(&self) -> WindowManager {
205        self.application.windows()
206    }
207}
208
209#[cfg(test)]
210#[path = "event_context_test.rs"]
211mod tests;