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
30pub 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 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 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 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 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 pub fn resolve_entity_identifier(&self, id: &str) -> Option<Entity> {
193 self.entity_identifiers.get(id).cloned()
194 }
195
196 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 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 pub fn current(&self) -> Entity {
227 self.current
228 }
229
230 pub fn modifiers(&self) -> &Modifiers {
232 self.modifiers
233 }
234
235 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 pub fn has_drop_data(&self) -> bool {
258 self.drop_data.is_some()
259 }
260
261 pub fn drop_data(&self) -> Option<&DropData> {
263 self.drop_data.as_ref()
264 }
265
266 pub fn active_drag_view(&self) -> Option<Entity> {
268 *self.active_drag_view
269 }
270
271 pub fn set_active_drag_view(&mut self, drag_view: Option<Entity>) {
273 *self.active_drag_view = drag_view;
274 }
275
276 pub fn bounds(&self) -> BoundingBox {
278 self.cache.get_bounds(self.current)
279 }
280
281 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 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 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 pub fn parent_transformed_bounds(&self) -> BoundingBox {
312 self.transformed_bounds(self.parent())
313 }
314
315 pub fn scale_factor(&self) -> f32 {
321 self.style.dpi_factor as f32
322 }
323
324 pub fn logical_to_physical(&self, logical: f32) -> f32 {
326 self.style.logical_to_physical(logical)
327 }
328
329 pub fn physical_to_logical(&self, physical: f32) -> f32 {
331 self.style.physical_to_logical(physical)
332 }
333
334 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 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 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 pub fn transform(&self) -> Matrix {
382 self.cache.transform.get(self.current).copied().unwrap_or_default()
383 }
384
385 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 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 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 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 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_resource_loader<L: crate::resource::ResourceLoader>(&mut self, loader: L) {
453 self.resource_manager.resource_loaders.insert(0, Box::new(loader));
454 }
455
456 pub fn load_image_encoded(&mut self, path: &str, data: &[u8], policy: ImageRetentionPolicy) {
457 let id = if let Some(image_id) = self.resource_manager.image_ids.get(path) {
458 *image_id
459 } else {
460 let id = self.resource_manager.image_id_manager.create();
461 self.resource_manager.image_ids.insert(path.to_owned(), id);
462 id
463 };
464
465 if let Some(image) = skia_safe::Image::from_encoded(skia_safe::Data::new_copy(data)) {
466 match self.resource_manager.images.entry(id) {
467 Entry::Occupied(mut occ) => {
468 occ.get_mut().image = ImageOrSvg::Image(image);
469 occ.get_mut().dirty = true;
470 occ.get_mut().retention_policy = policy;
471 }
472 Entry::Vacant(vac) => {
473 vac.insert(StoredImage {
474 image: ImageOrSvg::Image(image),
475 retention_policy: policy,
476 used: true,
477 dirty: false,
478 observers: HashSet::new(),
479 });
480 }
481 }
482 let observers: Vec<Entity> = self
485 .resource_manager
486 .images
487 .get(&id)
488 .map(|img| img.observers.iter().copied().collect())
489 .unwrap_or_default();
490 for observer in observers {
491 self.style.needs_relayout(observer);
492 }
493 self.style.needs_relayout(self.current);
494 }
495 }
496
497 pub fn capture(&mut self) {
499 *self.captured = self.current;
500 }
501
502 pub fn release(&mut self) {
504 if self.current == *self.captured {
505 *self.captured = Entity::null();
506 }
507 }
508
509 fn set_focus_pseudo_classes(&mut self, focused: Entity, enabled: bool, focus_visible: bool) {
511 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(focused) {
512 pseudo_classes.set(PseudoClassFlags::FOCUS, enabled);
513 if !enabled || focus_visible {
514 pseudo_classes.set(PseudoClassFlags::FOCUS_VISIBLE, enabled);
515 }
516 }
517
518 for ancestor in focused.parent_iter(self.tree) {
519 let entity = ancestor;
520 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(entity) {
521 pseudo_classes.set(PseudoClassFlags::FOCUS_WITHIN, enabled);
522 }
523 self.style.needs_restyle(entity);
524 }
525 }
526
527 pub fn focus_with_visibility(&mut self, focus_visible: bool) {
529 let focusable = self.current == Entity::root()
530 || self
531 .style
532 .abilities
533 .get(self.current)
534 .is_some_and(|abilities| abilities.contains(Abilities::FOCUSABLE));
535 if !focusable {
536 return;
537 }
538
539 let old_focus = self.focused();
540 let new_focus = self.current();
541 self.set_focus_pseudo_classes(old_focus, false, focus_visible);
542 if self.current() != self.focused() {
543 self.emit_to(old_focus, WindowEvent::FocusOut);
544 self.emit_to(new_focus, WindowEvent::FocusIn);
545 *self.focused = self.current();
546 }
547 self.set_focus_pseudo_classes(new_focus, true, focus_visible);
548
549 self.emit_custom(Event::new(WindowEvent::FocusVisibility(focus_visible)).target(old_focus));
550 self.emit_custom(Event::new(WindowEvent::FocusVisibility(focus_visible)).target(new_focus));
551
552 self.needs_restyle();
553 }
554
555 pub fn focus(&mut self) {
559 let focused = self.focused();
560 let old_focus_visible = self
561 .style
562 .pseudo_classes
563 .get_mut(focused)
564 .filter(|class| class.contains(PseudoClassFlags::FOCUS_VISIBLE))
565 .is_some();
566 self.focus_with_visibility(old_focus_visible)
567 }
568
569 pub fn focus_next(&mut self) {
571 let lock_focus_to = self.tree.lock_focus_within(*self.focused);
572 let next_focused = if let Some(next_focused) =
573 focus_forward(self.tree, self.style, *self.focused, lock_focus_to)
574 {
575 next_focused
576 } else {
577 TreeIterator::full(self.tree)
578 .find(|node| is_navigatable(self.tree, self.style, *node, lock_focus_to))
579 .unwrap_or(Entity::root())
580 };
581
582 if next_focused != *self.focused {
583 self.event_queue.push_back(
584 Event::new(WindowEvent::FocusOut).target(*self.focused).origin(Entity::root()),
585 );
586 self.event_queue.push_back(
587 Event::new(WindowEvent::FocusIn).target(next_focused).origin(Entity::root()),
588 );
589
590 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(*self.triggered) {
591 pseudo_classes.set(PseudoClassFlags::ACTIVE, false);
592 }
593 self.needs_restyle();
594 *self.triggered = Entity::null();
595 }
596 }
597
598 pub fn focus_prev(&mut self) {
600 let lock_focus_to = self.tree.lock_focus_within(*self.focused);
601 let prev_focused = if let Some(prev_focused) =
602 focus_backward(self.tree, self.style, *self.focused, lock_focus_to)
603 {
604 prev_focused
605 } else {
606 TreeIterator::full(self.tree)
607 .rfind(|node| is_navigatable(self.tree, self.style, *node, lock_focus_to))
608 .unwrap_or(Entity::root())
609 };
610
611 if prev_focused != *self.focused {
612 self.event_queue.push_back(
613 Event::new(WindowEvent::FocusOut).target(*self.focused).origin(Entity::root()),
614 );
615 self.event_queue.push_back(
616 Event::new(WindowEvent::FocusIn).target(prev_focused).origin(Entity::root()),
617 );
618
619 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(*self.triggered) {
620 pseudo_classes.set(PseudoClassFlags::ACTIVE, false);
621 }
622 self.needs_restyle();
623 *self.triggered = Entity::null();
624 }
625 }
626
627 pub fn hovered(&self) -> Entity {
629 *self.hovered
630 }
631
632 pub fn focused(&self) -> Entity {
634 *self.focused
635 }
636
637 pub fn is_hovered(&self) -> bool {
641 self.hovered() == self.current
642 }
643
644 pub fn is_active(&self) -> bool {
646 if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
647 pseudo_classes.contains(PseudoClassFlags::ACTIVE)
648 } else {
649 false
650 }
651 }
652
653 pub fn is_over(&self) -> bool {
655 if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
656 pseudo_classes.contains(PseudoClassFlags::OVER)
657 } else {
658 false
659 }
660 }
661
662 pub fn is_focused(&self) -> bool {
664 self.focused() == self.current
665 }
666
667 pub fn is_draggable(&self) -> bool {
669 self.style
670 .abilities
671 .get(self.current)
672 .map(|abilities| abilities.contains(Abilities::DRAGGABLE))
673 .unwrap_or_default()
674 }
675
676 pub fn is_disabled(&self) -> bool {
678 self.style.disabled.get(self.current()).cloned().unwrap_or_default()
679 }
680
681 pub fn is_checked(&self) -> bool {
683 if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
684 pseudo_classes.contains(PseudoClassFlags::CHECKED)
685 } else {
686 false
687 }
688 }
689
690 pub fn is_read_only(&self) -> bool {
692 if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
693 pseudo_classes.contains(PseudoClassFlags::READ_ONLY)
694 } else {
695 false
696 }
697 }
698
699 pub fn lock_cursor_icon(&mut self) {
703 *self.cursor_icon_locked = true;
704 }
705
706 pub fn unlock_cursor_icon(&mut self) {
708 *self.cursor_icon_locked = false;
709 let hovered = *self.hovered;
710 let cursor = self.style.cursor.get(hovered).cloned().unwrap_or_default();
711 self.emit(WindowEvent::SetCursor(cursor));
712 }
713
714 pub fn is_cursor_icon_locked(&self) -> bool {
716 *self.cursor_icon_locked
717 }
718
719 pub fn set_drop_data(&mut self, data: impl Into<DropData>) {
721 *self.drop_data = Some(data.into())
722 }
723
724 #[cfg(feature = "clipboard")]
728 pub fn get_clipboard(&mut self) -> Result<String, Box<dyn Error + Send + Sync + 'static>> {
729 self.current_window_clipboard().get_contents()
730 }
731
732 #[cfg(feature = "clipboard")]
736 pub fn set_clipboard(
737 &mut self,
738 text: String,
739 ) -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
740 self.current_window_clipboard().set_contents(text)
741 }
742
743 #[cfg(feature = "clipboard")]
744 fn current_window_clipboard(&mut self) -> &mut Box<dyn ClipboardProvider> {
745 let window = if self.tree.is_window(self.current) {
746 self.current
747 } else {
748 self.tree.get_parent_window(self.current).unwrap_or(Entity::root())
749 };
750
751 self.clipboards.entry(window).or_insert_with(super::default_clipboard_provider)
752 }
753
754 pub fn toggle_class(&mut self, class_name: &str, applied: bool) {
764 let current = self.current();
765 if let Some(class_list) = self.style.classes.get_mut(current) {
766 if applied {
767 class_list.insert(class_name.to_string());
768 } else {
769 class_list.remove(class_name);
770 }
771 } else if applied {
772 let mut class_list = HashSet::new();
773 class_list.insert(class_name.to_string());
774 self.style.classes.insert(current, class_list);
775 }
776
777 self.needs_restyle();
778 }
779
780 pub fn environment(&self) -> &Environment {
782 self.data::<Environment>()
783 }
784
785 pub fn needs_redraw(&mut self) {
787 let parent_window = self.tree.get_parent_window(self.current).unwrap_or(Entity::root());
788 if let Some(window_state) = self.windows.get_mut(&parent_window) {
789 window_state.redraw_list.insert(self.current);
790 }
791 }
792
793 pub fn needs_relayout(&mut self) {
795 self.style.needs_relayout(self.current);
796 self.needs_redraw();
797 }
798
799 pub fn needs_restyle(&mut self) {
801 if self.current == Entity::null() || self.style.restyle.contains(&self.current) {
802 return;
803 }
804
805 self.style.restyle.insert(self.current);
806 let iter = if let Some(parent) = self.tree.get_layout_parent(self.current) {
807 LayoutTreeIterator::subtree(self.tree, parent)
808 } else {
809 LayoutTreeIterator::subtree(self.tree, self.current)
810 };
811
812 for descendant in iter {
813 self.style.restyle.insert(descendant);
814 }
815 self.style.needs_restyle(self.current);
816 }
817
818 pub fn needs_retransform(&mut self) {
819 self.style.needs_retransform(self.current);
820 let iter = LayoutTreeIterator::subtree(self.tree, self.current);
821 for descendant in iter {
822 self.style.needs_retransform(descendant);
823 }
824 }
825
826 pub fn needs_reclip(&mut self) {
827 self.style.needs_reclip(self.current);
828 let iter = LayoutTreeIterator::subtree(self.tree, self.current);
829 for descendant in iter {
830 self.style.needs_reclip(descendant);
831 }
832 }
833
834 pub fn reload_styles(&mut self) -> Result<(), std::io::Error> {
836 if self.resource_manager.styles.is_empty() {
837 return Ok(());
838 }
839
840 self.style.remove_rules();
841
842 self.style.clear_style_rules();
843
844 let mut overall_theme = String::new();
845
846 for style_string in self.resource_manager.styles.iter().flat_map(|style| style.get_style())
847 {
848 overall_theme += &style_string;
849 }
850
851 self.style.parse_theme(&overall_theme);
852
853 self.style.needs_relayout(Entity::root());
854
855 for entity in self.tree.into_iter() {
856 self.style.needs_restyle(entity);
857
858 self.style.needs_text_update(entity);
860 }
861
862 Ok(())
863 }
864
865 pub fn spawn<F>(&self, target: F)
867 where
868 F: 'static + Send + FnOnce(&mut ContextProxy),
869 {
870 let mut cxp = ContextProxy {
871 current: self.current,
872 event_proxy: self.event_proxy.as_ref().map(|p| p.make_clone()),
873 };
874
875 std::thread::spawn(move || target(&mut cxp));
876 }
877
878 pub fn get_proxy(&self) -> ContextProxy {
880 ContextProxy {
881 current: self.current,
882 event_proxy: self.event_proxy.as_ref().map(|p| p.make_clone()),
883 }
884 }
885
886 #[cfg(feature = "tokio")]
910 pub fn add_task<T, E>(&self, task: TaskBuilder<T, E>) -> TaskHandle
911 where
912 T: Send + 'static,
913 E: Send + 'static,
914 {
915 task.add_to_event_context(self)
916 }
917
918 pub fn modify<V: View>(&mut self, f: impl FnOnce(&mut V)) {
919 if let Some(view) = self
920 .views
921 .get_mut(&self.current)
922 .and_then(|view_handler| view_handler.downcast_mut::<V>())
923 {
924 (f)(view);
925 }
926 }
927
928 pub fn background_color(&mut self) -> Color {
936 self.style.background_color.get(self.current).copied().unwrap_or_default()
937 }
938
939 pub fn set_id(&mut self, id: &str) {
942 self.style.ids.insert(self.current, id.to_string())
943 }
944
945 pub fn set_hover(&mut self, flag: bool) {
957 let current = self.current();
958 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
959 pseudo_classes.set(PseudoClassFlags::HOVER, flag);
960 }
961
962 self.needs_restyle();
963 }
964
965 pub fn set_active(&mut self, active: bool) {
974 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(self.current) {
975 pseudo_classes.set(PseudoClassFlags::ACTIVE, active);
976 }
977
978 self.needs_restyle();
979 }
980
981 pub fn set_read_only(&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_ONLY, flag);
985 }
986
987 self.needs_restyle();
988 }
989
990 pub fn set_read_write(&mut self, flag: bool) {
991 let current = self.current();
992 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
993 pseudo_classes.set(PseudoClassFlags::READ_WRITE, flag);
994 }
995
996 self.needs_restyle();
997 }
998
999 pub fn set_checked(&mut self, flag: bool) {
1008 let current = self.current();
1009 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
1010 pseudo_classes.set(PseudoClassFlags::CHECKED, flag);
1011 }
1012
1013 self.needs_restyle();
1014 }
1015
1016 pub fn set_valid(&mut self, flag: bool) {
1025 let current = self.current();
1026 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
1027 pseudo_classes.set(PseudoClassFlags::VALID, flag);
1028 pseudo_classes.set(PseudoClassFlags::INVALID, !flag);
1029 }
1030
1031 self.needs_restyle();
1032 }
1033
1034 pub fn set_placeholder_shown(&mut self, flag: bool) {
1035 let current = self.current();
1036 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
1037 pseudo_classes.set(PseudoClassFlags::PLACEHOLDER_SHOWN, flag);
1038 }
1039
1040 self.needs_restyle();
1041 }
1042
1043 pub fn is_valid(&self) -> bool {
1045 self.style
1046 .pseudo_classes
1047 .get(self.current)
1048 .map(|pseudo_classes| pseudo_classes.contains(PseudoClassFlags::VALID))
1049 .unwrap_or_default()
1050 }
1051
1052 pub fn is_placeholder_shown(&self) -> bool {
1053 self.style
1054 .pseudo_classes
1055 .get(self.current)
1056 .map(|pseudo_classes| pseudo_classes.contains(PseudoClassFlags::PLACEHOLDER_SHOWN))
1057 .unwrap_or_default()
1058 }
1059
1060 pub fn set_name(&mut self, name: &str) {
1064 self.style.name.insert(self.current, name.to_string());
1065 }
1066
1067 pub fn set_role(&mut self, role: Role) {
1069 self.style.role.insert(self.current, role);
1070 }
1071
1072 pub fn set_live(&mut self, live: Live) {
1079 self.style.live.insert(self.current, live);
1080 }
1081
1082 pub fn labelled_by(&mut self, id: &str) {
1084 self.style.labelled_by.insert(self.current, id.to_string());
1085 }
1086
1087 pub fn described_by(&mut self, id: &str) {
1089 self.style.described_by.insert(self.current, id.to_string());
1090 }
1091
1092 pub fn controls(&mut self, id: &str) {
1094 self.style.controls.insert(self.current, id.to_string());
1095 }
1096
1097 pub fn set_hidden(&mut self, hidden: bool) {
1099 self.style.hidden.insert(self.current, hidden)
1100 }
1101
1102 pub fn text_value(&mut self, text: &str) {
1104 self.style.text_value.insert(self.current, text.to_string());
1105 }
1106
1107 pub fn numeric_value(&mut self, value: f64) {
1109 self.style.numeric_value.insert(self.current, value);
1110 }
1111
1112 pub fn set_display(&mut self, display: Display) {
1118 self.style.display.insert(self.current, display);
1119 }
1120
1121 pub fn set_visibility(&mut self, visibility: Visibility) {
1125 self.style.visibility.insert(self.current, visibility);
1126 }
1127
1128 pub fn set_opacity(&mut self, opacity: f32) {
1132 self.style.opacity.insert(self.current, Opacity(opacity));
1133 }
1134
1135 pub fn set_z_index(&mut self, z_index: i32) {
1137 self.style.z_index.insert(self.current, z_index);
1138 }
1139
1140 pub fn set_clip_path(&mut self, clip_path: ClipPath) {
1142 self.style.clip_path.insert(self.current, clip_path);
1143 self.needs_reclip();
1144 self.needs_redraw();
1145 }
1146
1147 pub fn set_overflowx(&mut self, overflowx: impl Into<Overflow>) {
1149 self.style.overflowx.insert(self.current, overflowx.into());
1150 self.needs_reclip();
1151 self.needs_redraw();
1152 }
1153
1154 pub fn set_overflowy(&mut self, overflowy: impl Into<Overflow>) {
1156 self.style.overflowy.insert(self.current, overflowy.into());
1157 self.needs_reclip();
1158 self.needs_redraw();
1159 }
1160
1161 pub fn set_transform(&mut self, transform: impl Into<Vec<Transform>>) {
1165 self.style.transform.insert(self.current, transform.into());
1166 self.needs_retransform();
1167 self.needs_redraw();
1168 }
1169
1170 pub fn set_transform_origin(&mut self, transform_origin: Translate) {
1172 self.style.transform_origin.insert(self.current, transform_origin);
1173 self.needs_retransform();
1174 self.needs_redraw();
1175 }
1176
1177 pub fn set_translate(&mut self, translate: impl Into<Translate>) {
1179 self.style.translate.insert(self.current, translate.into());
1180 self.needs_retransform();
1181 self.needs_redraw();
1182 }
1183
1184 pub fn set_rotate(&mut self, angle: impl Into<Angle>) {
1186 self.style.rotate.insert(self.current, angle.into());
1187 self.needs_retransform();
1188 self.needs_redraw();
1189 }
1190
1191 pub fn set_scale(&mut self, scale: impl Into<Scale>) {
1193 self.style.scale.insert(self.current, scale.into());
1194 self.needs_retransform();
1195 self.needs_redraw();
1196 }
1197
1198 pub fn set_filter(&mut self, filter: Filter) {
1202 self.style.filter.insert(self.current, filter);
1203 self.needs_redraw();
1204 }
1205
1206 pub fn set_backdrop_filter(&mut self, filter: Filter) {
1208 self.style.backdrop_filter.insert(self.current, filter);
1209 self.needs_redraw();
1210 }
1211
1212 pub fn set_background_color(&mut self, background_color: Color) {
1219 self.style.background_color.insert(self.current, background_color);
1220 self.needs_redraw();
1221 }
1222
1223 pub fn set_width(&mut self, width: Units) {
1226 self.style.width.insert(self.current, width);
1227 self.needs_relayout();
1228 self.needs_redraw();
1229 }
1230
1231 pub fn set_height(&mut self, height: Units) {
1232 self.style.height.insert(self.current, height);
1233 self.needs_relayout();
1234 self.needs_redraw();
1235 }
1236
1237 pub fn set_max_height(&mut self, height: Units) {
1238 self.style.max_height.insert(self.current, height);
1239 self.needs_relayout();
1240 self.needs_redraw();
1241 }
1242
1243 pub fn set_left(&mut self, left: Units) {
1246 self.style.left.insert(self.current, left);
1247 self.needs_relayout();
1248 self.needs_redraw();
1249 }
1250
1251 pub fn set_top(&mut self, top: Units) {
1252 self.style.top.insert(self.current, top);
1253 self.needs_relayout();
1254 self.needs_redraw();
1255 }
1256
1257 pub fn set_right(&mut self, right: Units) {
1258 self.style.right.insert(self.current, right);
1259 self.needs_relayout();
1260 self.needs_redraw();
1261 }
1262
1263 pub fn set_bottom(&mut self, bottom: Units) {
1264 self.style.bottom.insert(self.current, bottom);
1265 self.needs_relayout();
1266 self.needs_redraw();
1267 }
1268
1269 pub fn set_padding_left(&mut self, padding_left: Units) {
1272 self.style.padding_left.insert(self.current, padding_left);
1273 self.needs_relayout();
1274 self.needs_redraw();
1275 }
1276
1277 pub fn set_padding_top(&mut self, padding_top: Units) {
1278 self.style.padding_top.insert(self.current, padding_top);
1279 self.needs_relayout();
1280 self.needs_redraw();
1281 }
1282
1283 pub fn set_padding_right(&mut self, padding_right: Units) {
1284 self.style.padding_right.insert(self.current, padding_right);
1285 self.needs_relayout();
1286 self.needs_redraw();
1287 }
1288
1289 pub fn set_padding_bottom(&mut self, padding_bottom: Units) {
1290 self.style.padding_bottom.insert(self.current, padding_bottom);
1291 self.needs_relayout();
1292 self.needs_redraw();
1293 }
1294
1295 pub fn set_text(&mut self, text: &str) {
1299 self.style.text.insert(self.current, text.to_owned());
1300 self.style.needs_text_update(self.current);
1301 self.needs_relayout();
1302 self.needs_redraw();
1303 }
1304
1305 pub fn set_pointer_events(&mut self, pointer_events: impl Into<PointerEvents>) {
1306 self.style.pointer_events.insert(self.current, pointer_events.into());
1307 }
1308
1309 pub fn border_top_width(&self) -> f32 {
1313 if let Some(length) = self.style.border_top_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 pub fn border_right_width(&self) -> f32 {
1322 if let Some(length) = self.style.border_right_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 pub fn border_bottom_width(&self) -> f32 {
1331 if let Some(length) = self.style.border_bottom_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 pub fn border_left_width(&self) -> f32 {
1340 if let Some(length) = self.style.border_left_width.get(self.current) {
1341 let bounds = self.bounds();
1342 return length.to_pixels(bounds.w.min(bounds.h), self.scale_factor()).round();
1343 }
1344 0.0
1345 }
1346
1347 pub fn border_width(&self) -> f32 {
1350 self.border_top_width()
1351 }
1352
1353 pub fn font_size(&self) -> f32 {
1355 self.logical_to_physical(
1356 self.style
1357 .font_size
1358 .get(self.current)
1359 .cloned()
1360 .map(|f| f.0.to_px().unwrap())
1361 .unwrap_or(16.0),
1362 )
1363 }
1364
1365 pub fn add_timer(
1396 &mut self,
1397 interval: Duration,
1398 duration: Option<Duration>,
1399 callback: impl Fn(&mut EventContext, TimerAction) + 'static,
1400 ) -> Timer {
1401 let id = Timer(self.timers.len());
1402 self.timers.push(TimerState {
1403 entity: Entity::root(),
1404 id,
1405 time: Instant::now(),
1406 interval,
1407 duration,
1408 start_time: Instant::now(),
1409 callback: Rc::new(callback),
1410 ticking: false,
1411 stopping: false,
1412 });
1413
1414 id
1415 }
1416
1417 pub fn start_timer(&mut self, timer: Timer) {
1421 let current = self.current;
1422 if !self.timer_is_running(timer) {
1423 let timer_state = self.timers[timer.0].clone();
1424 self.running_timers.push(timer_state);
1426 }
1427
1428 self.modify_timer(timer, |timer_state| {
1429 let now = Instant::now();
1430 timer_state.start_time = now;
1431 timer_state.time = now;
1432 timer_state.entity = current;
1433 timer_state.ticking = false;
1434 timer_state.stopping = false;
1435 });
1436 }
1437
1438 pub fn modify_timer(&mut self, timer: Timer, timer_function: impl Fn(&mut TimerState)) {
1440 let mut running_timers = self.running_timers.clone().into_vec();
1441
1442 if let Some(timer_state) =
1443 running_timers.iter_mut().find(|timer_state| timer_state.id == timer)
1444 {
1445 (timer_function)(timer_state);
1446 *self.running_timers = running_timers.into();
1447 return;
1448 }
1449
1450 for pending_timer in self.timers.iter_mut() {
1451 if pending_timer.id == timer {
1452 (timer_function)(pending_timer);
1453 }
1454 }
1455 }
1456
1457 pub fn query_timer<T>(
1458 &mut self,
1459 timer: Timer,
1460 timer_function: impl Fn(&TimerState) -> T,
1461 ) -> Option<T> {
1462 if let Some(timer_state) =
1463 self.running_timers.iter().find(|timer_state| timer_state.id == timer)
1464 {
1465 return Some(timer_function(timer_state));
1466 }
1467
1468 for pending_timer in self.timers.iter() {
1469 if pending_timer.id == timer {
1470 return Some(timer_function(pending_timer));
1471 }
1472 }
1473
1474 None
1475 }
1476
1477 pub fn timer_is_running(&mut self, timer: Timer) -> bool {
1479 for timer_state in self.running_timers.iter() {
1480 if timer_state.id == timer {
1481 return true;
1482 }
1483 }
1484
1485 false
1486 }
1487
1488 pub fn stop_timer(&mut self, timer: Timer) {
1492 let mut running_timers = self.running_timers.clone();
1493
1494 for timer_state in running_timers.iter() {
1495 if timer_state.id == timer {
1496 self.with_current(timer_state.entity, |cx| {
1497 (timer_state.callback)(cx, TimerAction::Stop);
1498 });
1499 }
1500 }
1501
1502 *self.running_timers =
1503 running_timers.drain().filter(|timer_state| timer_state.id != timer).collect();
1504 }
1505}
1506
1507impl DataContext for EventContext<'_> {
1508 fn try_data<T: 'static>(&self) -> Option<&T> {
1509 if let Some(t) = <dyn Any>::downcast_ref::<T>(&()) {
1511 return Some(t);
1512 }
1513
1514 for entity in self.current.parent_iter(self.tree) {
1515 if let Some(models) = self.models.get(&entity) {
1517 if let Some(model) = models.get(&TypeId::of::<T>()) {
1518 return model.downcast_ref::<T>();
1519 }
1520 }
1521
1522 if let Some(view_handler) = self.views.get(&entity) {
1524 if let Some(data) = view_handler.downcast_ref::<T>() {
1525 return Some(data);
1526 }
1527 }
1528 }
1529
1530 None
1531 }
1532
1533 fn localization_context(&self) -> Option<LocalizationContext<'_>> {
1534 Some(LocalizationContext::from_event_context(self))
1535 }
1536}
1537
1538impl EmitContext for EventContext<'_> {
1539 fn emit<M: Any>(&mut self, message: M) {
1540 self.event_queue.push_back(
1541 Event::new(message)
1542 .target(self.current)
1543 .origin(self.current)
1544 .propagate(Propagation::Up),
1545 );
1546 }
1547
1548 fn emit_to<M: Any>(&mut self, target: Entity, message: M) {
1549 self.event_queue.push_back(
1550 Event::new(message).target(target).origin(self.current).propagate(Propagation::Direct),
1551 );
1552 }
1553
1554 fn emit_custom(&mut self, event: Event) {
1555 self.event_queue.push_back(event);
1556 }
1557
1558 fn schedule_emit<M: Any>(&mut self, message: M, at: Instant) -> TimedEventHandle {
1559 self.schedule_emit_custom(
1560 Event::new(message)
1561 .target(self.current)
1562 .origin(self.current)
1563 .propagate(Propagation::Up),
1564 at,
1565 )
1566 }
1567 fn schedule_emit_to<M: Any>(
1568 &mut self,
1569 target: Entity,
1570 message: M,
1571 at: Instant,
1572 ) -> TimedEventHandle {
1573 self.schedule_emit_custom(
1574 Event::new(message).target(target).origin(self.current).propagate(Propagation::Direct),
1575 at,
1576 )
1577 }
1578 fn schedule_emit_custom(&mut self, event: Event, at: Instant) -> TimedEventHandle {
1579 let handle = TimedEventHandle(*self.next_event_id);
1580 self.event_schedule.push(TimedEvent { event, time: at, ident: handle });
1581 *self.next_event_id += 1;
1582 handle
1583 }
1584 fn cancel_scheduled(&mut self, handle: TimedEventHandle) {
1585 *self.event_schedule =
1586 self.event_schedule.drain().filter(|item| item.ident != handle).collect();
1587 }
1588}
1589
1590pub trait TreeProps {
1592 fn parent(&self) -> Entity;
1594 fn first_child(&self) -> Entity;
1596 fn parent_window(&self) -> Entity;
1598}
1599
1600impl TreeProps for EventContext<'_> {
1601 fn parent(&self) -> Entity {
1602 self.tree.get_layout_parent(self.current).unwrap()
1603 }
1604
1605 fn first_child(&self) -> Entity {
1606 self.tree.get_layout_first_child(self.current).unwrap()
1607 }
1608
1609 fn parent_window(&self) -> Entity {
1610 self.tree.get_parent_window(self.current).unwrap_or(Entity::root())
1611 }
1612}