vizia_core/context/
mod.rs

1//! Context types for retained state, used during view building, event handling, and drawing.
2
3mod access;
4#[doc(hidden)]
5pub mod backend;
6mod draw;
7mod event;
8mod proxy;
9mod resource;
10
11use log::debug;
12use skia_safe::{
13    FontMgr, svg,
14    textlayout::{FontCollection, TypefaceFontProvider},
15};
16use std::cell::RefCell;
17use std::collections::{BinaryHeap, VecDeque};
18use std::rc::Rc;
19use std::sync::Mutex;
20use std::{
21    any::{Any, TypeId},
22    sync::Arc,
23};
24use vizia_id::IdManager;
25use vizia_window::WindowDescription;
26
27#[cfg(feature = "clipboard")]
28use copypasta::{ClipboardContext, ClipboardProvider, nop_clipboard::NopClipboardContext};
29use hashbrown::{HashMap, HashSet, hash_map::Entry};
30
31pub use access::*;
32pub use draw::*;
33pub use event::*;
34pub use proxy::*;
35pub use resource::*;
36
37use crate::{
38    binding::{Store, StoreId},
39    events::{TimedEvent, TimedEventHandle, TimerState, ViewHandler},
40    model::ModelData,
41};
42
43use crate::{
44    binding::{BindingHandler, MapId},
45    resource::StoredImage,
46};
47use crate::{cache::CachedData, resource::ImageOrSvg};
48
49use crate::prelude::*;
50use crate::resource::ResourceManager;
51use crate::text::TextContext;
52use vizia_input::{ImeState, MouseState};
53use vizia_storage::{ChildIterator, LayoutTreeIterator};
54
55static DEFAULT_LAYOUT: &str = include_str!("../../resources/themes/default_layout.css");
56static DARK_THEME: &str = include_str!("../../resources/themes/dark_theme.css");
57static LIGHT_THEME: &str = include_str!("../../resources/themes/light_theme.css");
58static MARKDOWN: &str = include_str!("../../resources/themes/markdown.css");
59
60type Views = HashMap<Entity, Box<dyn ViewHandler>>;
61type Models = HashMap<Entity, HashMap<TypeId, Box<dyn ModelData>>>;
62type Stores = HashMap<Entity, HashMap<StoreId, Box<dyn Store>>>;
63type Bindings = HashMap<Entity, Box<dyn BindingHandler>>;
64
65thread_local! {
66    /// ID manager for lens map functions.
67    pub static MAP_MANAGER: RefCell<IdManager<MapId>> = RefCell::new(IdManager::new());
68    /// Store of mapping functions used for lens maps.
69    pub static MAPS: RefCell<HashMap<MapId, (Entity, Box<dyn Any>)>> = RefCell::new(HashMap::new());
70    /// The 'current' entity which is used for storing lens map mapping functions as per above.
71    pub static CURRENT: RefCell<Entity> = RefCell::new(Entity::root());
72}
73
74#[derive(Default, Clone)]
75pub struct WindowState {
76    pub window_description: WindowDescription,
77    pub scale_factor: f32,
78    pub needs_relayout: bool,
79    pub needs_redraw: bool,
80    pub redraw_list: HashSet<Entity>,
81    pub dirty_rect: Option<BoundingBox>,
82    pub owner: Option<Entity>,
83    pub is_modal: bool,
84    pub should_close: bool,
85    pub content: Option<Arc<dyn Fn(&mut Context)>>,
86}
87
88/// The main storage and control object for a Vizia application.
89pub struct Context {
90    pub(crate) entity_manager: IdManager<Entity>,
91    pub(crate) entity_identifiers: HashMap<String, Entity>,
92    pub tree: Tree<Entity>,
93    pub(crate) current: Entity,
94    pub(crate) views: Views,
95    pub(crate) models: Models,
96    pub(crate) stores: Stores,
97    pub(crate) bindings: Bindings,
98    pub(crate) event_queue: VecDeque<Event>,
99    pub(crate) event_schedule: BinaryHeap<TimedEvent>,
100    pub(crate) next_event_id: usize,
101    pub(crate) timers: Vec<TimerState>,
102    pub(crate) running_timers: BinaryHeap<TimerState>,
103    pub tree_updates: Vec<Option<accesskit::TreeUpdate>>,
104    pub(crate) listeners:
105        HashMap<Entity, Box<dyn Fn(&mut dyn ViewHandler, &mut EventContext, &mut Event)>>,
106    pub(crate) global_listeners: Vec<Box<dyn Fn(&mut EventContext, &mut Event)>>,
107    pub(crate) style: Style,
108    pub(crate) cache: CachedData,
109    pub windows: HashMap<Entity, WindowState>,
110
111    pub mouse: MouseState<Entity>,
112    pub(crate) modifiers: Modifiers,
113
114    pub(crate) captured: Entity,
115    pub(crate) triggered: Entity,
116    pub(crate) hovered: Entity,
117    pub(crate) focused: Entity,
118    pub(crate) focus_stack: Vec<Entity>,
119    pub(crate) cursor_icon_locked: bool,
120
121    pub(crate) resource_manager: ResourceManager,
122
123    pub text_context: TextContext,
124
125    pub(crate) event_proxy: Option<Box<dyn EventProxy>>,
126
127    #[cfg(feature = "clipboard")]
128    pub(crate) clipboard: Box<dyn ClipboardProvider>,
129
130    pub(crate) click_time: Instant,
131    pub(crate) clicks: usize,
132    pub(crate) click_pos: (f32, f32),
133    pub(crate) click_button: MouseButton,
134
135    pub ignore_default_theme: bool,
136    pub window_has_focus: bool,
137    pub ime_state: ImeState,
138
139    pub(crate) drop_data: Option<DropData>,
140}
141
142impl Default for Context {
143    fn default() -> Self {
144        Context::new()
145    }
146}
147
148impl Context {
149    /// Creates a new context.
150    pub fn new() -> Self {
151        let mut cache = CachedData::default();
152        cache.add(Entity::root());
153
154        let mut result = Self {
155            entity_manager: IdManager::new(),
156            entity_identifiers: HashMap::new(),
157            tree: Tree::new(),
158            current: Entity::root(),
159            views: HashMap::default(),
160            models: HashMap::default(),
161            stores: HashMap::default(),
162            bindings: HashMap::default(),
163            style: Style::default(),
164            cache,
165            windows: HashMap::new(),
166            event_queue: VecDeque::new(),
167            event_schedule: BinaryHeap::new(),
168            next_event_id: 0,
169            timers: Vec::new(),
170            running_timers: BinaryHeap::new(),
171            tree_updates: Vec::new(),
172            listeners: HashMap::default(),
173            global_listeners: Vec::new(),
174            mouse: MouseState::default(),
175            modifiers: Modifiers::empty(),
176            captured: Entity::null(),
177            triggered: Entity::null(),
178            hovered: Entity::root(),
179            focused: Entity::root(),
180            focus_stack: Vec::new(),
181            cursor_icon_locked: false,
182            resource_manager: ResourceManager::new(),
183            text_context: {
184                let mut font_collection = FontCollection::new();
185
186                let default_font_manager = FontMgr::default();
187
188                let asset_provider = TypefaceFontProvider::new();
189
190                font_collection.set_default_font_manager(default_font_manager.clone(), None);
191                let asset_font_manager: FontMgr = asset_provider.clone().into();
192                font_collection.set_asset_font_manager(asset_font_manager);
193
194                TextContext {
195                    font_collection,
196                    default_font_manager,
197                    asset_provider,
198                    text_bounds: Default::default(),
199                    text_paragraphs: Default::default(),
200                }
201            },
202
203            event_proxy: None,
204
205            #[cfg(feature = "clipboard")]
206            clipboard: {
207                if let Ok(context) = ClipboardContext::new() {
208                    Box::new(context)
209                } else {
210                    Box::new(NopClipboardContext::new().unwrap())
211                }
212            },
213            click_time: Instant::now(),
214            clicks: 0,
215            click_pos: (0.0, 0.0),
216            click_button: MouseButton::Left,
217
218            ignore_default_theme: false,
219            window_has_focus: true,
220
221            ime_state: Default::default(),
222
223            drop_data: None,
224        };
225
226        result.tree.set_window(Entity::root(), true);
227
228        result.style.needs_restyle(Entity::root());
229        result.style.needs_relayout();
230        result.style.needs_retransform(Entity::root());
231        result.style.needs_reclip(Entity::root());
232        result.needs_redraw(Entity::root());
233
234        // Set the default DPI factor to 1.0.
235        result.style.dpi_factor = 1.0;
236
237        // Build the environment model at the root.
238        Environment::new(&mut result).build(&mut result);
239
240        result.entity_manager.create();
241
242        result.style.role.insert(Entity::root(), Role::Window);
243
244        result
245    }
246
247    /// The "current" entity, generally the entity which is currently being built or the entity
248    /// which is currently having an event dispatched to it.
249    pub fn current(&self) -> Entity {
250        self.current
251    }
252
253    /// Makes the above black magic more explicit
254    pub fn with_current<T>(&mut self, current: Entity, f: impl FnOnce(&mut Context) -> T) -> T {
255        let previous = self.current;
256        self.current = current;
257        CURRENT.with_borrow_mut(|f| *f = current);
258        let ret = f(self);
259        CURRENT.with_borrow_mut(|f| *f = previous);
260        self.current = previous;
261        ret
262    }
263
264    /// Returns a reference to the [Environment] model.
265    pub fn environment(&self) -> &Environment {
266        self.data::<Environment>().unwrap()
267    }
268
269    /// Returns the entity id of the  parent window to the current view.
270    pub fn parent_window(&self) -> Entity {
271        self.tree.get_parent_window(self.current).unwrap_or(Entity::root())
272    }
273
274    /// Returns the scale factor of the display.
275    pub fn scale_factor(&self) -> f32 {
276        self.style.dpi_factor as f32
277    }
278
279    /// Mark the application as needing to rerun the draw method
280    pub fn needs_redraw(&mut self, entity: Entity) {
281        if self.entity_manager.is_alive(entity) {
282            // If a child window needs redrawing, add itself to the redraw list.
283            // This ensures that the entire window is redrawn: https://github.com/vizia/vizia/issues/580
284            let window = if self.tree.is_window(entity) {
285                entity
286            } else {
287                self.tree.get_parent_window(entity).unwrap_or(Entity::root())
288            };
289            if let Some(window_state) = self.windows.get_mut(&window) {
290                window_state.redraw_list.insert(entity);
291            }
292        }
293    }
294
295    /// Mark the application as needing to recompute view styles
296    pub fn needs_restyle(&mut self, entity: Entity) {
297        if entity == Entity::null() || self.style.restyle.contains(&entity) {
298            return;
299        }
300        self.style.restyle.insert(entity);
301        let iter = if let Some(parent) = self.tree.get_layout_parent(entity) {
302            LayoutTreeIterator::subtree(&self.tree, parent)
303        } else {
304            LayoutTreeIterator::subtree(&self.tree, entity)
305        };
306
307        for descendant in iter {
308            self.style.restyle.insert(descendant);
309        }
310        // self.style.needs_restyle();
311    }
312
313    pub fn needs_retransform(&mut self, entity: Entity) {
314        self.style.needs_retransform(entity);
315        let iter = LayoutTreeIterator::subtree(&self.tree, entity);
316        for descendant in iter {
317            self.style.needs_retransform(descendant);
318        }
319    }
320
321    pub fn needs_reclip(&mut self, entity: Entity) {
322        self.style.needs_reclip(entity);
323        let iter = LayoutTreeIterator::subtree(&self.tree, entity);
324        for descendant in iter {
325            self.style.needs_reclip(descendant);
326        }
327    }
328
329    /// Mark the application as needing to rerun layout computations
330    pub fn needs_relayout(&mut self) {
331        self.style.needs_relayout();
332    }
333
334    pub(crate) fn set_system_flags(&mut self, entity: Entity, system_flags: SystemFlags) {
335        if system_flags.contains(SystemFlags::RESTYLE) {
336            self.needs_restyle(entity);
337        }
338
339        if system_flags.contains(SystemFlags::REDRAW) {
340            self.needs_redraw(entity);
341        }
342
343        if system_flags.contains(SystemFlags::REFLOW) {
344            self.style.needs_text_update(entity);
345        }
346
347        if system_flags.contains(SystemFlags::RETRANSFORM) {
348            self.needs_retransform(entity);
349        }
350
351        if system_flags.contains(SystemFlags::RECLIP) {
352            self.needs_reclip(entity);
353        }
354    }
355
356    /// Enables or disables PseudoClasses for the focus of an entity
357    pub(crate) fn set_focus_pseudo_classes(
358        &mut self,
359        focused: Entity,
360        enabled: bool,
361        focus_visible: bool,
362    ) {
363        if enabled {
364            debug!(
365                "Focus changed to {:?} parent: {:?}, view: {}, posx: {}, posy: {} width: {} height: {}",
366                focused,
367                self.tree.get_parent(focused),
368                self.views
369                    .get(&focused)
370                    .map_or("<None>", |view| view.element().unwrap_or("<Unnamed>")),
371                self.cache.get_posx(focused),
372                self.cache.get_posy(focused),
373                self.cache.get_width(focused),
374                self.cache.get_height(focused),
375            );
376        }
377
378        if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(focused) {
379            pseudo_classes.set(PseudoClassFlags::FOCUS, enabled);
380            if !enabled || focus_visible {
381                pseudo_classes.set(PseudoClassFlags::FOCUS_VISIBLE, enabled);
382                self.style.needs_access_update(focused);
383                self.needs_restyle(focused);
384            }
385        }
386
387        for ancestor in focused.parent_iter(&self.tree) {
388            let entity = ancestor;
389            if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(entity) {
390                pseudo_classes.set(PseudoClassFlags::FOCUS_WITHIN, enabled);
391            }
392            // self.needs_restyle(entity);
393        }
394    }
395
396    /// Sets application focus to the current entity with the specified focus visiblity
397    pub fn focus_with_visibility(&mut self, focus_visible: bool) {
398        let old_focus = self.focused;
399        let new_focus = self.current;
400        self.set_focus_pseudo_classes(old_focus, false, focus_visible);
401        if self.current != self.focused {
402            self.emit_to(old_focus, WindowEvent::FocusOut);
403            self.emit_to(new_focus, WindowEvent::FocusIn);
404            self.focused = self.current;
405        }
406        self.set_focus_pseudo_classes(new_focus, true, focus_visible);
407
408        self.emit_custom(Event::new(WindowEvent::FocusVisibility(focus_visible)).target(old_focus));
409        self.emit_custom(Event::new(WindowEvent::FocusVisibility(focus_visible)).target(new_focus));
410
411        self.needs_restyle(self.focused);
412        self.needs_restyle(self.current);
413        self.style.needs_access_update(self.focused);
414        self.style.needs_access_update(self.current);
415    }
416
417    /// Sets application focus to the current entity using the previous focus visibility
418    pub fn focus(&mut self) {
419        let focused = self.focused;
420        let old_focus_visible = self
421            .style
422            .pseudo_classes
423            .get_mut(focused)
424            .filter(|class| class.contains(PseudoClassFlags::FOCUS_VISIBLE))
425            .is_some();
426        self.focus_with_visibility(old_focus_visible)
427    }
428
429    /// Removes the children of the provided entity from the application.
430    pub(crate) fn remove_children(&mut self, entity: Entity) {
431        let child_iter = ChildIterator::new(&self.tree, entity);
432        let children = child_iter.collect::<Vec<_>>();
433        for child in children.into_iter() {
434            self.remove(child);
435        }
436    }
437
438    /// Removes the provided entity from the application.
439    pub fn remove(&mut self, entity: Entity) {
440        let delete_list = entity.branch_iter(&self.tree).collect::<Vec<_>>();
441
442        if !delete_list.is_empty() {
443            self.style.needs_restyle(self.current);
444            self.style.needs_relayout();
445            self.needs_redraw(self.current);
446        }
447
448        for entity in delete_list.iter().rev() {
449            if let Some(mut view) = self.views.remove(entity) {
450                view.event(
451                    &mut EventContext::new_with_current(self, *entity),
452                    &mut Event::new(WindowEvent::Destroyed).direct(*entity),
453                );
454
455                self.views.insert(*entity, view);
456            }
457
458            if let Some(binding) = self.bindings.remove(entity) {
459                binding.remove(self);
460
461                self.bindings.insert(*entity, binding);
462            }
463
464            for image in self.resource_manager.images.values_mut() {
465                // no need to drop them here. garbage collection happens after draw (policy based)
466                image.observers.remove(entity);
467            }
468
469            if let Some(identifier) = self.style.ids.get(*entity) {
470                self.entity_identifiers.remove(identifier);
471            }
472
473            if let Some(index) = self.focus_stack.iter().position(|r| r == entity) {
474                self.focus_stack.remove(index);
475            }
476
477            if self.focused == *entity {
478                if let Some(new_focus) = self.focus_stack.pop() {
479                    self.with_current(new_focus, |cx| cx.focus());
480                } else {
481                    self.with_current(Entity::root(), |cx| cx.focus());
482                }
483            }
484
485            if self.captured == *entity {
486                self.captured = Entity::null();
487            }
488
489            // Remove any map lenses associated with the entity.
490
491            MAP_MANAGER.with_borrow_mut(|manager| {
492                MAPS.with_borrow_mut(|maps| {
493                    maps.retain(|id, (e, _)| {
494                        if e == entity {
495                            manager.destroy(*id);
496                            false
497                        } else {
498                            true
499                        }
500                    });
501                });
502            });
503
504            if let Some(parent) = self.tree.get_layout_parent(*entity) {
505                self.style.needs_access_update(parent);
506            }
507
508            let mut stopped_timers = Vec::new();
509
510            for timer in self.running_timers.iter() {
511                if timer.entity == *entity {
512                    stopped_timers.push(timer.id);
513                }
514            }
515
516            for timer in stopped_timers {
517                self.stop_timer(timer);
518            }
519
520            let window_entity = self.tree.get_parent_window(*entity).unwrap_or(Entity::root());
521
522            if !self.tree.is_window(*entity) {
523                if let Some(draw_bounds) = self.cache.draw_bounds.get(*entity) {
524                    if let Some(dirty_rect) =
525                        &mut self.windows.get_mut(&window_entity).unwrap().dirty_rect
526                    {
527                        *dirty_rect = dirty_rect.union(draw_bounds);
528                    } else {
529                        self.windows.get_mut(&window_entity).unwrap().dirty_rect =
530                            Some(*draw_bounds);
531                    }
532                }
533            }
534
535            self.windows.get_mut(&window_entity).unwrap().redraw_list.remove(entity);
536
537            if self.windows.contains_key(entity) {
538                self.windows.remove(entity);
539            }
540
541            self.tree.remove(*entity).expect("");
542            self.cache.remove(*entity);
543            self.style.remove(*entity);
544            self.models.remove(entity);
545            self.stores.remove(entity);
546            self.views.remove(entity);
547            self.text_context.text_bounds.remove(*entity);
548            self.text_context.text_paragraphs.remove(*entity);
549            self.entity_manager.destroy(*entity);
550        }
551    }
552
553    /// Add a listener to an entity.
554    ///
555    /// A listener can be used to handle events which would not normally propagate to the entity.
556    /// For example, mouse events when a different entity has captured them. Useful for things like
557    /// closing a popup when clicking outside of its bounding box.
558    pub fn add_listener<F, W>(&mut self, listener: F)
559    where
560        W: View,
561        F: 'static + Fn(&mut W, &mut EventContext, &mut Event),
562    {
563        self.listeners.insert(
564            self.current,
565            Box::new(move |event_handler, context, event| {
566                if let Some(widget) = event_handler.downcast_mut::<W>() {
567                    (listener)(widget, context, event);
568                }
569            }),
570        );
571    }
572
573    /// Adds a global listener to the application.
574    ///
575    /// Global listeners have the first opportunity to handle every event that is sent in an
576    /// application. They will *never* be removed. If you need a listener tied to the lifetime of a
577    /// view, use `add_listener`.
578    pub fn add_global_listener<F>(&mut self, listener: F)
579    where
580        F: 'static + Fn(&mut EventContext, &mut Event),
581    {
582        self.global_listeners.push(Box::new(listener));
583    }
584
585    /// Sets the language used by the application for localization.
586    pub fn set_language(&mut self, lang: LanguageIdentifier) {
587        let cx = &mut EventContext::new(self);
588        if let Some(mut models) = cx.models.remove(&Entity::root()) {
589            if let Some(model) = models.get_mut(&TypeId::of::<Environment>()) {
590                model.event(cx, &mut Event::new(EnvironmentEvent::SetLocale(lang)));
591            }
592
593            self.models.insert(Entity::root(), models);
594        }
595    }
596
597    pub fn add_font_mem(&mut self, data: impl AsRef<[u8]>) {
598        // self.text_context.font_system().db_mut().load_font_data(data.as_ref().to_vec());
599        self.text_context.asset_provider.register_typeface(
600            self.text_context.default_font_manager.new_from_data(data.as_ref(), None).unwrap(),
601            None,
602        );
603    }
604
605    /// Sets the global default font for the application.
606    pub fn set_default_font(&mut self, names: &[&str]) {
607        self.style.default_font = names
608            .iter()
609            .map(|x| FamilyOwned::Named(x.to_string()))
610            .chain(std::iter::once(FamilyOwned::Generic(GenericFontFamily::SansSerif)))
611            .collect();
612    }
613
614    /// Add a style string to the application.
615    pub(crate) fn add_theme(&mut self, theme: &str) {
616        self.resource_manager.themes.push(theme.to_owned());
617
618        EventContext::new(self).reload_styles().expect("Failed to reload styles");
619    }
620
621    pub fn add_stylesheet(&mut self, style: impl IntoCssStr) -> Result<(), std::io::Error> {
622        self.resource_manager.styles.push(Box::new(style));
623
624        EventContext::new(self).reload_styles().expect("Failed to reload styles");
625
626        Ok(())
627    }
628
629    /// Remove all user themes from the application.
630    pub fn remove_user_themes(&mut self) {
631        self.resource_manager.themes.clear();
632
633        self.add_theme(DEFAULT_LAYOUT);
634        self.add_theme(MARKDOWN);
635        if !self.ignore_default_theme {
636            let environment = self.data::<Environment>().expect("Failed to get environment");
637            match environment.theme.get_current_theme() {
638                ThemeMode::LightMode => self.add_theme(LIGHT_THEME),
639                ThemeMode::DarkMode => self.add_theme(DARK_THEME),
640            }
641        }
642    }
643
644    pub fn add_animation(&mut self, animation: AnimationBuilder) -> Animation {
645        self.style.add_animation(animation)
646    }
647
648    pub fn set_image_loader<F: 'static + Fn(&mut ResourceContext, &str)>(&mut self, loader: F) {
649        self.resource_manager.image_loader = Some(Box::new(loader));
650    }
651
652    pub fn add_translation(&mut self, lang: LanguageIdentifier, ftl: impl ToString) {
653        self.resource_manager.add_translation(lang, ftl.to_string());
654    }
655
656    /// Adds a timer to the application.
657    ///
658    /// `interval` - The time between ticks of the timer.
659    /// `duration` - An optional duration for the timer. Pass `None` for a continuos timer.
660    /// `callback` - A callback which is called on when the timer is started, ticks, and stops. Disambiguated by the `TimerAction` parameter of the callback.
661    ///
662    /// Returns a `Timer` id which can be used to start and stop the timer.  
663    ///
664    /// # Example
665    /// Creates a timer which calls the provided callback every second for 5 seconds:
666    /// ```rust
667    /// # use vizia_core::prelude::*;
668    /// # use instant::{Instant, Duration};
669    /// # let cx = &mut Context::default();
670    /// let timer = cx.add_timer(Duration::from_secs(1), Some(Duration::from_secs(5)), |cx, reason|{
671    ///     match reason {
672    ///         TimerAction::Start => {
673    ///             debug!("Start timer");
674    ///         }
675    ///     
676    ///         TimerAction::Tick(delta) => {
677    ///             debug!("Tick timer: {:?}", delta);
678    ///         }
679    ///
680    ///         TimerAction::Stop => {
681    ///             debug!("Stop timer");
682    ///         }
683    ///     }
684    /// });
685    /// ```
686    pub fn add_timer(
687        &mut self,
688        interval: Duration,
689        duration: Option<Duration>,
690        callback: impl Fn(&mut EventContext, TimerAction) + 'static,
691    ) -> Timer {
692        let id = Timer(self.timers.len());
693        self.timers.push(TimerState {
694            entity: Entity::root(),
695            id,
696            time: Instant::now(),
697            interval,
698            duration,
699            start_time: Instant::now(),
700            callback: Rc::new(callback),
701            ticking: false,
702            stopping: false,
703        });
704
705        id
706    }
707
708    /// Starts a timer with the provided timer id.
709    ///
710    /// Events sent within the timer callback provided in `add_timer()` will target the current view.
711    pub fn start_timer(&mut self, timer: Timer) {
712        let current = self.current;
713        if !self.timer_is_running(timer) {
714            let timer_state = self.timers[timer.0].clone();
715            // Copy timer state from pending to playing
716            self.running_timers.push(timer_state);
717        }
718
719        self.modify_timer(timer, |timer_state| {
720            let now = Instant::now();
721            timer_state.start_time = now;
722            timer_state.time = now;
723            timer_state.entity = current;
724            timer_state.ticking = false;
725            timer_state.stopping = false;
726        });
727    }
728
729    /// Modifies the state of an existing timer with the provided `Timer` id.
730    pub fn modify_timer(&mut self, timer: Timer, timer_function: impl Fn(&mut TimerState)) {
731        while let Some(next_timer_state) = self.running_timers.peek() {
732            if next_timer_state.id == timer {
733                let mut timer_state = self.running_timers.pop().unwrap();
734
735                (timer_function)(&mut timer_state);
736
737                self.running_timers.push(timer_state);
738
739                return;
740            }
741        }
742
743        for pending_timer in self.timers.iter_mut() {
744            if pending_timer.id == timer {
745                (timer_function)(pending_timer);
746            }
747        }
748    }
749
750    /// Returns true if the timer with the provided timer id is currently running.
751    pub fn timer_is_running(&mut self, timer: Timer) -> bool {
752        for timer_state in self.running_timers.iter() {
753            if timer_state.id == timer {
754                return true;
755            }
756        }
757
758        false
759    }
760
761    /// Stops the timer with the given timer id.
762    ///
763    /// 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()`.
764    pub fn stop_timer(&mut self, timer: Timer) {
765        let mut running_timers = self.running_timers.clone();
766
767        for timer_state in running_timers.iter() {
768            if timer_state.id == timer {
769                (timer_state.callback)(
770                    &mut EventContext::new_with_current(self, timer_state.entity),
771                    TimerAction::Stop,
772                );
773            }
774        }
775
776        self.running_timers =
777            running_timers.drain().filter(|timer_state| timer_state.id != timer).collect();
778    }
779
780    // Tick all timers.
781    pub(crate) fn tick_timers(&mut self) {
782        let now = Instant::now();
783        while let Some(next_timer_state) = self.running_timers.peek() {
784            if next_timer_state.time <= now {
785                let mut timer_state = self.running_timers.pop().unwrap();
786
787                if timer_state.end_time().unwrap_or_else(|| now + Duration::from_secs(1)) >= now {
788                    if !timer_state.ticking {
789                        (timer_state.callback)(
790                            &mut EventContext::new_with_current(self, timer_state.entity),
791                            TimerAction::Start,
792                        );
793                        timer_state.ticking = true;
794                    } else {
795                        (timer_state.callback)(
796                            &mut EventContext::new_with_current(self, timer_state.entity),
797                            TimerAction::Tick(now - timer_state.time),
798                        );
799                    }
800                    timer_state.time = now + timer_state.interval - (now - timer_state.time);
801                    self.running_timers.push(timer_state);
802                } else {
803                    (timer_state.callback)(
804                        &mut EventContext::new_with_current(self, timer_state.entity),
805                        TimerAction::Stop,
806                    );
807                }
808            } else {
809                break;
810            }
811        }
812    }
813
814    pub fn load_image(&mut self, path: &str, data: &'static [u8], policy: ImageRetentionPolicy) {
815        let id = if let Some(image_id) = self.resource_manager.image_ids.get(path) {
816            *image_id
817        } else {
818            let id = self.resource_manager.image_id_manager.create();
819            self.resource_manager.image_ids.insert(path.to_owned(), id);
820            id
821        };
822
823        if let Some(image) =
824            skia_safe::Image::from_encoded(unsafe { skia_safe::Data::new_bytes(data) })
825        {
826            match self.resource_manager.images.entry(id) {
827                Entry::Occupied(mut occ) => {
828                    occ.get_mut().image = ImageOrSvg::Image(image);
829                    occ.get_mut().dirty = true;
830                    occ.get_mut().retention_policy = policy;
831                }
832                Entry::Vacant(vac) => {
833                    vac.insert(StoredImage {
834                        image: ImageOrSvg::Image(image),
835                        retention_policy: policy,
836                        used: true,
837                        dirty: false,
838                        observers: HashSet::new(),
839                    });
840                }
841            }
842            self.style.needs_relayout();
843        }
844    }
845
846    pub fn load_svg(&mut self, path: &str, data: &[u8], policy: ImageRetentionPolicy) -> ImageId {
847        let id = if let Some(image_id) = self.resource_manager.image_ids.get(path) {
848            return *image_id;
849        } else {
850            let id = self.resource_manager.image_id_manager.create();
851            self.resource_manager.image_ids.insert(path.to_owned(), id);
852            id
853        };
854
855        if let Ok(svg) = svg::Dom::from_bytes(data, self.text_context.default_font_manager.clone())
856        {
857            match self.resource_manager.images.entry(id) {
858                Entry::Occupied(mut occ) => {
859                    occ.get_mut().image = ImageOrSvg::Svg(svg);
860                    occ.get_mut().dirty = true;
861                    occ.get_mut().retention_policy = policy;
862                }
863                Entry::Vacant(vac) => {
864                    vac.insert(StoredImage {
865                        image: ImageOrSvg::Svg(svg),
866                        retention_policy: policy,
867                        used: true,
868                        dirty: false,
869                        observers: HashSet::new(),
870                    });
871                }
872            }
873            self.style.needs_relayout();
874        }
875
876        id
877    }
878
879    pub fn spawn<F>(&self, target: F)
880    where
881        F: 'static + Send + FnOnce(&mut ContextProxy),
882    {
883        let mut cxp = ContextProxy {
884            current: self.current,
885            event_proxy: self.event_proxy.as_ref().map(|p| p.make_clone()),
886        };
887
888        std::thread::spawn(move || target(&mut cxp));
889    }
890
891    pub fn get_proxy(&self) -> ContextProxy {
892        ContextProxy {
893            current: self.current,
894            event_proxy: self.event_proxy.as_ref().map(|p| p.make_clone()),
895        }
896    }
897
898    /// Finds the entity that identifier identifies
899    pub fn resolve_entity_identifier(&self, identity: &str) -> Option<Entity> {
900        self.entity_identifiers.get(identity).cloned()
901    }
902
903    /// Toggles the addition/removal of a class name for the current view.
904    ///
905    /// # Example
906    /// ```rust
907    /// # use vizia_core::prelude::*;
908    /// # let context = &mut Context::default();
909    /// # let mut cx = &mut EventContext::new(context);
910    /// cx.toggle_class("foo", true);
911    /// ```
912    pub fn toggle_class(&mut self, class_name: &str, applied: bool) {
913        let current = self.current();
914        if let Some(class_list) = self.style.classes.get_mut(current) {
915            if applied {
916                class_list.insert(class_name.to_string());
917            } else {
918                class_list.remove(class_name);
919            }
920        } else if applied {
921            let mut class_list = HashSet::new();
922            class_list.insert(class_name.to_string());
923            self.style.classes.insert(current, class_list);
924        }
925
926        self.style.needs_restyle(self.current);
927    }
928
929    pub fn set_ime_state(&mut self, new_state: ImeState) {
930        self.ime_state = new_state;
931    }
932}
933
934pub(crate) enum InternalEvent {
935    Redraw,
936    LoadImage { path: String, image: Mutex<Option<skia_safe::Image>>, policy: ImageRetentionPolicy },
937}
938
939pub struct LocalizationContext<'a> {
940    pub(crate) current: Entity,
941    pub(crate) resource_manager: &'a ResourceManager,
942    pub(crate) models: &'a Models,
943    pub(crate) views: &'a Views,
944    pub(crate) tree: &'a Tree<Entity>,
945}
946
947impl<'a> LocalizationContext<'a> {
948    pub(crate) fn from_context(cx: &'a Context) -> Self {
949        Self {
950            current: cx.current,
951            resource_manager: &cx.resource_manager,
952            models: &cx.models,
953            views: &cx.views,
954            tree: &cx.tree,
955        }
956    }
957
958    pub(crate) fn from_event_context(cx: &'a EventContext) -> Self {
959        Self {
960            current: cx.current,
961            resource_manager: cx.resource_manager,
962            models: cx.models,
963            views: cx.views,
964            tree: cx.tree,
965        }
966    }
967
968    pub(crate) fn environment(&self) -> &Environment {
969        self.data::<Environment>().unwrap()
970    }
971}
972
973/// A trait for any Context-like object that lets you access stored model data.
974///
975/// This lets e.g Lens::get be generic over any of these types.
976pub trait DataContext {
977    /// Get model/view data from the context. Returns `None` if the data does not exist.
978    fn data<T: 'static>(&self) -> Option<&T>;
979
980    /// Convert the current context into a [LocalizationContext].
981    fn localization_context(&self) -> Option<LocalizationContext<'_>> {
982        None
983    }
984}
985
986/// A trait for any Context-like object that lets you emit events.
987pub trait EmitContext {
988    /// Send an event containing the provided message up the tree from the current entity.
989    ///
990    /// # Example
991    /// ```rust
992    /// # use vizia_core::prelude::*;
993    /// # use instant::{Instant, Duration};
994    /// # let cx = &mut Context::default();
995    /// # enum AppEvent {Increment}
996    /// cx.emit(AppEvent::Increment);
997    /// ```
998    fn emit<M: Any + Send>(&mut self, message: M);
999
1000    /// Send an event containing the provided message directly to a specified entity from the current entity.
1001    ///
1002    /// # Example
1003    /// ```rust
1004    /// # use vizia_core::prelude::*;
1005    /// # use instant::{Instant, Duration};
1006    /// # let cx = &mut Context::default();
1007    /// # enum AppEvent {Increment}
1008    /// cx.emit_to(Entity::root(), AppEvent::Increment);
1009    /// ```
1010    fn emit_to<M: Any + Send>(&mut self, target: Entity, message: M);
1011
1012    /// Send a custom event with custom origin and propagation information.
1013    ///
1014    /// # Example
1015    /// ```rust
1016    /// # use vizia_core::prelude::*;
1017    /// # use instant::{Instant, Duration};
1018    /// # let cx = &mut Context::default();
1019    /// # enum AppEvent {Increment}
1020    /// cx.emit_custom(
1021    ///     Event::new(AppEvent::Increment)
1022    ///         .origin(cx.current())
1023    ///         .target(Entity::root())
1024    ///         .propagate(Propagation::Subtree)
1025    /// );
1026    /// ```
1027    fn emit_custom(&mut self, event: Event);
1028
1029    /// Send an event containing the provided message up the tree at a particular time instant.
1030    ///
1031    /// Returns a `TimedEventHandle` which can be used to cancel the scheduled event.
1032    ///
1033    /// # Example
1034    /// Emit an event after a delay of 2 seconds:
1035    /// ```rust
1036    /// # use vizia_core::prelude::*;
1037    /// # use instant::{Instant, Duration};
1038    /// # let cx = &mut Context::default();
1039    /// # enum AppEvent {Increment}
1040    /// cx.schedule_emit(AppEvent::Increment, Instant::now() + Duration::from_secs(2));
1041    /// ```
1042    fn schedule_emit<M: Any + Send>(&mut self, message: M, at: Instant) -> TimedEventHandle;
1043
1044    /// Send an event containing the provided message directly to a specified view at a particular time instant.
1045    ///
1046    /// Returns a `TimedEventHandle` which can be used to cancel the scheduled event.
1047    ///
1048    /// # Example
1049    /// Emit an event to the root view (window) after a delay of 2 seconds:
1050    /// ```rust
1051    /// # use vizia_core::prelude::*;
1052    /// # use instant::{Instant, Duration};
1053    /// # let cx = &mut Context::default();
1054    /// # enum AppEvent {Increment}
1055    /// cx.schedule_emit_to(Entity::root(), AppEvent::Increment, Instant::now() + Duration::from_secs(2));
1056    /// ```
1057    fn schedule_emit_to<M: Any + Send>(
1058        &mut self,
1059        target: Entity,
1060        message: M,
1061        at: Instant,
1062    ) -> TimedEventHandle;
1063
1064    /// Send a custom event with custom origin and propagation information at a particular time instant.
1065    ///
1066    /// Returns a `TimedEventHandle` which can be used to cancel the scheduled event.
1067    ///
1068    /// # Example
1069    /// Emit a custom event after a delay of 2 seconds:
1070    /// ```rust
1071    /// # use vizia_core::prelude::*;
1072    /// # use instant::{Instant, Duration};
1073    /// # let cx = &mut Context::default();
1074    /// # enum AppEvent {Increment}
1075    /// cx.schedule_emit_custom(    
1076    ///     Event::new(AppEvent::Increment)
1077    ///         .target(Entity::root())
1078    ///         .origin(cx.current())
1079    ///         .propagate(Propagation::Subtree),
1080    ///     Instant::now() + Duration::from_secs(2)
1081    /// );
1082    /// ```
1083    fn schedule_emit_custom(&mut self, event: Event, at: Instant) -> TimedEventHandle;
1084
1085    /// Cancel a scheduled event before it is sent.
1086    ///
1087    /// # Example
1088    /// ```rust
1089    /// # use vizia_core::prelude::*;
1090    /// # use instant::{Instant, Duration};
1091    /// # let cx = &mut Context::default();
1092    /// # enum AppEvent {Increment}
1093    /// let timed_event = cx.schedule_emit_to(Entity::root(), AppEvent::Increment, Instant::now() + Duration::from_secs(2));
1094    /// cx.cancel_scheduled(timed_event);
1095    /// ```
1096    fn cancel_scheduled(&mut self, handle: TimedEventHandle);
1097}
1098
1099impl DataContext for Context {
1100    fn data<T: 'static>(&self) -> Option<&T> {
1101        // return data for the static model.
1102        if let Some(t) = <dyn Any>::downcast_ref::<T>(&()) {
1103            return Some(t);
1104        }
1105
1106        for entity in self.current.parent_iter(&self.tree) {
1107            // Return any model data.
1108            if let Some(models) = self.models.get(&entity) {
1109                if let Some(model) = models.get(&TypeId::of::<T>()) {
1110                    return model.downcast_ref::<T>();
1111                }
1112            }
1113
1114            // Return any view data.
1115            if let Some(view_handler) = self.views.get(&entity) {
1116                if let Some(data) = view_handler.downcast_ref::<T>() {
1117                    return Some(data);
1118                }
1119            }
1120        }
1121
1122        None
1123    }
1124
1125    fn localization_context(&self) -> Option<LocalizationContext<'_>> {
1126        Some(LocalizationContext::from_context(self))
1127    }
1128}
1129
1130impl DataContext for LocalizationContext<'_> {
1131    fn data<T: 'static>(&self) -> Option<&T> {
1132        // return data for the static model.
1133        if let Some(t) = <dyn Any>::downcast_ref::<T>(&()) {
1134            return Some(t);
1135        }
1136
1137        for entity in self.current.parent_iter(self.tree) {
1138            // Return any model data.
1139            if let Some(models) = self.models.get(&entity) {
1140                if let Some(model) = models.get(&TypeId::of::<T>()) {
1141                    return model.downcast_ref::<T>();
1142                }
1143            }
1144
1145            // Return any view data.
1146            if let Some(view_handler) = self.views.get(&entity) {
1147                if let Some(data) = view_handler.downcast_ref::<T>() {
1148                    return Some(data);
1149                }
1150            }
1151        }
1152
1153        None
1154    }
1155}
1156
1157impl EmitContext for Context {
1158    fn emit<M: Any + Send>(&mut self, message: M) {
1159        self.event_queue.push_back(
1160            Event::new(message)
1161                .target(self.current)
1162                .origin(self.current)
1163                .propagate(Propagation::Up),
1164        );
1165    }
1166
1167    fn emit_to<M: Any + Send>(&mut self, target: Entity, message: M) {
1168        self.event_queue.push_back(
1169            Event::new(message).target(target).origin(self.current).propagate(Propagation::Direct),
1170        );
1171    }
1172
1173    fn emit_custom(&mut self, event: Event) {
1174        self.event_queue.push_back(event);
1175    }
1176
1177    fn schedule_emit<M: Any + Send>(&mut self, message: M, at: Instant) -> TimedEventHandle {
1178        self.schedule_emit_custom(
1179            Event::new(message)
1180                .target(self.current)
1181                .origin(self.current)
1182                .propagate(Propagation::Up),
1183            at,
1184        )
1185    }
1186
1187    fn schedule_emit_to<M: Any + Send>(
1188        &mut self,
1189        target: Entity,
1190        message: M,
1191        at: Instant,
1192    ) -> TimedEventHandle {
1193        self.schedule_emit_custom(
1194            Event::new(message).target(target).origin(self.current).propagate(Propagation::Direct),
1195            at,
1196        )
1197    }
1198
1199    fn schedule_emit_custom(&mut self, event: Event, at: Instant) -> TimedEventHandle {
1200        let handle = TimedEventHandle(self.next_event_id);
1201        self.event_schedule.push(TimedEvent { event, time: at, ident: handle });
1202        self.next_event_id += 1;
1203        handle
1204    }
1205
1206    fn cancel_scheduled(&mut self, handle: TimedEventHandle) {
1207        self.event_schedule =
1208            self.event_schedule.drain().filter(|item| item.ident != handle).collect();
1209    }
1210}