vizia_core/events/event.rs
1use crate::entity::Entity;
2use std::{any::Any, cmp::Ordering, fmt::Debug};
3use vizia_id::GenerationalId;
4use web_time::Instant;
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 + Send>>,
27}
28
29impl Debug for Event {
30 fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 Ok(())
32 }
33}
34
35impl Event {
36 /// Creates a new event with a specified message.
37 pub fn new<M>(message: M) -> Self
38 where
39 M: Any + Send,
40 {
41 Event { meta: Default::default(), message: Some(Box::new(message)) }
42 }
43
44 /// Sets the target of the event.
45 pub fn target(mut self, entity: Entity) -> Self {
46 self.meta.target = entity;
47 self
48 }
49
50 /// Sets the origin of the event.
51 pub fn origin(mut self, entity: Entity) -> Self {
52 self.meta.origin = entity;
53 self
54 }
55
56 /// Sets the propagation of the event.
57 pub fn propagate(mut self, propagation: Propagation) -> Self {
58 self.meta.propagation = propagation;
59 self
60 }
61
62 /// Sets the propagation to directly target the `entity`.
63 pub fn direct(mut self, entity: Entity) -> Self {
64 self.meta.propagation = Propagation::Direct;
65 self.meta.target = entity;
66 self
67 }
68
69 /// Consumes the event to prevent it from continuing on its propagation path.
70 pub fn consume(&mut self) {
71 self.meta.consume();
72 }
73
74 /// Tries to downcast the event message to the specified type. If the downcast was successful,
75 /// the message and the event metadata get passed into `f`.
76 ///
77 /// # Example
78 /// ```no_run
79 /// # use vizia_core::prelude::*;
80 /// # let cx = &mut Context::default();
81 /// # use vizia_winit::application::Application;
82 /// # pub struct AppData {
83 /// # count: i32,
84 /// # }
85 /// # pub enum AppEvent {
86 /// # Increment,
87 /// # Decrement,
88 /// # }
89 /// # impl Model for AppData {
90 /// # fn event(&mut self, _cx: &mut EventContext, event: &mut Event) {
91 /// event.map(|app_event, _| match app_event {
92 /// AppEvent::Increment => {
93 /// self.count += 1;
94 /// }
95 ///
96 /// AppEvent::Decrement => {
97 /// self.count -= 1;
98 /// }
99 /// });
100 /// # }
101 /// # }
102 /// ```
103 pub fn map<M, F>(&mut self, f: F)
104 where
105 M: Any + Send,
106 F: FnOnce(&M, &mut EventMeta),
107 {
108 if let Some(message) = &self.message {
109 if let Some(message) = message.as_ref().downcast_ref() {
110 (f)(message, &mut self.meta);
111 }
112 }
113 }
114
115 /// Tries to downcast the event message to the specified type. If the downcast was successful,
116 /// return the message by value and consume the event. Otherwise, do nothing.
117 ///
118 /// # Example
119 /// ```
120 /// # use vizia_core::prelude::*;
121 /// # let cx = &mut Context::default();
122 /// # use vizia_winit::application::Application;
123 /// # pub struct AppData {
124 /// # count: i32,
125 /// # }
126 /// # pub enum AppEvent {
127 /// # Increment,
128 /// # Decrement,
129 /// # }
130 /// # impl Model for AppData {
131 /// # fn event(&mut self, _cx: &mut EventContext, event: &mut Event) {
132 /// event.take(|app_event, meta| match app_event {
133 /// AppEvent::Increment => {
134 /// self.count += 1;
135 /// }
136 ///
137 /// AppEvent::Decrement => {
138 /// self.count -= 1;
139 /// }
140 /// });
141 /// # }
142 /// # }
143 /// ```
144 pub fn take<M: Any + Send, F>(&mut self, f: F)
145 where
146 F: FnOnce(M, &mut EventMeta),
147 {
148 if let Some(message) = &self.message {
149 if message.as_ref().is::<M>() {
150 // Safe to unwrap because we already checked it exists
151 let m = self.message.take().unwrap();
152 // Safe to unwrap because we already checked it can be cast to M
153 let v = m.downcast().unwrap();
154 self.meta.consume();
155 (f)(*v, &mut self.meta);
156 }
157 }
158 }
159}
160
161/// The metadata of an [`Event`].
162#[derive(Debug, Clone, Copy)]
163pub struct EventMeta {
164 /// The entity that produced the event.
165 pub origin: Entity,
166 /// The entity the event should be sent to (or from in the case of subtree propagation).
167 pub target: Entity,
168 /// How the event propagates through the tree.
169 pub propagation: Propagation,
170 /// Determines whether the event should continue to be propagated.
171 pub(crate) consumed: bool,
172}
173
174impl EventMeta {
175 /// Consumes the event to prevent it from continuing on its propagation path.
176 pub fn consume(&mut self) {
177 self.consumed = true;
178 }
179}
180
181impl Default for EventMeta {
182 fn default() -> Self {
183 Self {
184 origin: Entity::null(),
185 target: Entity::root(),
186 propagation: Propagation::Up,
187 consumed: false,
188 }
189 }
190}
191
192/// A handle used to cancel a scheduled event before it is sent with `cx.cancel_scheduled`.
193#[derive(Debug, PartialEq, Eq, Copy, Clone)]
194pub struct TimedEventHandle(pub usize);
195
196#[derive(Debug)]
197pub(crate) struct TimedEvent {
198 pub ident: TimedEventHandle,
199 pub event: Event,
200 pub time: Instant,
201}
202
203impl PartialEq<Self> for TimedEvent {
204 fn eq(&self, other: &Self) -> bool {
205 self.time.eq(&other.time)
206 }
207}
208
209impl Eq for TimedEvent {}
210
211impl PartialOrd for TimedEvent {
212 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
213 Some(self.cmp(other))
214 }
215}
216
217impl Ord for TimedEvent {
218 fn cmp(&self, other: &Self) -> Ordering {
219 self.time.cmp(&other.time).reverse()
220 }
221}