vizia_core/events/event.rs
1use crate::entity::Entity;
2use std::time::Instant;
3use std::{any::Any, cmp::Ordering, fmt::Debug};
4use vizia_id::GenerationalId;
5
6/// Determines how an event propagates through the tree.
7#[derive(Debug, Clone, Copy, PartialEq)]
8pub enum Propagation {
9 // /// Events propagate down the tree to the target entity, e.g. from grand-parent to parent to child (target)
10 // Down,
11 /// Events propagate up the tree from the target entity from ancestor to ancestor, e.g. from child (target) to parent to grand-parent etc.
12 Up,
13 // /// Events propagate down the tree to the target entity and then back up to the root
14 // DownUp,
15 /// Events propagate starting at the target entity and visiting every entity that is a descendent of the target.
16 Subtree,
17 /// Events propagate directly to the target entity and to no others.
18 Direct,
19}
20
21/// A wrapper around a message, providing metadata on how the event travels through the view tree.
22pub struct Event {
23 /// The meta data of the event
24 pub(crate) meta: EventMeta,
25 /// The message of the event
26 pub(crate) message: Option<Box<dyn Any>>,
27}
28
29/// A sendable event payload used by context proxies to forward events from non-UI threads.
30pub struct ProxyEvent {
31 /// The meta data of the event
32 pub(crate) meta: EventMeta,
33 /// The sendable message payload
34 pub(crate) message: Option<Box<dyn Any + Send>>,
35}
36
37impl Debug for Event {
38 fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39 Ok(())
40 }
41}
42
43impl Debug for ProxyEvent {
44 fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45 Ok(())
46 }
47}
48
49impl Event {
50 /// Creates a new event with a specified message.
51 pub fn new<M>(message: M) -> Self
52 where
53 M: Any,
54 {
55 Event { meta: Default::default(), message: Some(Box::new(message)) }
56 }
57
58 /// Sets the target of the event.
59 pub fn target(mut self, entity: Entity) -> Self {
60 self.meta.target = entity;
61 self
62 }
63
64 /// Sets the origin of the event.
65 pub fn origin(mut self, entity: Entity) -> Self {
66 self.meta.origin = entity;
67 self
68 }
69
70 /// Sets the propagation of the event.
71 pub fn propagate(mut self, propagation: Propagation) -> Self {
72 self.meta.propagation = propagation;
73 self
74 }
75
76 /// Sets the propagation to directly target the `entity`.
77 pub fn direct(mut self, entity: Entity) -> Self {
78 self.meta.propagation = Propagation::Direct;
79 self.meta.target = entity;
80 self
81 }
82
83 /// Consumes the event to prevent it from continuing on its propagation path.
84 pub fn consume(&mut self) {
85 self.meta.consume();
86 }
87
88 /// Tries to downcast the event message to the specified type. If the downcast was successful,
89 /// the message and the event metadata get passed into `f`.
90 ///
91 /// # Example
92 /// ```no_run
93 /// # use vizia_core::prelude::*;
94 /// # let cx = &mut Context::default();
95 /// # use vizia_winit::application::Application;
96 /// # pub struct AppData {
97 /// # count: i32,
98 /// # }
99 /// # pub enum AppEvent {
100 /// # Increment,
101 /// # Decrement,
102 /// # }
103 /// # impl Model for AppData {
104 /// # fn event(&mut self, _cx: &mut EventContext, event: &mut Event) {
105 /// event.map(|app_event, _| match app_event {
106 /// AppEvent::Increment => {
107 /// self.count += 1;
108 /// }
109 ///
110 /// AppEvent::Decrement => {
111 /// self.count -= 1;
112 /// }
113 /// });
114 /// # }
115 /// # }
116 /// ```
117 pub fn map<M, F>(&mut self, f: F)
118 where
119 M: Any,
120 F: FnOnce(&M, &mut EventMeta),
121 {
122 if let Some(message) = &self.message {
123 if let Some(message) = message.as_ref().downcast_ref() {
124 (f)(message, &mut self.meta);
125 }
126 }
127 }
128
129 /// Tries to downcast the event message to the specified type. If the downcast was successful,
130 /// return the message by value and consume the event. Otherwise, do nothing.
131 ///
132 /// # Example
133 /// ```
134 /// # use vizia_core::prelude::*;
135 /// # let cx = &mut Context::default();
136 /// # use vizia_winit::application::Application;
137 /// # pub struct AppData {
138 /// # count: i32,
139 /// # }
140 /// # pub enum AppEvent {
141 /// # Increment,
142 /// # Decrement,
143 /// # }
144 /// # impl Model for AppData {
145 /// # fn event(&mut self, _cx: &mut EventContext, event: &mut Event) {
146 /// event.take(|app_event, meta| match app_event {
147 /// AppEvent::Increment => {
148 /// self.count += 1;
149 /// }
150 ///
151 /// AppEvent::Decrement => {
152 /// self.count -= 1;
153 /// }
154 /// });
155 /// # }
156 /// # }
157 /// ```
158 pub fn take<M: Any, F>(&mut self, f: F)
159 where
160 F: FnOnce(M, &mut EventMeta),
161 {
162 if let Some(message) = &self.message {
163 if message.as_ref().is::<M>() {
164 // Safe to unwrap because we already checked it exists
165 let m = self.message.take().unwrap();
166 // Safe to unwrap because we already checked it can be cast to M
167 let v = m.downcast().unwrap();
168 self.meta.consume();
169 (f)(*v, &mut self.meta);
170 }
171 }
172 }
173}
174
175impl ProxyEvent {
176 /// Creates a new proxy event with a sendable message.
177 pub fn new<M>(message: M) -> Self
178 where
179 M: Any + Send,
180 {
181 ProxyEvent { meta: Default::default(), message: Some(Box::new(message)) }
182 }
183
184 /// Sets the target of the event.
185 pub fn target(mut self, entity: Entity) -> Self {
186 self.meta.target = entity;
187 self
188 }
189
190 /// Sets the origin of the event.
191 pub fn origin(mut self, entity: Entity) -> Self {
192 self.meta.origin = entity;
193 self
194 }
195
196 /// Sets the propagation of the event.
197 pub fn propagate(mut self, propagation: Propagation) -> Self {
198 self.meta.propagation = propagation;
199 self
200 }
201
202 /// Converts a proxy event into a normal event on the UI thread.
203 pub fn into_event(self) -> Event {
204 Event { meta: self.meta, message: self.message.map(|message| message as Box<dyn Any>) }
205 }
206}
207
208/// The metadata of an [`Event`].
209#[derive(Debug, Clone, Copy)]
210pub struct EventMeta {
211 /// The entity that produced the event.
212 pub origin: Entity,
213 /// The entity the event should be sent to (or from in the case of subtree propagation).
214 pub target: Entity,
215 /// How the event propagates through the tree.
216 pub propagation: Propagation,
217 /// Determines whether the event should continue to be propagated.
218 pub(crate) consumed: bool,
219}
220
221impl EventMeta {
222 /// Consumes the event to prevent it from continuing on its propagation path.
223 pub fn consume(&mut self) {
224 self.consumed = true;
225 }
226}
227
228impl Default for EventMeta {
229 fn default() -> Self {
230 Self {
231 origin: Entity::null(),
232 target: Entity::root(),
233 propagation: Propagation::Up,
234 consumed: false,
235 }
236 }
237}
238
239/// A handle used to cancel a scheduled event before it is sent with `cx.cancel_scheduled`.
240#[derive(Debug, PartialEq, Eq, Copy, Clone)]
241pub struct TimedEventHandle(pub usize);
242
243#[derive(Debug)]
244pub(crate) struct TimedEvent {
245 pub ident: TimedEventHandle,
246 pub event: Event,
247 pub time: Instant,
248}
249
250impl PartialEq<Self> for TimedEvent {
251 fn eq(&self, other: &Self) -> bool {
252 self.time.eq(&other.time)
253 }
254}
255
256impl Eq for TimedEvent {}
257
258impl PartialOrd for TimedEvent {
259 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
260 Some(self.cmp(other))
261 }
262}
263
264impl Ord for TimedEvent {
265 fn cmp(&self, other: &Self) -> Ordering {
266 self.time.cmp(&other.time).reverse()
267 }
268}