1use std::any::{Any, TypeId};
2use std::collections::{BinaryHeap, VecDeque};
3#[cfg(feature = "clipboard")]
4use std::error::Error;
5use std::rc::Rc;
6
7use hashbrown::hash_map::Entry;
8use hashbrown::{HashMap, HashSet};
9use vizia_storage::{LayoutTreeIterator, TreeIterator};
10
11use crate::animation::AnimId;
12use crate::cache::CachedData;
13use crate::events::{TimedEvent, TimedEventHandle, TimerState, ViewHandler};
14use crate::prelude::*;
15use crate::resource::{ImageOrSvg, ResourceManager, StoredImage};
16use crate::tree::{focus_backward, focus_forward, is_navigatable};
17use vizia_input::MouseState;
18
19use skia_safe::Matrix;
20
21use crate::text::TextContext;
22#[cfg(feature = "clipboard")]
23use copypasta::ClipboardProvider;
24
25use super::{LocalizationContext, ModelData};
26
27type Views = HashMap<Entity, Box<dyn ViewHandler>>;
28type Models = HashMap<Entity, HashMap<TypeId, Box<dyn ModelData>>>;
29
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 clipboard: &'a mut Box<dyn ClipboardProvider>,
92 pub(crate) event_proxy: &'a mut Option<Box<dyn crate::context::EventProxy>>,
93 pub(crate) drop_data: &'a mut Option<DropData>,
94 pub(crate) active_drag_view: &'a mut Option<Entity>,
95 pub windows: &'a mut HashMap<Entity, WindowState>,
96}
97
98macro_rules! get_length_property {
99 (
100 $(#[$meta:meta])*
101 $name:ident
102 ) => {
103 $(#[$meta])*
104 pub fn $name(&self) -> f32 {
105 if let Some(length) = self.style.$name.get(self.current) {
106 let bounds = self.bounds();
107
108 let px = length.to_pixels(bounds.w.min(bounds.h), self.scale_factor());
109 return px.round();
110 }
111
112 0.0
113 }
114 };
115}
116
117impl<'a> EventContext<'a> {
118 pub fn new(cx: &'a mut Context) -> Self {
120 Self {
121 current: cx.current,
122 captured: &mut cx.captured,
123 focused: &mut cx.focused,
124 hovered: &cx.hovered,
125 triggered: &mut cx.triggered,
126 entity_identifiers: &cx.entity_identifiers,
127 style: &mut cx.style,
128 cache: &mut cx.cache,
129 tree: &cx.tree,
130 models: &mut cx.models,
131 views: &mut cx.views,
132 listeners: &mut cx.listeners,
133 resource_manager: &mut cx.resource_manager,
134 text_context: &mut cx.text_context,
135 #[cfg(feature = "tokio")]
136 task_runtime: &cx.task_runtime,
137 #[cfg(feature = "tokio")]
138 named_tasks: &cx.named_tasks,
139 modifiers: &cx.modifiers,
140 mouse: &cx.mouse,
141 event_queue: &mut cx.event_queue,
142 event_schedule: &mut cx.event_schedule,
143 next_event_id: &mut cx.next_event_id,
144 timers: &mut cx.timers,
145 running_timers: &mut cx.running_timers,
146 cursor_icon_locked: &mut cx.cursor_icon_locked,
147 #[cfg(feature = "clipboard")]
148 clipboard: &mut cx.clipboard,
149 event_proxy: &mut cx.event_proxy,
150 drop_data: &mut cx.drop_data,
151 active_drag_view: &mut cx.active_drag_view,
152 windows: &mut cx.windows,
153 }
154 }
155
156 pub fn new_with_current(cx: &'a mut Context, current: Entity) -> Self {
158 Self {
159 current,
160 captured: &mut cx.captured,
161 focused: &mut cx.focused,
162 hovered: &cx.hovered,
163 triggered: &mut cx.triggered,
164 entity_identifiers: &cx.entity_identifiers,
165 style: &mut cx.style,
166 cache: &mut cx.cache,
167 tree: &cx.tree,
168 models: &mut cx.models,
169 views: &mut cx.views,
170 listeners: &mut cx.listeners,
171 resource_manager: &mut cx.resource_manager,
172 text_context: &mut cx.text_context,
173 #[cfg(feature = "tokio")]
174 task_runtime: &cx.task_runtime,
175 #[cfg(feature = "tokio")]
176 named_tasks: &cx.named_tasks,
177 modifiers: &cx.modifiers,
178 mouse: &cx.mouse,
179 event_queue: &mut cx.event_queue,
180 event_schedule: &mut cx.event_schedule,
181 next_event_id: &mut cx.next_event_id,
182 timers: &mut cx.timers,
183 running_timers: &mut cx.running_timers,
184 cursor_icon_locked: &mut cx.cursor_icon_locked,
185 #[cfg(feature = "clipboard")]
186 clipboard: &mut cx.clipboard,
187 event_proxy: &mut cx.event_proxy,
188 drop_data: &mut cx.drop_data,
189 active_drag_view: &mut cx.active_drag_view,
190 windows: &mut cx.windows,
191 }
192 }
193
194 pub fn get_view<V: View>(&self) -> Option<&V> {
196 self.views.get(&self.current).and_then(|view| view.downcast_ref::<V>())
197 }
198
199 pub fn get_view_with<V: View>(&self, entity: Entity) -> Option<&V> {
201 self.views.get(&entity).and_then(|view| view.downcast_ref::<V>())
202 }
203
204 pub fn close_window(&mut self) {
205 if let Some(state) = self.windows.get_mut(&self.current) {
206 state.should_close = true;
207 }
208 }
209
210 pub fn resolve_entity_identifier(&self, id: &str) -> Option<Entity> {
212 self.entity_identifiers.get(id).cloned()
213 }
214
215 pub fn get_entity_by_element_id(&self, element: &str) -> Option<Entity> {
217 let descendants = LayoutTreeIterator::subtree(self.tree, self.current);
218 for descendant in descendants {
219 if let Some(id) = self.views.get(&descendant).and_then(|view| view.element()) {
220 if id == element {
221 return Some(descendant);
222 }
223 }
224 }
225
226 None
227 }
228
229 pub fn get_entities_by_class(&self, class: &str) -> Vec<Entity> {
231 let mut entities = Vec::new();
232 let descendants = LayoutTreeIterator::subtree(self.tree, self.current);
233 for descendant in descendants {
234 if let Some(class_list) = self.style.classes.get(descendant) {
235 if class_list.contains(class) {
236 entities.push(descendant);
237 }
238 }
239 }
240
241 entities
242 }
243
244 pub fn current(&self) -> Entity {
246 self.current
247 }
248
249 pub fn modifiers(&self) -> &Modifiers {
251 self.modifiers
252 }
253
254 pub fn mouse(&self) -> &MouseState<Entity> {
256 self.mouse
257 }
258
259 pub fn nth_child(&self, n: usize) -> Option<Entity> {
260 self.tree.get_child(self.current, n)
261 }
262
263 pub fn last_child(&self) -> Option<Entity> {
264 self.tree.get_last_child(self.current).copied()
265 }
266
267 pub fn with_current<T>(&mut self, entity: Entity, f: impl FnOnce(&mut Self) -> T) -> T {
268 let prev = self.current();
269 self.current = entity;
270 let ret = (f)(self);
271 self.current = prev;
272 ret
273 }
274
275 pub fn has_drop_data(&self) -> bool {
277 self.drop_data.is_some()
278 }
279
280 pub fn drop_data(&self) -> Option<&DropData> {
282 self.drop_data.as_ref()
283 }
284
285 pub fn active_drag_view(&self) -> Option<Entity> {
287 *self.active_drag_view
288 }
289
290 pub fn set_active_drag_view(&mut self, drag_view: Option<Entity>) {
292 *self.active_drag_view = drag_view;
293 }
294
295 pub fn bounds(&self) -> BoundingBox {
297 self.cache.get_bounds(self.current)
298 }
299
300 pub fn scale_factor(&self) -> f32 {
306 self.style.dpi_factor as f32
307 }
308
309 pub fn logical_to_physical(&self, logical: f32) -> f32 {
311 self.style.logical_to_physical(logical)
312 }
313
314 pub fn physical_to_logical(&self, physical: f32) -> f32 {
316 self.style.physical_to_logical(physical)
317 }
318
319 pub fn clip_region(&self) -> BoundingBox {
321 let current_window = if self.tree.is_window(self.current) {
322 self.current
323 } else {
324 self.tree.get_parent_window(self.current).unwrap_or(Entity::root())
325 };
326
327 let window_bounds = self.cache.get_bounds(current_window);
328
329 if let Some(clip_path) = self.cache.clip_path.get(self.current) {
331 return clip_path
332 .clone()
333 .map(|clip_path| Into::<BoundingBox>::into(*clip_path.bounds()))
334 .unwrap_or(window_bounds);
335 }
336
337 if self.style.ignore_clipping.get(self.current).copied().unwrap_or(false) {
338 return window_bounds;
339 }
340
341 let mut current = self.current;
342 while let Some(parent) = self.tree.get_parent(current) {
343 if let Some(clip_path) = self.cache.clip_path.get(parent) {
345 return clip_path
346 .clone()
347 .map(|clip_path| Into::<BoundingBox>::into(*clip_path.bounds()))
348 .unwrap_or(window_bounds);
349 }
350
351 if self.style.ignore_clipping.get(parent).copied().unwrap_or(false) {
352 return window_bounds;
353 }
354
355 if parent == current_window {
356 break;
357 }
358
359 current = parent;
360 }
361
362 window_bounds
363 }
364
365 pub fn transform(&self) -> Matrix {
367 self.cache.transform.get(self.current).copied().unwrap_or_default()
368 }
369
370 pub fn play_animation(&mut self, anim_id: impl AnimId, duration: Duration, delay: Duration) {
372 if let Some(animation_id) = anim_id.get(self) {
373 self.style.enqueue_animation(self.current, animation_id, duration, delay);
374 }
375 }
376
377 pub fn play_animation_for(
379 &mut self,
380 anim_id: impl AnimId,
381 target: &str,
382 duration: Duration,
383 delay: Duration,
384 ) {
385 if let Some(target_entity) = self.resolve_entity_identifier(target) {
386 if let Some(animation_id) = anim_id.get(self) {
387 self.style.enqueue_animation(target_entity, animation_id, duration, delay)
388 }
389 }
390 }
391
392 pub fn is_animating(&self, anim_id: impl AnimId) -> bool {
394 if let Some(animation_id) = anim_id.get(self) {
395 return self.style.is_animating(self.current, animation_id);
396 }
397
398 false
399 }
400
401 pub fn add_listener<F, W>(&mut self, listener: F)
407 where
408 W: View,
409 F: 'static + Fn(&mut W, &mut EventContext, &mut Event),
410 {
411 self.listeners.insert(
412 self.current,
413 Box::new(move |event_handler, context, event| {
414 if let Some(widget) = event_handler.downcast_mut::<W>() {
415 (listener)(widget, context, event);
416 }
417 }),
418 );
419 }
420
421 pub fn set_language(&mut self, lang: LanguageIdentifier) {
423 if let Some(mut models) = self.models.remove(&Entity::root()) {
424 if let Some(model) = models.get_mut(&TypeId::of::<Environment>()) {
425 model.event(self, &mut Event::new(EnvironmentEvent::SetLocale(lang)));
426 }
427
428 self.models.insert(Entity::root(), models);
429 }
430 }
431
432 pub fn add_image_encoded(&mut self, path: &str, data: &[u8], policy: ImageRetentionPolicy) {
433 let id = if let Some(image_id) = self.resource_manager.image_ids.get(path) {
434 *image_id
435 } else {
436 let id = self.resource_manager.image_id_manager.create();
437 self.resource_manager.image_ids.insert(path.to_owned(), id);
438 id
439 };
440
441 if let Some(image) = skia_safe::Image::from_encoded(skia_safe::Data::new_copy(data)) {
442 match self.resource_manager.images.entry(id) {
443 Entry::Occupied(mut occ) => {
444 occ.get_mut().image = ImageOrSvg::Image(image);
445 occ.get_mut().dirty = true;
446 occ.get_mut().retention_policy = policy;
447 }
448 Entry::Vacant(vac) => {
449 vac.insert(StoredImage {
450 image: ImageOrSvg::Image(image),
451 retention_policy: policy,
452 used: true,
453 dirty: false,
454 observers: HashSet::new(),
455 });
456 }
457 }
458 self.style.needs_relayout();
459 }
460 }
461
462 pub fn capture(&mut self) {
464 *self.captured = self.current;
465 }
466
467 pub fn release(&mut self) {
469 if self.current == *self.captured {
470 *self.captured = Entity::null();
471 }
472 }
473
474 fn set_focus_pseudo_classes(&mut self, focused: Entity, enabled: bool, focus_visible: bool) {
476 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(focused) {
477 pseudo_classes.set(PseudoClassFlags::FOCUS, enabled);
478 if !enabled || focus_visible {
479 pseudo_classes.set(PseudoClassFlags::FOCUS_VISIBLE, enabled);
480 }
481 }
482
483 for ancestor in focused.parent_iter(self.tree) {
484 let entity = ancestor;
485 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(entity) {
486 pseudo_classes.set(PseudoClassFlags::FOCUS_WITHIN, enabled);
487 }
488 self.style.needs_restyle(entity);
489 }
490 }
491
492 pub fn focus_with_visibility(&mut self, focus_visible: bool) {
494 let focusable = self.current == Entity::root()
495 || self
496 .style
497 .abilities
498 .get(self.current)
499 .is_some_and(|abilities| abilities.contains(Abilities::FOCUSABLE));
500 if !focusable {
501 return;
502 }
503
504 let old_focus = self.focused();
505 let new_focus = self.current();
506 self.set_focus_pseudo_classes(old_focus, false, focus_visible);
507 if self.current() != self.focused() {
508 self.emit_to(old_focus, WindowEvent::FocusOut);
509 self.emit_to(new_focus, WindowEvent::FocusIn);
510 *self.focused = self.current();
511 }
512 self.set_focus_pseudo_classes(new_focus, true, focus_visible);
513
514 self.emit_custom(Event::new(WindowEvent::FocusVisibility(focus_visible)).target(old_focus));
515 self.emit_custom(Event::new(WindowEvent::FocusVisibility(focus_visible)).target(new_focus));
516
517 self.needs_restyle();
518 }
519
520 pub fn focus(&mut self) {
524 let focused = self.focused();
525 let old_focus_visible = self
526 .style
527 .pseudo_classes
528 .get_mut(focused)
529 .filter(|class| class.contains(PseudoClassFlags::FOCUS_VISIBLE))
530 .is_some();
531 self.focus_with_visibility(old_focus_visible)
532 }
533
534 pub fn focus_next(&mut self) {
536 let lock_focus_to = self.tree.lock_focus_within(*self.focused);
537 let next_focused = if let Some(next_focused) =
538 focus_forward(self.tree, self.style, *self.focused, lock_focus_to)
539 {
540 next_focused
541 } else {
542 TreeIterator::full(self.tree)
543 .find(|node| is_navigatable(self.tree, self.style, *node, lock_focus_to))
544 .unwrap_or(Entity::root())
545 };
546
547 if next_focused != *self.focused {
548 self.event_queue.push_back(
549 Event::new(WindowEvent::FocusOut).target(*self.focused).origin(Entity::root()),
550 );
551 self.event_queue.push_back(
552 Event::new(WindowEvent::FocusIn).target(next_focused).origin(Entity::root()),
553 );
554
555 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(*self.triggered) {
556 pseudo_classes.set(PseudoClassFlags::ACTIVE, false);
557 }
558 self.needs_restyle();
559 *self.triggered = Entity::null();
560 }
561 }
562
563 pub fn focus_prev(&mut self) {
565 let lock_focus_to = self.tree.lock_focus_within(*self.focused);
566 let prev_focused = if let Some(prev_focused) =
567 focus_backward(self.tree, self.style, *self.focused, lock_focus_to)
568 {
569 prev_focused
570 } else {
571 TreeIterator::full(self.tree)
572 .rfind(|node| is_navigatable(self.tree, self.style, *node, lock_focus_to))
573 .unwrap_or(Entity::root())
574 };
575
576 if prev_focused != *self.focused {
577 self.event_queue.push_back(
578 Event::new(WindowEvent::FocusOut).target(*self.focused).origin(Entity::root()),
579 );
580 self.event_queue.push_back(
581 Event::new(WindowEvent::FocusIn).target(prev_focused).origin(Entity::root()),
582 );
583
584 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(*self.triggered) {
585 pseudo_classes.set(PseudoClassFlags::ACTIVE, false);
586 }
587 self.needs_restyle();
588 *self.triggered = Entity::null();
589 }
590 }
591
592 pub fn hovered(&self) -> Entity {
594 *self.hovered
595 }
596
597 pub fn focused(&self) -> Entity {
599 *self.focused
600 }
601
602 pub fn is_hovered(&self) -> bool {
606 self.hovered() == self.current
607 }
608
609 pub fn is_active(&self) -> bool {
611 if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
612 pseudo_classes.contains(PseudoClassFlags::ACTIVE)
613 } else {
614 false
615 }
616 }
617
618 pub fn is_over(&self) -> bool {
620 if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
621 pseudo_classes.contains(PseudoClassFlags::OVER)
622 } else {
623 false
624 }
625 }
626
627 pub fn is_focused(&self) -> bool {
629 self.focused() == self.current
630 }
631
632 pub fn is_draggable(&self) -> bool {
634 self.style
635 .abilities
636 .get(self.current)
637 .map(|abilities| abilities.contains(Abilities::DRAGGABLE))
638 .unwrap_or_default()
639 }
640
641 pub fn is_disabled(&self) -> bool {
643 self.style.disabled.get(self.current()).cloned().unwrap_or_default()
644 }
645
646 pub fn is_checked(&self) -> bool {
648 if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
649 pseudo_classes.contains(PseudoClassFlags::CHECKED)
650 } else {
651 false
652 }
653 }
654
655 pub fn is_read_only(&self) -> bool {
657 if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
658 pseudo_classes.contains(PseudoClassFlags::READ_ONLY)
659 } else {
660 false
661 }
662 }
663
664 pub fn lock_cursor_icon(&mut self) {
668 *self.cursor_icon_locked = true;
669 }
670
671 pub fn unlock_cursor_icon(&mut self) {
673 *self.cursor_icon_locked = false;
674 let hovered = *self.hovered;
675 let cursor = self.style.cursor.get(hovered).cloned().unwrap_or_default();
676 self.emit(WindowEvent::SetCursor(cursor));
677 }
678
679 pub fn is_cursor_icon_locked(&self) -> bool {
681 *self.cursor_icon_locked
682 }
683
684 pub fn set_drop_data(&mut self, data: impl Into<DropData>) {
686 *self.drop_data = Some(data.into())
687 }
688
689 #[cfg(feature = "clipboard")]
693 pub fn get_clipboard(&mut self) -> Result<String, Box<dyn Error + Send + Sync + 'static>> {
694 self.clipboard.get_contents()
695 }
696
697 #[cfg(feature = "clipboard")]
701 pub fn set_clipboard(
702 &mut self,
703 text: String,
704 ) -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
705 self.clipboard.set_contents(text)
706 }
707
708 pub fn toggle_class(&mut self, class_name: &str, applied: bool) {
718 let current = self.current();
719 if let Some(class_list) = self.style.classes.get_mut(current) {
720 if applied {
721 class_list.insert(class_name.to_string());
722 } else {
723 class_list.remove(class_name);
724 }
725 } else if applied {
726 let mut class_list = HashSet::new();
727 class_list.insert(class_name.to_string());
728 self.style.classes.insert(current, class_list);
729 }
730
731 self.needs_restyle();
732 }
733
734 pub fn environment(&self) -> &Environment {
736 self.data::<Environment>()
737 }
738
739 pub fn needs_redraw(&mut self) {
741 let parent_window = self.tree.get_parent_window(self.current).unwrap_or(Entity::root());
742 if let Some(window_state) = self.windows.get_mut(&parent_window) {
743 window_state.redraw_list.insert(self.current);
744 }
745 }
746
747 pub fn needs_relayout(&mut self) {
749 self.style.needs_relayout();
750 self.needs_redraw();
751 }
752
753 pub fn needs_restyle(&mut self) {
755 if self.current == Entity::null() || self.style.restyle.contains(&self.current) {
756 return;
757 }
758
759 self.style.restyle.insert(self.current);
760 let iter = if let Some(parent) = self.tree.get_layout_parent(self.current) {
761 LayoutTreeIterator::subtree(self.tree, parent)
762 } else {
763 LayoutTreeIterator::subtree(self.tree, self.current)
764 };
765
766 for descendant in iter {
767 self.style.restyle.insert(descendant);
768 }
769 self.style.needs_restyle(self.current);
770 }
771
772 pub fn needs_retransform(&mut self) {
773 self.style.needs_retransform(self.current);
774 let iter = LayoutTreeIterator::subtree(self.tree, self.current);
775 for descendant in iter {
776 self.style.needs_retransform(descendant);
777 }
778 }
779
780 pub fn needs_reclip(&mut self) {
781 self.style.needs_reclip(self.current);
782 let iter = LayoutTreeIterator::subtree(self.tree, self.current);
783 for descendant in iter {
784 self.style.needs_reclip(descendant);
785 }
786 }
787
788 pub fn reload_styles(&mut self) -> Result<(), std::io::Error> {
790 if self.resource_manager.styles.is_empty() {
791 return Ok(());
792 }
793
794 self.style.remove_rules();
795
796 self.style.clear_style_rules();
797
798 let mut overall_theme = String::new();
799
800 for style_string in self.resource_manager.styles.iter().flat_map(|style| style.get_style())
801 {
802 overall_theme += &style_string;
803 }
804
805 self.style.parse_theme(&overall_theme);
806
807 for entity in self.tree.into_iter() {
808 self.style.needs_restyle(entity);
809 self.style.needs_relayout();
810 self.style.needs_text_update(entity);
812 }
813
814 Ok(())
815 }
816
817 pub fn spawn<F>(&self, target: F)
819 where
820 F: 'static + Send + FnOnce(&mut ContextProxy),
821 {
822 let mut cxp = ContextProxy {
823 current: self.current,
824 event_proxy: self.event_proxy.as_ref().map(|p| p.make_clone()),
825 };
826
827 std::thread::spawn(move || target(&mut cxp));
828 }
829
830 pub fn get_proxy(&self) -> ContextProxy {
832 ContextProxy {
833 current: self.current,
834 event_proxy: self.event_proxy.as_ref().map(|p| p.make_clone()),
835 }
836 }
837
838 #[cfg(feature = "tokio")]
862 pub fn add_task<T, E>(&self, task: TaskBuilder<T, E>) -> TaskHandle
863 where
864 T: Send + 'static,
865 E: Send + 'static,
866 {
867 task.add_to_event_context(self)
868 }
869
870 pub fn modify<V: View>(&mut self, f: impl FnOnce(&mut V)) {
871 if let Some(view) = self
872 .views
873 .get_mut(&self.current)
874 .and_then(|view_handler| view_handler.downcast_mut::<V>())
875 {
876 (f)(view);
877 }
878 }
879
880 pub fn background_color(&mut self) -> Color {
888 self.style.background_color.get(self.current).copied().unwrap_or_default()
889 }
890
891 pub fn set_id(&mut self, id: &str) {
894 self.style.ids.insert(self.current, id.to_string())
895 }
896
897 pub fn set_hover(&mut self, flag: bool) {
909 let current = self.current();
910 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
911 pseudo_classes.set(PseudoClassFlags::HOVER, flag);
912 }
913
914 self.needs_restyle();
915 }
916
917 pub fn set_active(&mut self, active: bool) {
926 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(self.current) {
927 pseudo_classes.set(PseudoClassFlags::ACTIVE, active);
928 }
929
930 self.needs_restyle();
931 }
932
933 pub fn set_read_only(&mut self, flag: bool) {
934 let current = self.current();
935 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
936 pseudo_classes.set(PseudoClassFlags::READ_ONLY, flag);
937 }
938
939 self.needs_restyle();
940 }
941
942 pub fn set_read_write(&mut self, flag: bool) {
943 let current = self.current();
944 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
945 pseudo_classes.set(PseudoClassFlags::READ_WRITE, flag);
946 }
947
948 self.needs_restyle();
949 }
950
951 pub fn set_checked(&mut self, flag: bool) {
960 let current = self.current();
961 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
962 pseudo_classes.set(PseudoClassFlags::CHECKED, flag);
963 }
964
965 self.needs_restyle();
966 }
967
968 pub fn set_valid(&mut self, flag: bool) {
977 let current = self.current();
978 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
979 pseudo_classes.set(PseudoClassFlags::VALID, flag);
980 pseudo_classes.set(PseudoClassFlags::INVALID, !flag);
981 }
982
983 self.needs_restyle();
984 }
985
986 pub fn set_placeholder_shown(&mut self, flag: bool) {
987 let current = self.current();
988 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
989 pseudo_classes.set(PseudoClassFlags::PLACEHOLDER_SHOWN, flag);
990 }
991
992 self.needs_restyle();
993 }
994
995 pub fn is_valid(&self) -> bool {
997 self.style
998 .pseudo_classes
999 .get(self.current)
1000 .map(|pseudo_classes| pseudo_classes.contains(PseudoClassFlags::VALID))
1001 .unwrap_or_default()
1002 }
1003
1004 pub fn is_placeholder_shown(&self) -> bool {
1005 self.style
1006 .pseudo_classes
1007 .get(self.current)
1008 .map(|pseudo_classes| pseudo_classes.contains(PseudoClassFlags::PLACEHOLDER_SHOWN))
1009 .unwrap_or_default()
1010 }
1011
1012 pub fn set_name(&mut self, name: &str) {
1016 self.style.name.insert(self.current, name.to_string());
1017 }
1018
1019 pub fn set_role(&mut self, role: Role) {
1021 self.style.role.insert(self.current, role);
1022 }
1023
1024 pub fn set_live(&mut self, live: Live) {
1031 self.style.live.insert(self.current, live);
1032 }
1033
1034 pub fn labelled_by(&mut self, id: &str) {
1036 self.style.labelled_by.insert(self.current, id.to_string());
1037 }
1038
1039 pub fn described_by(&mut self, id: &str) {
1041 self.style.described_by.insert(self.current, id.to_string());
1042 }
1043
1044 pub fn controls(&mut self, id: &str) {
1046 self.style.controls.insert(self.current, id.to_string());
1047 }
1048
1049 pub fn set_hidden(&mut self, hidden: bool) {
1051 self.style.hidden.insert(self.current, hidden)
1052 }
1053
1054 pub fn text_value(&mut self, text: &str) {
1056 self.style.text_value.insert(self.current, text.to_string());
1057 }
1058
1059 pub fn numeric_value(&mut self, value: f64) {
1061 self.style.numeric_value.insert(self.current, value);
1062 }
1063
1064 pub fn set_display(&mut self, display: Display) {
1070 self.style.display.insert(self.current, display);
1071 }
1072
1073 pub fn set_visibility(&mut self, visibility: Visibility) {
1077 self.style.visibility.insert(self.current, visibility);
1078 }
1079
1080 pub fn set_opacity(&mut self, opacity: f32) {
1084 self.style.opacity.insert(self.current, Opacity(opacity));
1085 }
1086
1087 pub fn set_z_index(&mut self, z_index: i32) {
1089 self.style.z_index.insert(self.current, z_index);
1090 }
1091
1092 pub fn set_clip_path(&mut self, clip_path: ClipPath) {
1094 self.style.clip_path.insert(self.current, clip_path);
1095 self.needs_reclip();
1096 self.needs_redraw();
1097 }
1098
1099 pub fn set_overflowx(&mut self, overflowx: impl Into<Overflow>) {
1101 self.style.overflowx.insert(self.current, overflowx.into());
1102 self.needs_reclip();
1103 self.needs_redraw();
1104 }
1105
1106 pub fn set_overflowy(&mut self, overflowy: impl Into<Overflow>) {
1108 self.style.overflowy.insert(self.current, overflowy.into());
1109 self.needs_reclip();
1110 self.needs_redraw();
1111 }
1112
1113 pub fn set_transform(&mut self, transform: impl Into<Vec<Transform>>) {
1117 self.style.transform.insert(self.current, transform.into());
1118 self.needs_retransform();
1119 self.needs_redraw();
1120 }
1121
1122 pub fn set_transform_origin(&mut self, transform_origin: Translate) {
1124 self.style.transform_origin.insert(self.current, transform_origin);
1125 self.needs_retransform();
1126 self.needs_redraw();
1127 }
1128
1129 pub fn set_translate(&mut self, translate: impl Into<Translate>) {
1131 self.style.translate.insert(self.current, translate.into());
1132 self.needs_retransform();
1133 self.needs_redraw();
1134 }
1135
1136 pub fn set_rotate(&mut self, angle: impl Into<Angle>) {
1138 self.style.rotate.insert(self.current, angle.into());
1139 self.needs_retransform();
1140 self.needs_redraw();
1141 }
1142
1143 pub fn set_scale(&mut self, scale: impl Into<Scale>) {
1145 self.style.scale.insert(self.current, scale.into());
1146 self.needs_retransform();
1147 self.needs_redraw();
1148 }
1149
1150 pub fn set_filter(&mut self, filter: Filter) {
1154 self.style.filter.insert(self.current, filter);
1155 self.needs_redraw();
1156 }
1157
1158 pub fn set_backdrop_filter(&mut self, filter: Filter) {
1160 self.style.backdrop_filter.insert(self.current, filter);
1161 self.needs_redraw();
1162 }
1163
1164 pub fn set_background_color(&mut self, background_color: Color) {
1171 self.style.background_color.insert(self.current, background_color);
1172 self.needs_redraw();
1173 }
1174
1175 pub fn set_width(&mut self, width: Units) {
1178 self.style.width.insert(self.current, width);
1179 self.needs_relayout();
1180 self.needs_redraw();
1181 }
1182
1183 pub fn set_height(&mut self, height: Units) {
1184 self.style.height.insert(self.current, height);
1185 self.needs_relayout();
1186 self.needs_redraw();
1187 }
1188
1189 pub fn set_max_height(&mut self, height: Units) {
1190 self.style.max_height.insert(self.current, height);
1191 self.needs_relayout();
1192 self.needs_redraw();
1193 }
1194
1195 pub fn set_left(&mut self, left: Units) {
1198 self.style.left.insert(self.current, left);
1199 self.needs_relayout();
1200 self.needs_redraw();
1201 }
1202
1203 pub fn set_top(&mut self, top: Units) {
1204 self.style.top.insert(self.current, top);
1205 self.needs_relayout();
1206 self.needs_redraw();
1207 }
1208
1209 pub fn set_right(&mut self, right: Units) {
1210 self.style.right.insert(self.current, right);
1211 self.needs_relayout();
1212 self.needs_redraw();
1213 }
1214
1215 pub fn set_bottom(&mut self, bottom: Units) {
1216 self.style.bottom.insert(self.current, bottom);
1217 self.needs_relayout();
1218 self.needs_redraw();
1219 }
1220
1221 pub fn set_padding_left(&mut self, padding_left: Units) {
1224 self.style.padding_left.insert(self.current, padding_left);
1225 self.needs_relayout();
1226 self.needs_redraw();
1227 }
1228
1229 pub fn set_padding_top(&mut self, padding_top: Units) {
1230 self.style.padding_top.insert(self.current, padding_top);
1231 self.needs_relayout();
1232 self.needs_redraw();
1233 }
1234
1235 pub fn set_padding_right(&mut self, padding_right: Units) {
1236 self.style.padding_right.insert(self.current, padding_right);
1237 self.needs_relayout();
1238 self.needs_redraw();
1239 }
1240
1241 pub fn set_padding_bottom(&mut self, padding_bottom: Units) {
1242 self.style.padding_bottom.insert(self.current, padding_bottom);
1243 self.needs_relayout();
1244 self.needs_redraw();
1245 }
1246
1247 pub fn set_text(&mut self, text: &str) {
1251 self.style.text.insert(self.current, text.to_owned());
1252 self.style.needs_text_update(self.current);
1253 self.needs_relayout();
1254 self.needs_redraw();
1255 }
1256
1257 pub fn set_pointer_events(&mut self, pointer_events: impl Into<PointerEvents>) {
1258 self.style.pointer_events.insert(self.current, pointer_events.into());
1259 }
1260
1261 get_length_property!(
1263 border_width
1265 );
1266
1267 pub fn font_size(&self) -> f32 {
1269 self.logical_to_physical(
1270 self.style
1271 .font_size
1272 .get(self.current)
1273 .cloned()
1274 .map(|f| f.0.to_px().unwrap())
1275 .unwrap_or(16.0),
1276 )
1277 }
1278
1279 pub fn add_timer(
1310 &mut self,
1311 interval: Duration,
1312 duration: Option<Duration>,
1313 callback: impl Fn(&mut EventContext, TimerAction) + 'static,
1314 ) -> Timer {
1315 let id = Timer(self.timers.len());
1316 self.timers.push(TimerState {
1317 entity: Entity::root(),
1318 id,
1319 time: Instant::now(),
1320 interval,
1321 duration,
1322 start_time: Instant::now(),
1323 callback: Rc::new(callback),
1324 ticking: false,
1325 stopping: false,
1326 });
1327
1328 id
1329 }
1330
1331 pub fn start_timer(&mut self, timer: Timer) {
1335 let current = self.current;
1336 if !self.timer_is_running(timer) {
1337 let timer_state = self.timers[timer.0].clone();
1338 self.running_timers.push(timer_state);
1340 }
1341
1342 self.modify_timer(timer, |timer_state| {
1343 let now = Instant::now();
1344 timer_state.start_time = now;
1345 timer_state.time = now;
1346 timer_state.entity = current;
1347 timer_state.ticking = false;
1348 timer_state.stopping = false;
1349 });
1350 }
1351
1352 pub fn modify_timer(&mut self, timer: Timer, timer_function: impl Fn(&mut TimerState)) {
1354 while let Some(next_timer_state) = self.running_timers.peek() {
1355 if next_timer_state.id == timer {
1356 let mut timer_state = self.running_timers.pop().unwrap();
1357
1358 (timer_function)(&mut timer_state);
1359
1360 self.running_timers.push(timer_state);
1361
1362 return;
1363 }
1364 }
1365
1366 for pending_timer in self.timers.iter_mut() {
1367 if pending_timer.id == timer {
1368 (timer_function)(pending_timer);
1369 }
1370 }
1371 }
1372
1373 pub fn query_timer<T>(
1374 &mut self,
1375 timer: Timer,
1376 timer_function: impl Fn(&TimerState) -> T,
1377 ) -> Option<T> {
1378 while let Some(next_timer_state) = self.running_timers.peek() {
1379 if next_timer_state.id == timer {
1380 let timer_state = self.running_timers.pop().unwrap();
1381
1382 let t = (timer_function)(&timer_state);
1383
1384 self.running_timers.push(timer_state);
1385
1386 return Some(t);
1387 }
1388 }
1389
1390 for pending_timer in self.timers.iter() {
1391 if pending_timer.id == timer {
1392 return Some(timer_function(pending_timer));
1393 }
1394 }
1395
1396 None
1397 }
1398
1399 pub fn timer_is_running(&mut self, timer: Timer) -> bool {
1401 for timer_state in self.running_timers.iter() {
1402 if timer_state.id == timer {
1403 return true;
1404 }
1405 }
1406
1407 false
1408 }
1409
1410 pub fn stop_timer(&mut self, timer: Timer) {
1414 let mut running_timers = self.running_timers.clone();
1415
1416 for timer_state in running_timers.iter() {
1417 if timer_state.id == timer {
1418 self.with_current(timer_state.entity, |cx| {
1419 (timer_state.callback)(cx, TimerAction::Stop);
1420 });
1421 }
1422 }
1423
1424 *self.running_timers =
1425 running_timers.drain().filter(|timer_state| timer_state.id != timer).collect();
1426 }
1427}
1428
1429impl DataContext for EventContext<'_> {
1430 fn try_data<T: 'static>(&self) -> Option<&T> {
1431 if let Some(t) = <dyn Any>::downcast_ref::<T>(&()) {
1433 return Some(t);
1434 }
1435
1436 for entity in self.current.parent_iter(self.tree) {
1437 if let Some(models) = self.models.get(&entity) {
1439 if let Some(model) = models.get(&TypeId::of::<T>()) {
1440 return model.downcast_ref::<T>();
1441 }
1442 }
1443
1444 if let Some(view_handler) = self.views.get(&entity) {
1446 if let Some(data) = view_handler.downcast_ref::<T>() {
1447 return Some(data);
1448 }
1449 }
1450 }
1451
1452 None
1453 }
1454
1455 fn localization_context(&self) -> Option<LocalizationContext<'_>> {
1456 Some(LocalizationContext::from_event_context(self))
1457 }
1458}
1459
1460impl EmitContext for EventContext<'_> {
1461 fn emit<M: Any + Send>(&mut self, message: M) {
1462 self.event_queue.push_back(
1463 Event::new(message)
1464 .target(self.current)
1465 .origin(self.current)
1466 .propagate(Propagation::Up),
1467 );
1468 }
1469
1470 fn emit_to<M: Any + Send>(&mut self, target: Entity, message: M) {
1471 self.event_queue.push_back(
1472 Event::new(message).target(target).origin(self.current).propagate(Propagation::Direct),
1473 );
1474 }
1475
1476 fn emit_custom(&mut self, event: Event) {
1477 self.event_queue.push_back(event);
1478 }
1479
1480 fn schedule_emit<M: Any + Send>(&mut self, message: M, at: Instant) -> TimedEventHandle {
1481 self.schedule_emit_custom(
1482 Event::new(message)
1483 .target(self.current)
1484 .origin(self.current)
1485 .propagate(Propagation::Up),
1486 at,
1487 )
1488 }
1489 fn schedule_emit_to<M: Any + Send>(
1490 &mut self,
1491 target: Entity,
1492 message: M,
1493 at: Instant,
1494 ) -> TimedEventHandle {
1495 self.schedule_emit_custom(
1496 Event::new(message).target(target).origin(self.current).propagate(Propagation::Direct),
1497 at,
1498 )
1499 }
1500 fn schedule_emit_custom(&mut self, event: Event, at: Instant) -> TimedEventHandle {
1501 let handle = TimedEventHandle(*self.next_event_id);
1502 self.event_schedule.push(TimedEvent { event, time: at, ident: handle });
1503 *self.next_event_id += 1;
1504 handle
1505 }
1506 fn cancel_scheduled(&mut self, handle: TimedEventHandle) {
1507 *self.event_schedule =
1508 self.event_schedule.drain().filter(|item| item.ident != handle).collect();
1509 }
1510}
1511
1512pub trait TreeProps {
1514 fn parent(&self) -> Entity;
1516 fn first_child(&self) -> Entity;
1518 fn parent_window(&self) -> Entity;
1520}
1521
1522impl TreeProps for EventContext<'_> {
1523 fn parent(&self) -> Entity {
1524 self.tree.get_layout_parent(self.current).unwrap()
1525 }
1526
1527 fn first_child(&self) -> Entity {
1528 self.tree.get_layout_first_child(self.current).unwrap()
1529 }
1530
1531 fn parent_window(&self) -> Entity {
1532 self.tree.get_parent_window(self.current).unwrap_or(Entity::root())
1533 }
1534}