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}