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