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