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