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