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