Skip to main content

vizia_core/context/
event.rs

1use std::any::{Any, TypeId};
2use std::collections::{BinaryHeap, VecDeque};
3#[cfg(feature = "clipboard")]
4use std::error::Error;
5use std::rc::Rc;
6
7use hashbrown::hash_map::Entry;
8use hashbrown::{HashMap, HashSet};
9use vizia_storage::{LayoutTreeIterator, TreeIterator};
10
11use crate::animation::AnimId;
12use crate::cache::CachedData;
13use crate::events::{TimedEvent, TimedEventHandle, TimerState, ViewHandler};
14use crate::prelude::*;
15use crate::resource::{ImageOrSvg, ResourceManager, StoredImage};
16use crate::tree::{focus_backward, focus_forward, is_navigatable};
17use vizia_input::MouseState;
18
19use skia_safe::Matrix;
20
21use crate::text::TextContext;
22#[cfg(feature = "clipboard")]
23use copypasta::ClipboardProvider;
24
25use super::{LocalizationContext, ModelData};
26
27type Views = HashMap<Entity, Box<dyn ViewHandler>>;
28type Models = HashMap<Entity, HashMap<TypeId, Box<dyn ModelData>>>;
29
30/// A context used when handling events.
31///
32/// The [`EventContext`] is provided by the [`event`](crate::prelude::View::event) method in [`View`], or the [`event`](crate::model::Model::event) method in [`Model`], and can be used to mutably access the
33/// desired style and layout properties of the current view.
34///
35/// # Example
36/// ```
37/// # use vizia_core::prelude::*;
38/// # use vizia_core::vg;
39/// # let cx = &mut Context::default();
40///
41/// pub struct CustomView {}
42///
43/// impl CustomView {
44///     pub fn new(cx: &mut Context) -> Handle<Self> {
45///         Self{}.build(cx, |_|{})
46///     }
47/// }
48///
49/// impl View for CustomView {
50///     fn event(&mut self, cx: &mut EventContext, event: &mut Event) {
51///         event.map(|window_event, _| match window_event {
52///             WindowEvent::Press{..} => {
53///                 // Change the view background color to red when pressed.
54///                 cx.set_background_color(Color::red());
55///             }
56///
57///             _=> {}
58///         });
59///     }
60/// }
61/// ```
62pub struct EventContext<'a> {
63    pub(crate) current: Entity,
64    pub(crate) captured: &'a mut Entity,
65    pub(crate) focused: &'a mut Entity,
66    pub(crate) hovered: &'a Entity,
67    pub(crate) triggered: &'a mut Entity,
68    pub(crate) style: &'a mut Style,
69    pub(crate) entity_identifiers: &'a HashMap<String, Entity>,
70    pub cache: &'a mut CachedData,
71    pub(crate) tree: &'a Tree<Entity>,
72    pub(crate) models: &'a mut Models,
73    pub(crate) views: &'a mut Views,
74    pub(crate) listeners:
75        &'a mut HashMap<Entity, Box<dyn Fn(&mut dyn ViewHandler, &mut EventContext, &mut Event)>>,
76    pub(crate) resource_manager: &'a mut ResourceManager,
77    pub(crate) text_context: &'a mut TextContext,
78    pub(crate) modifiers: &'a Modifiers,
79    pub(crate) mouse: &'a MouseState<Entity>,
80    pub(crate) event_queue: &'a mut VecDeque<Event>,
81    pub(crate) event_schedule: &'a mut BinaryHeap<TimedEvent>,
82    pub(crate) next_event_id: &'a mut usize,
83    pub(crate) timers: &'a mut Vec<TimerState>,
84    pub(crate) running_timers: &'a mut BinaryHeap<TimerState>,
85    cursor_icon_locked: &'a mut bool,
86    #[cfg(feature = "clipboard")]
87    clipboard: &'a mut Box<dyn ClipboardProvider>,
88    pub(crate) event_proxy: &'a mut Option<Box<dyn crate::context::EventProxy>>,
89    pub(crate) drop_data: &'a mut Option<DropData>,
90    pub(crate) active_drag_view: &'a mut Option<Entity>,
91    pub windows: &'a mut HashMap<Entity, WindowState>,
92}
93
94macro_rules! get_length_property {
95    (
96        $(#[$meta:meta])*
97        $name:ident
98    ) => {
99        $(#[$meta])*
100        pub fn $name(&self) -> f32 {
101            if let Some(length) = self.style.$name.get(self.current) {
102                let bounds = self.bounds();
103
104                let px = length.to_pixels(bounds.w.min(bounds.h), self.scale_factor());
105                return px.round();
106            }
107
108            0.0
109        }
110    };
111}
112
113impl<'a> EventContext<'a> {
114    /// Creates a new [EventContext].
115    pub fn new(cx: &'a mut Context) -> Self {
116        Self {
117            current: cx.current,
118            captured: &mut cx.captured,
119            focused: &mut cx.focused,
120            hovered: &cx.hovered,
121            triggered: &mut cx.triggered,
122            entity_identifiers: &cx.entity_identifiers,
123            style: &mut cx.style,
124            cache: &mut cx.cache,
125            tree: &cx.tree,
126            models: &mut cx.models,
127            views: &mut cx.views,
128            listeners: &mut cx.listeners,
129            resource_manager: &mut cx.resource_manager,
130            text_context: &mut cx.text_context,
131            modifiers: &cx.modifiers,
132            mouse: &cx.mouse,
133            event_queue: &mut cx.event_queue,
134            event_schedule: &mut cx.event_schedule,
135            next_event_id: &mut cx.next_event_id,
136            timers: &mut cx.timers,
137            running_timers: &mut cx.running_timers,
138            cursor_icon_locked: &mut cx.cursor_icon_locked,
139            #[cfg(feature = "clipboard")]
140            clipboard: &mut cx.clipboard,
141            event_proxy: &mut cx.event_proxy,
142            drop_data: &mut cx.drop_data,
143            active_drag_view: &mut cx.active_drag_view,
144            windows: &mut cx.windows,
145        }
146    }
147
148    /// Creates a new [EventContext] with the given current [Entity].
149    pub fn new_with_current(cx: &'a mut Context, current: Entity) -> Self {
150        Self {
151            current,
152            captured: &mut cx.captured,
153            focused: &mut cx.focused,
154            hovered: &cx.hovered,
155            triggered: &mut cx.triggered,
156            entity_identifiers: &cx.entity_identifiers,
157            style: &mut cx.style,
158            cache: &mut cx.cache,
159            tree: &cx.tree,
160            models: &mut cx.models,
161            views: &mut cx.views,
162            listeners: &mut cx.listeners,
163            resource_manager: &mut cx.resource_manager,
164            text_context: &mut cx.text_context,
165            modifiers: &cx.modifiers,
166            mouse: &cx.mouse,
167            event_queue: &mut cx.event_queue,
168            event_schedule: &mut cx.event_schedule,
169            next_event_id: &mut cx.next_event_id,
170            timers: &mut cx.timers,
171            running_timers: &mut cx.running_timers,
172            cursor_icon_locked: &mut cx.cursor_icon_locked,
173            #[cfg(feature = "clipboard")]
174            clipboard: &mut cx.clipboard,
175            event_proxy: &mut cx.event_proxy,
176            drop_data: &mut cx.drop_data,
177            active_drag_view: &mut cx.active_drag_view,
178            windows: &mut cx.windows,
179        }
180    }
181
182    /// Returns a reference to the current view associated with the event context.
183    pub fn get_view<V: View>(&self) -> Option<&V> {
184        self.views.get(&self.current).and_then(|view| view.downcast_ref::<V>())
185    }
186
187    /// Returns a reference to the specified view by entity.
188    pub fn get_view_with<V: View>(&self, entity: Entity) -> Option<&V> {
189        self.views.get(&entity).and_then(|view| view.downcast_ref::<V>())
190    }
191
192    pub fn close_window(&mut self) {
193        if let Some(state) = self.windows.get_mut(&self.current) {
194            state.should_close = true;
195        }
196    }
197
198    /// Returns the [Entity] id associated with the given identifier.
199    pub fn resolve_entity_identifier(&self, id: &str) -> Option<Entity> {
200        self.entity_identifiers.get(id).cloned()
201    }
202
203    /// Returns the descendant [Entity] id, of the current view, with the given element name if it exists.
204    pub fn get_entity_by_element_id(&self, element: &str) -> Option<Entity> {
205        let descendants = LayoutTreeIterator::subtree(self.tree, self.current);
206        for descendant in descendants {
207            if let Some(id) = self.views.get(&descendant).and_then(|view| view.element()) {
208                if id == element {
209                    return Some(descendant);
210                }
211            }
212        }
213
214        None
215    }
216
217    /// Returns the descendant [Entity] ids, of the current view, with the given class name.
218    pub fn get_entities_by_class(&self, class: &str) -> Vec<Entity> {
219        let mut entities = Vec::new();
220        let descendants = LayoutTreeIterator::subtree(self.tree, self.current);
221        for descendant in descendants {
222            if let Some(class_list) = self.style.classes.get(descendant) {
223                if class_list.contains(class) {
224                    entities.push(descendant);
225                }
226            }
227        }
228
229        entities
230    }
231
232    /// Returns the [Entity] id of the current view.
233    pub fn current(&self) -> Entity {
234        self.current
235    }
236
237    /// Returns a reference to the keyboard modifiers state.
238    pub fn modifiers(&self) -> &Modifiers {
239        self.modifiers
240    }
241
242    /// Returns a reference to the mouse state.
243    pub fn mouse(&self) -> &MouseState<Entity> {
244        self.mouse
245    }
246
247    pub fn nth_child(&self, n: usize) -> Option<Entity> {
248        self.tree.get_child(self.current, n)
249    }
250
251    pub fn last_child(&self) -> Option<Entity> {
252        self.tree.get_last_child(self.current).copied()
253    }
254
255    pub fn with_current<T>(&mut self, entity: Entity, f: impl FnOnce(&mut Self) -> T) -> T {
256        let prev = self.current();
257        self.current = entity;
258        let ret = (f)(self);
259        self.current = prev;
260        ret
261    }
262
263    /// Returns true if in a drop state.
264    pub fn has_drop_data(&self) -> bool {
265        self.drop_data.is_some()
266    }
267
268    /// Returns the current drop payload, if any.
269    pub fn drop_data(&self) -> Option<&DropData> {
270        self.drop_data.as_ref()
271    }
272
273    /// Returns the active drag preview view entity, if any.
274    pub fn active_drag_view(&self) -> Option<Entity> {
275        *self.active_drag_view
276    }
277
278    /// Sets the active drag preview view entity.
279    pub fn set_active_drag_view(&mut self, drag_view: Option<Entity>) {
280        *self.active_drag_view = drag_view;
281    }
282
283    /// Returns the bounds of the current view.
284    pub fn bounds(&self) -> BoundingBox {
285        self.cache.get_bounds(self.current)
286    }
287
288    // pub fn set_bounds(&mut self, bounds: BoundingBox) {
289    //     self.cache.set_bounds(self.current, bounds);
290    // }
291
292    /// Returns the scale factor.
293    pub fn scale_factor(&self) -> f32 {
294        self.style.dpi_factor as f32
295    }
296
297    /// Converts logical points to physical pixels.
298    pub fn logical_to_physical(&self, logical: f32) -> f32 {
299        self.style.logical_to_physical(logical)
300    }
301
302    /// Convert physical pixels to logical points.
303    pub fn physical_to_logical(&self, physical: f32) -> f32 {
304        self.style.physical_to_logical(physical)
305    }
306
307    /// Returns the clip bounds of the current view.
308    pub fn clip_region(&self) -> BoundingBox {
309        let current_window = if self.tree.is_window(self.current) {
310            self.current
311        } else {
312            self.tree.get_parent_window(self.current).unwrap_or(Entity::root())
313        };
314
315        let window_bounds = self.cache.get_bounds(current_window);
316
317        // A cached entry (including None) is authoritative for this entity.
318        if let Some(clip_path) = self.cache.clip_path.get(self.current) {
319            return clip_path
320                .clone()
321                .map(|clip_path| Into::<BoundingBox>::into(*clip_path.bounds()))
322                .unwrap_or(window_bounds);
323        }
324
325        if self.style.ignore_clipping.get(self.current).copied().unwrap_or(false) {
326            return window_bounds;
327        }
328
329        let mut current = self.current;
330        while let Some(parent) = self.tree.get_parent(current) {
331            // A cached parent entry (including None) is authoritative.
332            if let Some(clip_path) = self.cache.clip_path.get(parent) {
333                return clip_path
334                    .clone()
335                    .map(|clip_path| Into::<BoundingBox>::into(*clip_path.bounds()))
336                    .unwrap_or(window_bounds);
337            }
338
339            if self.style.ignore_clipping.get(parent).copied().unwrap_or(false) {
340                return window_bounds;
341            }
342
343            if parent == current_window {
344                break;
345            }
346
347            current = parent;
348        }
349
350        window_bounds
351    }
352
353    /// Returns the 2D transform of the current view.
354    pub fn transform(&self) -> Matrix {
355        self.cache.transform.get(self.current).copied().unwrap_or_default()
356    }
357
358    /// Trigger an animation with the given id to play on the current view.
359    pub fn play_animation(&mut self, anim_id: impl AnimId, duration: Duration, delay: Duration) {
360        if let Some(animation_id) = anim_id.get(self) {
361            self.style.enqueue_animation(self.current, animation_id, duration, delay);
362        }
363    }
364
365    /// Trigger an animation with the given id to play on a target view.
366    pub fn play_animation_for(
367        &mut self,
368        anim_id: impl AnimId,
369        target: &str,
370        duration: Duration,
371        delay: Duration,
372    ) {
373        if let Some(target_entity) = self.resolve_entity_identifier(target) {
374            if let Some(animation_id) = anim_id.get(self) {
375                self.style.enqueue_animation(target_entity, animation_id, duration, delay)
376            }
377        }
378    }
379
380    /// Returns true if the current view is currently animating with the given animation id.
381    pub fn is_animating(&self, anim_id: impl AnimId) -> bool {
382        if let Some(animation_id) = anim_id.get(self) {
383            return self.style.is_animating(self.current, animation_id);
384        }
385
386        false
387    }
388
389    /// Add a listener to an entity.
390    ///
391    /// A listener can be used to handle events which would not normally propagate to the entity.
392    /// For example, mouse events when a different entity has captured them. Useful for things like
393    /// closing a popup when clicking outside of its bounding box.
394    pub fn add_listener<F, W>(&mut self, listener: F)
395    where
396        W: View,
397        F: 'static + Fn(&mut W, &mut EventContext, &mut Event),
398    {
399        self.listeners.insert(
400            self.current,
401            Box::new(move |event_handler, context, event| {
402                if let Some(widget) = event_handler.downcast_mut::<W>() {
403                    (listener)(widget, context, event);
404                }
405            }),
406        );
407    }
408
409    /// Sets the language used by the application for localization.
410    pub fn set_language(&mut self, lang: LanguageIdentifier) {
411        if let Some(mut models) = self.models.remove(&Entity::root()) {
412            if let Some(model) = models.get_mut(&TypeId::of::<Environment>()) {
413                model.event(self, &mut Event::new(EnvironmentEvent::SetLocale(lang)));
414            }
415
416            self.models.insert(Entity::root(), models);
417        }
418    }
419
420    pub fn add_image_encoded(&mut self, path: &str, data: &[u8], policy: ImageRetentionPolicy) {
421        let id = if let Some(image_id) = self.resource_manager.image_ids.get(path) {
422            *image_id
423        } else {
424            let id = self.resource_manager.image_id_manager.create();
425            self.resource_manager.image_ids.insert(path.to_owned(), id);
426            id
427        };
428
429        if let Some(image) = skia_safe::Image::from_encoded(skia_safe::Data::new_copy(data)) {
430            match self.resource_manager.images.entry(id) {
431                Entry::Occupied(mut occ) => {
432                    occ.get_mut().image = ImageOrSvg::Image(image);
433                    occ.get_mut().dirty = true;
434                    occ.get_mut().retention_policy = policy;
435                }
436                Entry::Vacant(vac) => {
437                    vac.insert(StoredImage {
438                        image: ImageOrSvg::Image(image),
439                        retention_policy: policy,
440                        used: true,
441                        dirty: false,
442                        observers: HashSet::new(),
443                    });
444                }
445            }
446            self.style.needs_relayout();
447        }
448    }
449
450    /// Capture mouse input for the current view.
451    pub fn capture(&mut self) {
452        *self.captured = self.current;
453    }
454
455    /// Release mouse input capture for the current view.
456    pub fn release(&mut self) {
457        if self.current == *self.captured {
458            *self.captured = Entity::null();
459        }
460    }
461
462    /// Enables or disables PseudoClassFlags for the focus of an entity
463    fn set_focus_pseudo_classes(&mut self, focused: Entity, enabled: bool, focus_visible: bool) {
464        if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(focused) {
465            pseudo_classes.set(PseudoClassFlags::FOCUS, enabled);
466            if !enabled || focus_visible {
467                pseudo_classes.set(PseudoClassFlags::FOCUS_VISIBLE, enabled);
468            }
469        }
470
471        for ancestor in focused.parent_iter(self.tree) {
472            let entity = ancestor;
473            if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(entity) {
474                pseudo_classes.set(PseudoClassFlags::FOCUS_WITHIN, enabled);
475            }
476            self.style.needs_restyle(entity);
477        }
478    }
479
480    /// Sets application focus to the current view with the specified focus visibility.
481    pub fn focus_with_visibility(&mut self, focus_visible: bool) {
482        let old_focus = self.focused();
483        let new_focus = self.current();
484        self.set_focus_pseudo_classes(old_focus, false, focus_visible);
485        if self.current() != self.focused() {
486            self.emit_to(old_focus, WindowEvent::FocusOut);
487            self.emit_to(new_focus, WindowEvent::FocusIn);
488            *self.focused = self.current();
489        }
490        self.set_focus_pseudo_classes(new_focus, true, focus_visible);
491
492        self.emit_custom(Event::new(WindowEvent::FocusVisibility(focus_visible)).target(old_focus));
493        self.emit_custom(Event::new(WindowEvent::FocusVisibility(focus_visible)).target(new_focus));
494
495        self.needs_restyle();
496    }
497
498    /// Sets application focus to the current view using the previous focus visibility.
499    ///
500    /// Focused elements receive keyboard input events and can be selected with the `:focus` CSS pseudo-class selector.
501    pub fn focus(&mut self) {
502        let focused = self.focused();
503        let old_focus_visible = self
504            .style
505            .pseudo_classes
506            .get_mut(focused)
507            .filter(|class| class.contains(PseudoClassFlags::FOCUS_VISIBLE))
508            .is_some();
509        self.focus_with_visibility(old_focus_visible)
510    }
511
512    /// Moves the keyboard focus to the next navigable view.
513    pub fn focus_next(&mut self) {
514        let lock_focus_to = self.tree.lock_focus_within(*self.focused);
515        let next_focused = if let Some(next_focused) =
516            focus_forward(self.tree, self.style, *self.focused, lock_focus_to)
517        {
518            next_focused
519        } else {
520            TreeIterator::full(self.tree)
521                .find(|node| is_navigatable(self.tree, self.style, *node, lock_focus_to))
522                .unwrap_or(Entity::root())
523        };
524
525        if next_focused != *self.focused {
526            self.event_queue.push_back(
527                Event::new(WindowEvent::FocusOut).target(*self.focused).origin(Entity::root()),
528            );
529            self.event_queue.push_back(
530                Event::new(WindowEvent::FocusIn).target(next_focused).origin(Entity::root()),
531            );
532
533            if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(*self.triggered) {
534                pseudo_classes.set(PseudoClassFlags::ACTIVE, false);
535            }
536            self.needs_restyle();
537            *self.triggered = Entity::null();
538        }
539    }
540
541    /// Moves the keyboard focus to the previous navigable view.
542    pub fn focus_prev(&mut self) {
543        let lock_focus_to = self.tree.lock_focus_within(*self.focused);
544        let prev_focused = if let Some(prev_focused) =
545            focus_backward(self.tree, self.style, *self.focused, lock_focus_to)
546        {
547            prev_focused
548        } else {
549            TreeIterator::full(self.tree)
550                .rfind(|node| is_navigatable(self.tree, self.style, *node, lock_focus_to))
551                .unwrap_or(Entity::root())
552        };
553
554        if prev_focused != *self.focused {
555            self.event_queue.push_back(
556                Event::new(WindowEvent::FocusOut).target(*self.focused).origin(Entity::root()),
557            );
558            self.event_queue.push_back(
559                Event::new(WindowEvent::FocusIn).target(prev_focused).origin(Entity::root()),
560            );
561
562            if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(*self.triggered) {
563                pseudo_classes.set(PseudoClassFlags::ACTIVE, false);
564            }
565            self.needs_restyle();
566            *self.triggered = Entity::null();
567        }
568    }
569
570    /// Returns the currently hovered view.
571    pub fn hovered(&self) -> Entity {
572        *self.hovered
573    }
574
575    /// Returns the currently focused view.
576    pub fn focused(&self) -> Entity {
577        *self.focused
578    }
579
580    // PseudoClass Getters
581
582    /// Returns true if the current view is being hovered.
583    pub fn is_hovered(&self) -> bool {
584        self.hovered() == self.current
585    }
586
587    /// Returns true if the current view is active.
588    pub fn is_active(&self) -> bool {
589        if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
590            pseudo_classes.contains(PseudoClassFlags::ACTIVE)
591        } else {
592            false
593        }
594    }
595
596    /// Returns true if the mouse cursor is over the current view.
597    pub fn is_over(&self) -> bool {
598        if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
599            pseudo_classes.contains(PseudoClassFlags::OVER)
600        } else {
601            false
602        }
603    }
604
605    /// Returns true if the current view is focused.
606    pub fn is_focused(&self) -> bool {
607        self.focused() == self.current
608    }
609
610    /// Returns true if the current view can be dragged in a drag and drop operation.
611    pub fn is_draggable(&self) -> bool {
612        self.style
613            .abilities
614            .get(self.current)
615            .map(|abilities| abilities.contains(Abilities::DRAGGABLE))
616            .unwrap_or_default()
617    }
618
619    /// Returns true if the current view is disabled.
620    pub fn is_disabled(&self) -> bool {
621        self.style.disabled.get(self.current()).cloned().unwrap_or_default()
622    }
623
624    /// Returns true if the current view is checked.
625    pub fn is_checked(&self) -> bool {
626        if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
627            pseudo_classes.contains(PseudoClassFlags::CHECKED)
628        } else {
629            false
630        }
631    }
632
633    /// Returns true if the view is in a read-only state.
634    pub fn is_read_only(&self) -> bool {
635        if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
636            pseudo_classes.contains(PseudoClassFlags::READ_ONLY)
637        } else {
638            false
639        }
640    }
641
642    //
643
644    /// Prevents the cursor icon from changing until the lock is released.
645    pub fn lock_cursor_icon(&mut self) {
646        *self.cursor_icon_locked = true;
647    }
648
649    /// Releases any cursor icon lock, allowing the cursor icon to be changed.
650    pub fn unlock_cursor_icon(&mut self) {
651        *self.cursor_icon_locked = false;
652        let hovered = *self.hovered;
653        let cursor = self.style.cursor.get(hovered).cloned().unwrap_or_default();
654        self.emit(WindowEvent::SetCursor(cursor));
655    }
656
657    /// Returns true if the cursor icon is locked.
658    pub fn is_cursor_icon_locked(&self) -> bool {
659        *self.cursor_icon_locked
660    }
661
662    /// Sets the drop data of the current view.
663    pub fn set_drop_data(&mut self, data: impl Into<DropData>) {
664        *self.drop_data = Some(data.into())
665    }
666
667    /// Get the contents of the system clipboard.
668    ///
669    /// This may fail for a variety of backend-specific reasons.
670    #[cfg(feature = "clipboard")]
671    pub fn get_clipboard(&mut self) -> Result<String, Box<dyn Error + Send + Sync + 'static>> {
672        self.clipboard.get_contents()
673    }
674
675    /// Set the contents of the system clipboard.
676    ///
677    /// This may fail for a variety of backend-specific reasons.
678    #[cfg(feature = "clipboard")]
679    pub fn set_clipboard(
680        &mut self,
681        text: String,
682    ) -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
683        self.clipboard.set_contents(text)
684    }
685
686    /// Toggles the addition/removal of a class name for the current view.
687    ///
688    /// # Example
689    /// ```rust
690    /// # use vizia_core::prelude::*;
691    /// # let context = &mut Context::default();
692    /// # let mut cx = &mut EventContext::new(context);
693    /// cx.toggle_class("foo", true);
694    /// ```
695    pub fn toggle_class(&mut self, class_name: &str, applied: bool) {
696        let current = self.current();
697        if let Some(class_list) = self.style.classes.get_mut(current) {
698            if applied {
699                class_list.insert(class_name.to_string());
700            } else {
701                class_list.remove(class_name);
702            }
703        } else if applied {
704            let mut class_list = HashSet::new();
705            class_list.insert(class_name.to_string());
706            self.style.classes.insert(current, class_list);
707        }
708
709        self.needs_restyle();
710    }
711
712    /// Returns a reference to the [Environment] model.
713    pub fn environment(&self) -> &Environment {
714        self.data::<Environment>()
715    }
716
717    /// Marks the current view as needing to be redrawn.
718    pub fn needs_redraw(&mut self) {
719        let parent_window = self.tree.get_parent_window(self.current).unwrap_or(Entity::root());
720        if let Some(window_state) = self.windows.get_mut(&parent_window) {
721            window_state.redraw_list.insert(self.current);
722        }
723    }
724
725    /// Marks the current view as needing a layout computation.
726    pub fn needs_relayout(&mut self) {
727        self.style.needs_relayout();
728        self.needs_redraw();
729    }
730
731    /// Marks the current view as needing to be restyled.
732    pub fn needs_restyle(&mut self) {
733        if self.current == Entity::null() || self.style.restyle.contains(&self.current) {
734            return;
735        }
736
737        self.style.restyle.insert(self.current);
738        let iter = if let Some(parent) = self.tree.get_layout_parent(self.current) {
739            LayoutTreeIterator::subtree(self.tree, parent)
740        } else {
741            LayoutTreeIterator::subtree(self.tree, self.current)
742        };
743
744        for descendant in iter {
745            self.style.restyle.insert(descendant);
746        }
747        self.style.needs_restyle(self.current);
748    }
749
750    pub fn needs_retransform(&mut self) {
751        self.style.needs_retransform(self.current);
752        let iter = LayoutTreeIterator::subtree(self.tree, self.current);
753        for descendant in iter {
754            self.style.needs_retransform(descendant);
755        }
756    }
757
758    pub fn needs_reclip(&mut self) {
759        self.style.needs_reclip(self.current);
760        let iter = LayoutTreeIterator::subtree(self.tree, self.current);
761        for descendant in iter {
762            self.style.needs_reclip(descendant);
763        }
764    }
765
766    /// Reloads the stylesheets linked to the application.
767    pub fn reload_styles(&mut self) -> Result<(), std::io::Error> {
768        if self.resource_manager.styles.is_empty() {
769            return Ok(());
770        }
771
772        self.style.remove_rules();
773
774        self.style.clear_style_rules();
775
776        let mut overall_theme = String::new();
777
778        for style_string in self.resource_manager.styles.iter().flat_map(|style| style.get_style())
779        {
780            overall_theme += &style_string;
781        }
782
783        self.style.parse_theme(&overall_theme);
784
785        for entity in self.tree.into_iter() {
786            self.style.needs_restyle(entity);
787            self.style.needs_relayout();
788            //self.style.needs_redraw(entity);
789            self.style.needs_text_update(entity);
790        }
791
792        Ok(())
793    }
794
795    /// Spawns a thread and provides a [ContextProxy] for sending events back to the main UI thread.
796    pub fn spawn<F>(&self, target: F)
797    where
798        F: 'static + Send + FnOnce(&mut ContextProxy),
799    {
800        let mut cxp = ContextProxy {
801            current: self.current,
802            event_proxy: self.event_proxy.as_ref().map(|p| p.make_clone()),
803        };
804
805        std::thread::spawn(move || target(&mut cxp));
806    }
807
808    /// Returns a [ContextProxy] which can be moved between threads and used to send events back to the main UI thread.
809    pub fn get_proxy(&self) -> ContextProxy {
810        ContextProxy {
811            current: self.current,
812            event_proxy: self.event_proxy.as_ref().map(|p| p.make_clone()),
813        }
814    }
815
816    pub fn modify<V: View>(&mut self, f: impl FnOnce(&mut V)) {
817        if let Some(view) = self
818            .views
819            .get_mut(&self.current)
820            .and_then(|view_handler| view_handler.downcast_mut::<V>())
821        {
822            (f)(view);
823        }
824    }
825
826    // TODO: Abstract this to shared trait for all contexts
827
828    // Getters
829
830    /// Returns the background color of the view.
831    ///
832    /// Returns a transparent color if the view does not have a background color.
833    pub fn background_color(&mut self) -> Color {
834        self.style.background_color.get(self.current).copied().unwrap_or_default()
835    }
836
837    // Setters
838
839    pub fn set_id(&mut self, id: &str) {
840        self.style.ids.insert(self.current, id.to_string())
841    }
842
843    // Pseudoclass Setters
844
845    /// Sets the hover state of the current view.
846    ///
847    /// Hovered elements can be selected with the `:hover` CSS pseudo-class selector:
848    /// ```css
849    /// element:hover {
850    ///     background-color: red;
851    /// }
852    /// ```
853    /// Typically this is set by the hover system and should not be set manually.
854    pub fn set_hover(&mut self, flag: bool) {
855        let current = self.current();
856        if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
857            pseudo_classes.set(PseudoClassFlags::HOVER, flag);
858        }
859
860        self.needs_restyle();
861    }
862
863    /// Set the active state for the current view.
864    ///
865    /// Active elements can be selected with the `:active` CSS pseudo-class selector:
866    /// ```css
867    /// element:active {
868    ///     background-color: red;
869    /// }
870    /// ```
871    pub fn set_active(&mut self, active: bool) {
872        if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(self.current) {
873            pseudo_classes.set(PseudoClassFlags::ACTIVE, active);
874        }
875
876        self.needs_restyle();
877    }
878
879    pub fn set_read_only(&mut self, flag: bool) {
880        let current = self.current();
881        if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
882            pseudo_classes.set(PseudoClassFlags::READ_ONLY, flag);
883        }
884
885        self.needs_restyle();
886    }
887
888    pub fn set_read_write(&mut self, flag: bool) {
889        let current = self.current();
890        if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
891            pseudo_classes.set(PseudoClassFlags::READ_WRITE, flag);
892        }
893
894        self.needs_restyle();
895    }
896
897    /// Sets the checked state of the current view.
898    ///
899    /// Checked elements can be selected with the `:checked` CSS pseudo-class selector:
900    /// ```css
901    /// element:checked {
902    ///     background-color: red;
903    /// }
904    /// ```
905    pub fn set_checked(&mut self, flag: bool) {
906        let current = self.current();
907        if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
908            pseudo_classes.set(PseudoClassFlags::CHECKED, flag);
909        }
910
911        self.needs_restyle();
912    }
913
914    /// Sets the valid state of the current view.
915    ///
916    /// Checked elements can be selected with the `:checked` CSS pseudo-class selector:
917    /// ```css
918    /// element:checked {
919    ///     background-color: red;
920    /// }
921    /// ```
922    pub fn set_valid(&mut self, flag: bool) {
923        let current = self.current();
924        if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
925            pseudo_classes.set(PseudoClassFlags::VALID, flag);
926            pseudo_classes.set(PseudoClassFlags::INVALID, !flag);
927        }
928
929        self.needs_restyle();
930    }
931
932    pub fn set_placeholder_shown(&mut self, flag: bool) {
933        let current = self.current();
934        if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
935            pseudo_classes.set(PseudoClassFlags::PLACEHOLDER_SHOWN, flag);
936        }
937
938        self.needs_restyle();
939    }
940
941    // TODO: Move me
942    pub fn is_valid(&self) -> bool {
943        self.style
944            .pseudo_classes
945            .get(self.current)
946            .map(|pseudo_classes| pseudo_classes.contains(PseudoClassFlags::VALID))
947            .unwrap_or_default()
948    }
949
950    pub fn is_placeholder_shown(&self) -> bool {
951        self.style
952            .pseudo_classes
953            .get(self.current)
954            .map(|pseudo_classes| pseudo_classes.contains(PseudoClassFlags::PLACEHOLDER_SHOWN))
955            .unwrap_or_default()
956    }
957
958    // Accessibility Properties
959
960    /// Sets the accessibility name of the view.
961    pub fn set_name(&mut self, name: &str) {
962        self.style.name.insert(self.current, name.to_string());
963    }
964
965    /// Sets the accessibility role of the view.
966    pub fn set_role(&mut self, role: Role) {
967        self.style.role.insert(self.current, role);
968    }
969
970    // /// Sets the accessibility default action verb of the view.
971    // pub fn set_default_action_verb(&mut self, default_action_verb: DefaultActionVerb) {
972    //     self.style.default_action_verb.insert(self.current, default_action_verb);
973    // }
974
975    /// Sets the view to be an accessibility live region.
976    pub fn set_live(&mut self, live: Live) {
977        self.style.live.insert(self.current, live);
978    }
979
980    /// Sets the view, by id name, which labels the current view for accessibility.  
981    pub fn labelled_by(&mut self, id: &str) {
982        self.style.labelled_by.insert(self.current, id.to_string());
983    }
984
985    /// Sets the view, by id name, which describes the current view for accessibility.
986    pub fn described_by(&mut self, id: &str) {
987        self.style.described_by.insert(self.current, id.to_string());
988    }
989
990    /// Sets the view, by id name, which is controlled by the current view for accessibility.
991    pub fn controls(&mut self, id: &str) {
992        self.style.controls.insert(self.current, id.to_string());
993    }
994
995    /// Sets whether the view should be explicitely hidden from accessibility.
996    pub fn set_hidden(&mut self, hidden: bool) {
997        self.style.hidden.insert(self.current, hidden)
998    }
999
1000    /// Sets a text value used for accessbility for the current view.
1001    pub fn text_value(&mut self, text: &str) {
1002        self.style.text_value.insert(self.current, text.to_string());
1003    }
1004
1005    /// Sets a numeric value used for accessibility for the current view.
1006    pub fn numeric_value(&mut self, value: f64) {
1007        self.style.numeric_value.insert(self.current, value);
1008    }
1009
1010    // DISPLAY
1011
1012    /// Sets the display type of the current view.
1013    ///
1014    /// A display value of `Display::None` causes the view to be ignored by both layout and rendering.
1015    pub fn set_display(&mut self, display: Display) {
1016        self.style.display.insert(self.current, display);
1017    }
1018
1019    /// Sets the visibility of the current view.
1020    ///
1021    /// The layout system will still compute the size and position of an invisible (hidden) view.
1022    pub fn set_visibility(&mut self, visibility: Visibility) {
1023        self.style.visibility.insert(self.current, visibility);
1024    }
1025
1026    /// Sets the opacity of the current view.
1027    ///
1028    /// Expects a number between 0.0 (transparent) and 1.0 (opaque).
1029    pub fn set_opacity(&mut self, opacity: f32) {
1030        self.style.opacity.insert(self.current, Opacity(opacity));
1031    }
1032
1033    /// Sets the z-index of the current view.
1034    pub fn set_z_index(&mut self, z_index: i32) {
1035        self.style.z_index.insert(self.current, z_index);
1036    }
1037
1038    /// Sets the clip path of the current view.
1039    pub fn set_clip_path(&mut self, clip_path: ClipPath) {
1040        self.style.clip_path.insert(self.current, clip_path);
1041        self.needs_reclip();
1042        self.needs_redraw();
1043    }
1044
1045    /// Sets the overflow type on the horizontal axis of the current view.
1046    pub fn set_overflowx(&mut self, overflowx: impl Into<Overflow>) {
1047        self.style.overflowx.insert(self.current, overflowx.into());
1048        self.needs_reclip();
1049        self.needs_redraw();
1050    }
1051
1052    /// Sets the overflow type on the vertical axis of the current view.
1053    pub fn set_overflowy(&mut self, overflowy: impl Into<Overflow>) {
1054        self.style.overflowy.insert(self.current, overflowy.into());
1055        self.needs_reclip();
1056        self.needs_redraw();
1057    }
1058
1059    // TRANSFORM
1060
1061    /// Sets the transform of the current view.
1062    pub fn set_transform(&mut self, transform: impl Into<Vec<Transform>>) {
1063        self.style.transform.insert(self.current, transform.into());
1064        self.needs_retransform();
1065        self.needs_redraw();
1066    }
1067
1068    /// Sets the transform origin of the current view.
1069    pub fn set_transform_origin(&mut self, transform_origin: Translate) {
1070        self.style.transform_origin.insert(self.current, transform_origin);
1071        self.needs_retransform();
1072        self.needs_redraw();
1073    }
1074
1075    /// Sets the translation of the current view.
1076    pub fn set_translate(&mut self, translate: impl Into<Translate>) {
1077        self.style.translate.insert(self.current, translate.into());
1078        self.needs_retransform();
1079        self.needs_redraw();
1080    }
1081
1082    /// Sets the rotation of the current view.
1083    pub fn set_rotate(&mut self, angle: impl Into<Angle>) {
1084        self.style.rotate.insert(self.current, angle.into());
1085        self.needs_retransform();
1086        self.needs_redraw();
1087    }
1088
1089    /// Sets the scale of the current view.
1090    pub fn set_scale(&mut self, scale: impl Into<Scale>) {
1091        self.style.scale.insert(self.current, scale.into());
1092        self.needs_retransform();
1093        self.needs_redraw();
1094    }
1095
1096    // FILTER
1097
1098    /// Sets the filter of the current view.
1099    pub fn set_filter(&mut self, filter: Filter) {
1100        self.style.filter.insert(self.current, filter);
1101        self.needs_redraw();
1102    }
1103
1104    /// Sets the backdrop filter of the current view.
1105    pub fn set_backdrop_filter(&mut self, filter: Filter) {
1106        self.style.backdrop_filter.insert(self.current, filter);
1107        self.needs_redraw();
1108    }
1109
1110    // BOX SHADOW
1111
1112    // TODO
1113
1114    // BACKGROUND
1115
1116    pub fn set_background_color(&mut self, background_color: Color) {
1117        self.style.background_color.insert(self.current, background_color);
1118        self.needs_redraw();
1119    }
1120
1121    // SIZE
1122
1123    pub fn set_width(&mut self, width: Units) {
1124        self.style.width.insert(self.current, width);
1125        self.needs_relayout();
1126        self.needs_redraw();
1127    }
1128
1129    pub fn set_height(&mut self, height: Units) {
1130        self.style.height.insert(self.current, height);
1131        self.needs_relayout();
1132        self.needs_redraw();
1133    }
1134
1135    pub fn set_max_height(&mut self, height: Units) {
1136        self.style.max_height.insert(self.current, height);
1137        self.needs_relayout();
1138        self.needs_redraw();
1139    }
1140
1141    // SPACE
1142
1143    pub fn set_left(&mut self, left: Units) {
1144        self.style.left.insert(self.current, left);
1145        self.needs_relayout();
1146        self.needs_redraw();
1147    }
1148
1149    pub fn set_top(&mut self, top: Units) {
1150        self.style.top.insert(self.current, top);
1151        self.needs_relayout();
1152        self.needs_redraw();
1153    }
1154
1155    pub fn set_right(&mut self, right: Units) {
1156        self.style.right.insert(self.current, right);
1157        self.needs_relayout();
1158        self.needs_redraw();
1159    }
1160
1161    pub fn set_bottom(&mut self, bottom: Units) {
1162        self.style.bottom.insert(self.current, bottom);
1163        self.needs_relayout();
1164        self.needs_redraw();
1165    }
1166
1167    // PADDING
1168
1169    pub fn set_padding_left(&mut self, padding_left: Units) {
1170        self.style.padding_left.insert(self.current, padding_left);
1171        self.needs_relayout();
1172        self.needs_redraw();
1173    }
1174
1175    pub fn set_padding_top(&mut self, padding_top: Units) {
1176        self.style.padding_top.insert(self.current, padding_top);
1177        self.needs_relayout();
1178        self.needs_redraw();
1179    }
1180
1181    pub fn set_padding_right(&mut self, padding_right: Units) {
1182        self.style.padding_right.insert(self.current, padding_right);
1183        self.needs_relayout();
1184        self.needs_redraw();
1185    }
1186
1187    pub fn set_padding_bottom(&mut self, padding_bottom: Units) {
1188        self.style.padding_bottom.insert(self.current, padding_bottom);
1189        self.needs_relayout();
1190        self.needs_redraw();
1191    }
1192
1193    // TEXT
1194
1195    /// Sets the text of the current view.
1196    pub fn set_text(&mut self, text: &str) {
1197        self.style.text.insert(self.current, text.to_owned());
1198        self.style.needs_text_update(self.current);
1199        self.needs_relayout();
1200        self.needs_redraw();
1201    }
1202
1203    pub fn set_pointer_events(&mut self, pointer_events: impl Into<PointerEvents>) {
1204        self.style.pointer_events.insert(self.current, pointer_events.into());
1205    }
1206
1207    // GETTERS
1208    get_length_property!(
1209        /// Returns the border width of the current view in physical pixels.
1210        border_width
1211    );
1212
1213    /// Returns the font-size of the current view in physical pixels.
1214    pub fn font_size(&self) -> f32 {
1215        self.logical_to_physical(
1216            self.style
1217                .font_size
1218                .get(self.current)
1219                .cloned()
1220                .map(|f| f.0.to_px().unwrap())
1221                .unwrap_or(16.0),
1222        )
1223    }
1224
1225    /// Adds a timer to the application.
1226    ///
1227    /// `interval` - The time between ticks of the timer.
1228    /// `duration` - An optional duration for the timer. Pass `None` for a continuos timer.
1229    /// `callback` - A callback which is called on when the timer is started, ticks, and stops. Disambiguated by the `TimerAction` parameter of the callback.
1230    ///
1231    /// Returns a `Timer` id which can be used to start and stop the timer.  
1232    ///
1233    /// # Example
1234    /// Creates a timer which calls the provided callback every second for 5 seconds:
1235    /// ```rust
1236    /// # use vizia_core::prelude::*;
1237    /// # use instant::{Instant, Duration};
1238    /// # let cx = &mut Context::default();
1239    /// let timer = cx.add_timer(Duration::from_secs(1), Some(Duration::from_secs(5)), |cx, reason|{
1240    ///     match reason {
1241    ///         TimerAction::Start => {
1242    ///             debug!("Start timer");
1243    ///         }
1244    ///     
1245    ///         TimerAction::Tick(delta) => {
1246    ///             debug!("Tick timer: {:?}", delta);
1247    ///         }
1248    ///
1249    ///         TimerAction::Stop => {
1250    ///             debug!("Stop timer");
1251    ///         }
1252    ///     }
1253    /// });
1254    /// ```
1255    pub fn add_timer(
1256        &mut self,
1257        interval: Duration,
1258        duration: Option<Duration>,
1259        callback: impl Fn(&mut EventContext, TimerAction) + 'static,
1260    ) -> Timer {
1261        let id = Timer(self.timers.len());
1262        self.timers.push(TimerState {
1263            entity: Entity::root(),
1264            id,
1265            time: Instant::now(),
1266            interval,
1267            duration,
1268            start_time: Instant::now(),
1269            callback: Rc::new(callback),
1270            ticking: false,
1271            stopping: false,
1272        });
1273
1274        id
1275    }
1276
1277    /// Starts a timer with the provided timer id.
1278    ///
1279    /// Events sent within the timer callback provided in `add_timer()` will target the current view.
1280    pub fn start_timer(&mut self, timer: Timer) {
1281        let current = self.current;
1282        if !self.timer_is_running(timer) {
1283            let timer_state = self.timers[timer.0].clone();
1284            // Copy timer state from pending to playing
1285            self.running_timers.push(timer_state);
1286        }
1287
1288        self.modify_timer(timer, |timer_state| {
1289            let now = Instant::now();
1290            timer_state.start_time = now;
1291            timer_state.time = now;
1292            timer_state.entity = current;
1293            timer_state.ticking = false;
1294            timer_state.stopping = false;
1295        });
1296    }
1297
1298    /// Modifies the state of an existing timer with the provided `Timer` id.
1299    pub fn modify_timer(&mut self, timer: Timer, timer_function: impl Fn(&mut TimerState)) {
1300        while let Some(next_timer_state) = self.running_timers.peek() {
1301            if next_timer_state.id == timer {
1302                let mut timer_state = self.running_timers.pop().unwrap();
1303
1304                (timer_function)(&mut timer_state);
1305
1306                self.running_timers.push(timer_state);
1307
1308                return;
1309            }
1310        }
1311
1312        for pending_timer in self.timers.iter_mut() {
1313            if pending_timer.id == timer {
1314                (timer_function)(pending_timer);
1315            }
1316        }
1317    }
1318
1319    pub fn query_timer<T>(
1320        &mut self,
1321        timer: Timer,
1322        timer_function: impl Fn(&TimerState) -> T,
1323    ) -> Option<T> {
1324        while let Some(next_timer_state) = self.running_timers.peek() {
1325            if next_timer_state.id == timer {
1326                let timer_state = self.running_timers.pop().unwrap();
1327
1328                let t = (timer_function)(&timer_state);
1329
1330                self.running_timers.push(timer_state);
1331
1332                return Some(t);
1333            }
1334        }
1335
1336        for pending_timer in self.timers.iter() {
1337            if pending_timer.id == timer {
1338                return Some(timer_function(pending_timer));
1339            }
1340        }
1341
1342        None
1343    }
1344
1345    /// Returns true if the timer with the provided timer id is currently running.
1346    pub fn timer_is_running(&mut self, timer: Timer) -> bool {
1347        for timer_state in self.running_timers.iter() {
1348            if timer_state.id == timer {
1349                return true;
1350            }
1351        }
1352
1353        false
1354    }
1355
1356    /// Stops the timer with the given timer id.
1357    ///
1358    /// Any events emitted in response to the timer stopping, as determined by the callback provided in `add_timer()`, will target the view which called `start_timer()`.
1359    pub fn stop_timer(&mut self, timer: Timer) {
1360        let mut running_timers = self.running_timers.clone();
1361
1362        for timer_state in running_timers.iter() {
1363            if timer_state.id == timer {
1364                self.with_current(timer_state.entity, |cx| {
1365                    (timer_state.callback)(cx, TimerAction::Stop);
1366                });
1367            }
1368        }
1369
1370        *self.running_timers =
1371            running_timers.drain().filter(|timer_state| timer_state.id != timer).collect();
1372    }
1373}
1374
1375impl DataContext for EventContext<'_> {
1376    fn try_data<T: 'static>(&self) -> Option<&T> {
1377        // Return data for the static model.
1378        if let Some(t) = <dyn Any>::downcast_ref::<T>(&()) {
1379            return Some(t);
1380        }
1381
1382        for entity in self.current.parent_iter(self.tree) {
1383            // Return model data.
1384            if let Some(models) = self.models.get(&entity) {
1385                if let Some(model) = models.get(&TypeId::of::<T>()) {
1386                    return model.downcast_ref::<T>();
1387                }
1388            }
1389
1390            // Return view data.
1391            if let Some(view_handler) = self.views.get(&entity) {
1392                if let Some(data) = view_handler.downcast_ref::<T>() {
1393                    return Some(data);
1394                }
1395            }
1396        }
1397
1398        None
1399    }
1400
1401    fn localization_context(&self) -> Option<LocalizationContext<'_>> {
1402        Some(LocalizationContext::from_event_context(self))
1403    }
1404}
1405
1406impl EmitContext for EventContext<'_> {
1407    fn emit<M: Any + Send>(&mut self, message: M) {
1408        self.event_queue.push_back(
1409            Event::new(message)
1410                .target(self.current)
1411                .origin(self.current)
1412                .propagate(Propagation::Up),
1413        );
1414    }
1415
1416    fn emit_to<M: Any + Send>(&mut self, target: Entity, message: M) {
1417        self.event_queue.push_back(
1418            Event::new(message).target(target).origin(self.current).propagate(Propagation::Direct),
1419        );
1420    }
1421
1422    fn emit_custom(&mut self, event: Event) {
1423        self.event_queue.push_back(event);
1424    }
1425
1426    fn schedule_emit<M: Any + Send>(&mut self, message: M, at: Instant) -> TimedEventHandle {
1427        self.schedule_emit_custom(
1428            Event::new(message)
1429                .target(self.current)
1430                .origin(self.current)
1431                .propagate(Propagation::Up),
1432            at,
1433        )
1434    }
1435    fn schedule_emit_to<M: Any + Send>(
1436        &mut self,
1437        target: Entity,
1438        message: M,
1439        at: Instant,
1440    ) -> TimedEventHandle {
1441        self.schedule_emit_custom(
1442            Event::new(message).target(target).origin(self.current).propagate(Propagation::Direct),
1443            at,
1444        )
1445    }
1446    fn schedule_emit_custom(&mut self, event: Event, at: Instant) -> TimedEventHandle {
1447        let handle = TimedEventHandle(*self.next_event_id);
1448        self.event_schedule.push(TimedEvent { event, time: at, ident: handle });
1449        *self.next_event_id += 1;
1450        handle
1451    }
1452    fn cancel_scheduled(&mut self, handle: TimedEventHandle) {
1453        *self.event_schedule =
1454            self.event_schedule.drain().filter(|item| item.ident != handle).collect();
1455    }
1456}
1457
1458/// Trait for querying properties of the tree from a context.
1459pub trait TreeProps {
1460    /// Returns the entity id of the parent of the current view.
1461    fn parent(&self) -> Entity;
1462    /// Returns the entity id of the first_child of the current view.
1463    fn first_child(&self) -> Entity;
1464    /// Returns the entity id of the parent window of the current view.
1465    fn parent_window(&self) -> Entity;
1466}
1467
1468impl TreeProps for EventContext<'_> {
1469    fn parent(&self) -> Entity {
1470        self.tree.get_layout_parent(self.current).unwrap()
1471    }
1472
1473    fn first_child(&self) -> Entity {
1474        self.tree.get_layout_first_child(self.current).unwrap()
1475    }
1476
1477    fn parent_window(&self) -> Entity {
1478        self.tree.get_parent_window(self.current).unwrap_or(Entity::root())
1479    }
1480}