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 pub(crate) modifiers: &'a Modifiers,
79 pub(crate) mouse: &'a MouseState<Entity>,
80 pub(crate) event_queue: &'a mut VecDeque<Event>,
81 pub(crate) event_schedule: &'a mut BinaryHeap<TimedEvent>,
82 pub(crate) next_event_id: &'a mut usize,
83 pub(crate) timers: &'a mut Vec<TimerState>,
84 pub(crate) running_timers: &'a mut BinaryHeap<TimerState>,
85 cursor_icon_locked: &'a mut bool,
86 #[cfg(feature = "clipboard")]
87 clipboard: &'a mut Box<dyn ClipboardProvider>,
88 pub(crate) event_proxy: &'a mut Option<Box<dyn crate::context::EventProxy>>,
89 pub(crate) drop_data: &'a mut Option<DropData>,
90 pub(crate) active_drag_view: &'a mut Option<Entity>,
91 pub windows: &'a mut HashMap<Entity, WindowState>,
92}
93
94macro_rules! get_length_property {
95 (
96 $(#[$meta:meta])*
97 $name:ident
98 ) => {
99 $(#[$meta])*
100 pub fn $name(&self) -> f32 {
101 if let Some(length) = self.style.$name.get(self.current) {
102 let bounds = self.bounds();
103
104 let px = length.to_pixels(bounds.w.min(bounds.h), self.scale_factor());
105 return px.round();
106 }
107
108 0.0
109 }
110 };
111}
112
113impl<'a> EventContext<'a> {
114 pub fn new(cx: &'a mut Context) -> Self {
116 Self {
117 current: cx.current,
118 captured: &mut cx.captured,
119 focused: &mut cx.focused,
120 hovered: &cx.hovered,
121 triggered: &mut cx.triggered,
122 entity_identifiers: &cx.entity_identifiers,
123 style: &mut cx.style,
124 cache: &mut cx.cache,
125 tree: &cx.tree,
126 models: &mut cx.models,
127 views: &mut cx.views,
128 listeners: &mut cx.listeners,
129 resource_manager: &mut cx.resource_manager,
130 text_context: &mut cx.text_context,
131 modifiers: &cx.modifiers,
132 mouse: &cx.mouse,
133 event_queue: &mut cx.event_queue,
134 event_schedule: &mut cx.event_schedule,
135 next_event_id: &mut cx.next_event_id,
136 timers: &mut cx.timers,
137 running_timers: &mut cx.running_timers,
138 cursor_icon_locked: &mut cx.cursor_icon_locked,
139 #[cfg(feature = "clipboard")]
140 clipboard: &mut cx.clipboard,
141 event_proxy: &mut cx.event_proxy,
142 drop_data: &mut cx.drop_data,
143 active_drag_view: &mut cx.active_drag_view,
144 windows: &mut cx.windows,
145 }
146 }
147
148 pub fn new_with_current(cx: &'a mut Context, current: Entity) -> Self {
150 Self {
151 current,
152 captured: &mut cx.captured,
153 focused: &mut cx.focused,
154 hovered: &cx.hovered,
155 triggered: &mut cx.triggered,
156 entity_identifiers: &cx.entity_identifiers,
157 style: &mut cx.style,
158 cache: &mut cx.cache,
159 tree: &cx.tree,
160 models: &mut cx.models,
161 views: &mut cx.views,
162 listeners: &mut cx.listeners,
163 resource_manager: &mut cx.resource_manager,
164 text_context: &mut cx.text_context,
165 modifiers: &cx.modifiers,
166 mouse: &cx.mouse,
167 event_queue: &mut cx.event_queue,
168 event_schedule: &mut cx.event_schedule,
169 next_event_id: &mut cx.next_event_id,
170 timers: &mut cx.timers,
171 running_timers: &mut cx.running_timers,
172 cursor_icon_locked: &mut cx.cursor_icon_locked,
173 #[cfg(feature = "clipboard")]
174 clipboard: &mut cx.clipboard,
175 event_proxy: &mut cx.event_proxy,
176 drop_data: &mut cx.drop_data,
177 active_drag_view: &mut cx.active_drag_view,
178 windows: &mut cx.windows,
179 }
180 }
181
182 pub fn get_view<V: View>(&self) -> Option<&V> {
184 self.views.get(&self.current).and_then(|view| view.downcast_ref::<V>())
185 }
186
187 pub fn get_view_with<V: View>(&self, entity: Entity) -> Option<&V> {
189 self.views.get(&entity).and_then(|view| view.downcast_ref::<V>())
190 }
191
192 pub fn close_window(&mut self) {
193 if let Some(state) = self.windows.get_mut(&self.current) {
194 state.should_close = true;
195 }
196 }
197
198 pub fn resolve_entity_identifier(&self, id: &str) -> Option<Entity> {
200 self.entity_identifiers.get(id).cloned()
201 }
202
203 pub fn get_entity_by_element_id(&self, element: &str) -> Option<Entity> {
205 let descendants = LayoutTreeIterator::subtree(self.tree, self.current);
206 for descendant in descendants {
207 if let Some(id) = self.views.get(&descendant).and_then(|view| view.element()) {
208 if id == element {
209 return Some(descendant);
210 }
211 }
212 }
213
214 None
215 }
216
217 pub fn get_entities_by_class(&self, class: &str) -> Vec<Entity> {
219 let mut entities = Vec::new();
220 let descendants = LayoutTreeIterator::subtree(self.tree, self.current);
221 for descendant in descendants {
222 if let Some(class_list) = self.style.classes.get(descendant) {
223 if class_list.contains(class) {
224 entities.push(descendant);
225 }
226 }
227 }
228
229 entities
230 }
231
232 pub fn current(&self) -> Entity {
234 self.current
235 }
236
237 pub fn modifiers(&self) -> &Modifiers {
239 self.modifiers
240 }
241
242 pub fn mouse(&self) -> &MouseState<Entity> {
244 self.mouse
245 }
246
247 pub fn nth_child(&self, n: usize) -> Option<Entity> {
248 self.tree.get_child(self.current, n)
249 }
250
251 pub fn last_child(&self) -> Option<Entity> {
252 self.tree.get_last_child(self.current).copied()
253 }
254
255 pub fn with_current<T>(&mut self, entity: Entity, f: impl FnOnce(&mut Self) -> T) -> T {
256 let prev = self.current();
257 self.current = entity;
258 let ret = (f)(self);
259 self.current = prev;
260 ret
261 }
262
263 pub fn has_drop_data(&self) -> bool {
265 self.drop_data.is_some()
266 }
267
268 pub fn drop_data(&self) -> Option<&DropData> {
270 self.drop_data.as_ref()
271 }
272
273 pub fn active_drag_view(&self) -> Option<Entity> {
275 *self.active_drag_view
276 }
277
278 pub fn set_active_drag_view(&mut self, drag_view: Option<Entity>) {
280 *self.active_drag_view = drag_view;
281 }
282
283 pub fn bounds(&self) -> BoundingBox {
285 self.cache.get_bounds(self.current)
286 }
287
288 pub fn scale_factor(&self) -> f32 {
294 self.style.dpi_factor as f32
295 }
296
297 pub fn logical_to_physical(&self, logical: f32) -> f32 {
299 self.style.logical_to_physical(logical)
300 }
301
302 pub fn physical_to_logical(&self, physical: f32) -> f32 {
304 self.style.physical_to_logical(physical)
305 }
306
307 pub fn clip_region(&self) -> BoundingBox {
309 let current_window = if self.tree.is_window(self.current) {
310 self.current
311 } else {
312 self.tree.get_parent_window(self.current).unwrap_or(Entity::root())
313 };
314
315 let window_bounds = self.cache.get_bounds(current_window);
316
317 if let Some(clip_path) = self.cache.clip_path.get(self.current) {
319 return clip_path
320 .clone()
321 .map(|clip_path| Into::<BoundingBox>::into(*clip_path.bounds()))
322 .unwrap_or(window_bounds);
323 }
324
325 if self.style.ignore_clipping.get(self.current).copied().unwrap_or(false) {
326 return window_bounds;
327 }
328
329 let mut current = self.current;
330 while let Some(parent) = self.tree.get_parent(current) {
331 if let Some(clip_path) = self.cache.clip_path.get(parent) {
333 return clip_path
334 .clone()
335 .map(|clip_path| Into::<BoundingBox>::into(*clip_path.bounds()))
336 .unwrap_or(window_bounds);
337 }
338
339 if self.style.ignore_clipping.get(parent).copied().unwrap_or(false) {
340 return window_bounds;
341 }
342
343 if parent == current_window {
344 break;
345 }
346
347 current = parent;
348 }
349
350 window_bounds
351 }
352
353 pub fn transform(&self) -> Matrix {
355 self.cache.transform.get(self.current).copied().unwrap_or_default()
356 }
357
358 pub fn play_animation(&mut self, anim_id: impl AnimId, duration: Duration, delay: Duration) {
360 if let Some(animation_id) = anim_id.get(self) {
361 self.style.enqueue_animation(self.current, animation_id, duration, delay);
362 }
363 }
364
365 pub fn play_animation_for(
367 &mut self,
368 anim_id: impl AnimId,
369 target: &str,
370 duration: Duration,
371 delay: Duration,
372 ) {
373 if let Some(target_entity) = self.resolve_entity_identifier(target) {
374 if let Some(animation_id) = anim_id.get(self) {
375 self.style.enqueue_animation(target_entity, animation_id, duration, delay)
376 }
377 }
378 }
379
380 pub fn is_animating(&self, anim_id: impl AnimId) -> bool {
382 if let Some(animation_id) = anim_id.get(self) {
383 return self.style.is_animating(self.current, animation_id);
384 }
385
386 false
387 }
388
389 pub fn add_listener<F, W>(&mut self, listener: F)
395 where
396 W: View,
397 F: 'static + Fn(&mut W, &mut EventContext, &mut Event),
398 {
399 self.listeners.insert(
400 self.current,
401 Box::new(move |event_handler, context, event| {
402 if let Some(widget) = event_handler.downcast_mut::<W>() {
403 (listener)(widget, context, event);
404 }
405 }),
406 );
407 }
408
409 pub fn set_language(&mut self, lang: LanguageIdentifier) {
411 if let Some(mut models) = self.models.remove(&Entity::root()) {
412 if let Some(model) = models.get_mut(&TypeId::of::<Environment>()) {
413 model.event(self, &mut Event::new(EnvironmentEvent::SetLocale(lang)));
414 }
415
416 self.models.insert(Entity::root(), models);
417 }
418 }
419
420 pub fn add_image_encoded(&mut self, path: &str, data: &[u8], policy: ImageRetentionPolicy) {
421 let id = if let Some(image_id) = self.resource_manager.image_ids.get(path) {
422 *image_id
423 } else {
424 let id = self.resource_manager.image_id_manager.create();
425 self.resource_manager.image_ids.insert(path.to_owned(), id);
426 id
427 };
428
429 if let Some(image) = skia_safe::Image::from_encoded(skia_safe::Data::new_copy(data)) {
430 match self.resource_manager.images.entry(id) {
431 Entry::Occupied(mut occ) => {
432 occ.get_mut().image = ImageOrSvg::Image(image);
433 occ.get_mut().dirty = true;
434 occ.get_mut().retention_policy = policy;
435 }
436 Entry::Vacant(vac) => {
437 vac.insert(StoredImage {
438 image: ImageOrSvg::Image(image),
439 retention_policy: policy,
440 used: true,
441 dirty: false,
442 observers: HashSet::new(),
443 });
444 }
445 }
446 self.style.needs_relayout();
447 }
448 }
449
450 pub fn capture(&mut self) {
452 *self.captured = self.current;
453 }
454
455 pub fn release(&mut self) {
457 if self.current == *self.captured {
458 *self.captured = Entity::null();
459 }
460 }
461
462 fn set_focus_pseudo_classes(&mut self, focused: Entity, enabled: bool, focus_visible: bool) {
464 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(focused) {
465 pseudo_classes.set(PseudoClassFlags::FOCUS, enabled);
466 if !enabled || focus_visible {
467 pseudo_classes.set(PseudoClassFlags::FOCUS_VISIBLE, enabled);
468 }
469 }
470
471 for ancestor in focused.parent_iter(self.tree) {
472 let entity = ancestor;
473 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(entity) {
474 pseudo_classes.set(PseudoClassFlags::FOCUS_WITHIN, enabled);
475 }
476 self.style.needs_restyle(entity);
477 }
478 }
479
480 pub fn focus_with_visibility(&mut self, focus_visible: bool) {
482 let old_focus = self.focused();
483 let new_focus = self.current();
484 self.set_focus_pseudo_classes(old_focus, false, focus_visible);
485 if self.current() != self.focused() {
486 self.emit_to(old_focus, WindowEvent::FocusOut);
487 self.emit_to(new_focus, WindowEvent::FocusIn);
488 *self.focused = self.current();
489 }
490 self.set_focus_pseudo_classes(new_focus, true, focus_visible);
491
492 self.emit_custom(Event::new(WindowEvent::FocusVisibility(focus_visible)).target(old_focus));
493 self.emit_custom(Event::new(WindowEvent::FocusVisibility(focus_visible)).target(new_focus));
494
495 self.needs_restyle();
496 }
497
498 pub fn focus(&mut self) {
502 let focused = self.focused();
503 let old_focus_visible = self
504 .style
505 .pseudo_classes
506 .get_mut(focused)
507 .filter(|class| class.contains(PseudoClassFlags::FOCUS_VISIBLE))
508 .is_some();
509 self.focus_with_visibility(old_focus_visible)
510 }
511
512 pub fn focus_next(&mut self) {
514 let lock_focus_to = self.tree.lock_focus_within(*self.focused);
515 let next_focused = if let Some(next_focused) =
516 focus_forward(self.tree, self.style, *self.focused, lock_focus_to)
517 {
518 next_focused
519 } else {
520 TreeIterator::full(self.tree)
521 .find(|node| is_navigatable(self.tree, self.style, *node, lock_focus_to))
522 .unwrap_or(Entity::root())
523 };
524
525 if next_focused != *self.focused {
526 self.event_queue.push_back(
527 Event::new(WindowEvent::FocusOut).target(*self.focused).origin(Entity::root()),
528 );
529 self.event_queue.push_back(
530 Event::new(WindowEvent::FocusIn).target(next_focused).origin(Entity::root()),
531 );
532
533 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(*self.triggered) {
534 pseudo_classes.set(PseudoClassFlags::ACTIVE, false);
535 }
536 self.needs_restyle();
537 *self.triggered = Entity::null();
538 }
539 }
540
541 pub fn focus_prev(&mut self) {
543 let lock_focus_to = self.tree.lock_focus_within(*self.focused);
544 let prev_focused = if let Some(prev_focused) =
545 focus_backward(self.tree, self.style, *self.focused, lock_focus_to)
546 {
547 prev_focused
548 } else {
549 TreeIterator::full(self.tree)
550 .rfind(|node| is_navigatable(self.tree, self.style, *node, lock_focus_to))
551 .unwrap_or(Entity::root())
552 };
553
554 if prev_focused != *self.focused {
555 self.event_queue.push_back(
556 Event::new(WindowEvent::FocusOut).target(*self.focused).origin(Entity::root()),
557 );
558 self.event_queue.push_back(
559 Event::new(WindowEvent::FocusIn).target(prev_focused).origin(Entity::root()),
560 );
561
562 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(*self.triggered) {
563 pseudo_classes.set(PseudoClassFlags::ACTIVE, false);
564 }
565 self.needs_restyle();
566 *self.triggered = Entity::null();
567 }
568 }
569
570 pub fn hovered(&self) -> Entity {
572 *self.hovered
573 }
574
575 pub fn focused(&self) -> Entity {
577 *self.focused
578 }
579
580 pub fn is_hovered(&self) -> bool {
584 self.hovered() == self.current
585 }
586
587 pub fn is_active(&self) -> bool {
589 if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
590 pseudo_classes.contains(PseudoClassFlags::ACTIVE)
591 } else {
592 false
593 }
594 }
595
596 pub fn is_over(&self) -> bool {
598 if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
599 pseudo_classes.contains(PseudoClassFlags::OVER)
600 } else {
601 false
602 }
603 }
604
605 pub fn is_focused(&self) -> bool {
607 self.focused() == self.current
608 }
609
610 pub fn is_draggable(&self) -> bool {
612 self.style
613 .abilities
614 .get(self.current)
615 .map(|abilities| abilities.contains(Abilities::DRAGGABLE))
616 .unwrap_or_default()
617 }
618
619 pub fn is_disabled(&self) -> bool {
621 self.style.disabled.get(self.current()).cloned().unwrap_or_default()
622 }
623
624 pub fn is_checked(&self) -> bool {
626 if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
627 pseudo_classes.contains(PseudoClassFlags::CHECKED)
628 } else {
629 false
630 }
631 }
632
633 pub fn is_read_only(&self) -> bool {
635 if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
636 pseudo_classes.contains(PseudoClassFlags::READ_ONLY)
637 } else {
638 false
639 }
640 }
641
642 pub fn lock_cursor_icon(&mut self) {
646 *self.cursor_icon_locked = true;
647 }
648
649 pub fn unlock_cursor_icon(&mut self) {
651 *self.cursor_icon_locked = false;
652 let hovered = *self.hovered;
653 let cursor = self.style.cursor.get(hovered).cloned().unwrap_or_default();
654 self.emit(WindowEvent::SetCursor(cursor));
655 }
656
657 pub fn is_cursor_icon_locked(&self) -> bool {
659 *self.cursor_icon_locked
660 }
661
662 pub fn set_drop_data(&mut self, data: impl Into<DropData>) {
664 *self.drop_data = Some(data.into())
665 }
666
667 #[cfg(feature = "clipboard")]
671 pub fn get_clipboard(&mut self) -> Result<String, Box<dyn Error + Send + Sync + 'static>> {
672 self.clipboard.get_contents()
673 }
674
675 #[cfg(feature = "clipboard")]
679 pub fn set_clipboard(
680 &mut self,
681 text: String,
682 ) -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
683 self.clipboard.set_contents(text)
684 }
685
686 pub fn toggle_class(&mut self, class_name: &str, applied: bool) {
696 let current = self.current();
697 if let Some(class_list) = self.style.classes.get_mut(current) {
698 if applied {
699 class_list.insert(class_name.to_string());
700 } else {
701 class_list.remove(class_name);
702 }
703 } else if applied {
704 let mut class_list = HashSet::new();
705 class_list.insert(class_name.to_string());
706 self.style.classes.insert(current, class_list);
707 }
708
709 self.needs_restyle();
710 }
711
712 pub fn environment(&self) -> &Environment {
714 self.data::<Environment>()
715 }
716
717 pub fn needs_redraw(&mut self) {
719 let parent_window = self.tree.get_parent_window(self.current).unwrap_or(Entity::root());
720 if let Some(window_state) = self.windows.get_mut(&parent_window) {
721 window_state.redraw_list.insert(self.current);
722 }
723 }
724
725 pub fn needs_relayout(&mut self) {
727 self.style.needs_relayout();
728 self.needs_redraw();
729 }
730
731 pub fn needs_restyle(&mut self) {
733 if self.current == Entity::null() || self.style.restyle.contains(&self.current) {
734 return;
735 }
736
737 self.style.restyle.insert(self.current);
738 let iter = if let Some(parent) = self.tree.get_layout_parent(self.current) {
739 LayoutTreeIterator::subtree(self.tree, parent)
740 } else {
741 LayoutTreeIterator::subtree(self.tree, self.current)
742 };
743
744 for descendant in iter {
745 self.style.restyle.insert(descendant);
746 }
747 self.style.needs_restyle(self.current);
748 }
749
750 pub fn needs_retransform(&mut self) {
751 self.style.needs_retransform(self.current);
752 let iter = LayoutTreeIterator::subtree(self.tree, self.current);
753 for descendant in iter {
754 self.style.needs_retransform(descendant);
755 }
756 }
757
758 pub fn needs_reclip(&mut self) {
759 self.style.needs_reclip(self.current);
760 let iter = LayoutTreeIterator::subtree(self.tree, self.current);
761 for descendant in iter {
762 self.style.needs_reclip(descendant);
763 }
764 }
765
766 pub fn reload_styles(&mut self) -> Result<(), std::io::Error> {
768 if self.resource_manager.styles.is_empty() {
769 return Ok(());
770 }
771
772 self.style.remove_rules();
773
774 self.style.clear_style_rules();
775
776 let mut overall_theme = String::new();
777
778 for style_string in self.resource_manager.styles.iter().flat_map(|style| style.get_style())
779 {
780 overall_theme += &style_string;
781 }
782
783 self.style.parse_theme(&overall_theme);
784
785 for entity in self.tree.into_iter() {
786 self.style.needs_restyle(entity);
787 self.style.needs_relayout();
788 self.style.needs_text_update(entity);
790 }
791
792 Ok(())
793 }
794
795 pub fn spawn<F>(&self, target: F)
797 where
798 F: 'static + Send + FnOnce(&mut ContextProxy),
799 {
800 let mut cxp = ContextProxy {
801 current: self.current,
802 event_proxy: self.event_proxy.as_ref().map(|p| p.make_clone()),
803 };
804
805 std::thread::spawn(move || target(&mut cxp));
806 }
807
808 pub fn get_proxy(&self) -> ContextProxy {
810 ContextProxy {
811 current: self.current,
812 event_proxy: self.event_proxy.as_ref().map(|p| p.make_clone()),
813 }
814 }
815
816 pub fn modify<V: View>(&mut self, f: impl FnOnce(&mut V)) {
817 if let Some(view) = self
818 .views
819 .get_mut(&self.current)
820 .and_then(|view_handler| view_handler.downcast_mut::<V>())
821 {
822 (f)(view);
823 }
824 }
825
826 pub fn background_color(&mut self) -> Color {
834 self.style.background_color.get(self.current).copied().unwrap_or_default()
835 }
836
837 pub fn set_id(&mut self, id: &str) {
840 self.style.ids.insert(self.current, id.to_string())
841 }
842
843 pub fn set_hover(&mut self, flag: bool) {
855 let current = self.current();
856 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
857 pseudo_classes.set(PseudoClassFlags::HOVER, flag);
858 }
859
860 self.needs_restyle();
861 }
862
863 pub fn set_active(&mut self, active: bool) {
872 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(self.current) {
873 pseudo_classes.set(PseudoClassFlags::ACTIVE, active);
874 }
875
876 self.needs_restyle();
877 }
878
879 pub fn set_read_only(&mut self, flag: bool) {
880 let current = self.current();
881 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
882 pseudo_classes.set(PseudoClassFlags::READ_ONLY, flag);
883 }
884
885 self.needs_restyle();
886 }
887
888 pub fn set_read_write(&mut self, flag: bool) {
889 let current = self.current();
890 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
891 pseudo_classes.set(PseudoClassFlags::READ_WRITE, flag);
892 }
893
894 self.needs_restyle();
895 }
896
897 pub fn set_checked(&mut self, flag: bool) {
906 let current = self.current();
907 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
908 pseudo_classes.set(PseudoClassFlags::CHECKED, flag);
909 }
910
911 self.needs_restyle();
912 }
913
914 pub fn set_valid(&mut self, flag: bool) {
923 let current = self.current();
924 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
925 pseudo_classes.set(PseudoClassFlags::VALID, flag);
926 pseudo_classes.set(PseudoClassFlags::INVALID, !flag);
927 }
928
929 self.needs_restyle();
930 }
931
932 pub fn set_placeholder_shown(&mut self, flag: bool) {
933 let current = self.current();
934 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
935 pseudo_classes.set(PseudoClassFlags::PLACEHOLDER_SHOWN, flag);
936 }
937
938 self.needs_restyle();
939 }
940
941 pub fn is_valid(&self) -> bool {
943 self.style
944 .pseudo_classes
945 .get(self.current)
946 .map(|pseudo_classes| pseudo_classes.contains(PseudoClassFlags::VALID))
947 .unwrap_or_default()
948 }
949
950 pub fn is_placeholder_shown(&self) -> bool {
951 self.style
952 .pseudo_classes
953 .get(self.current)
954 .map(|pseudo_classes| pseudo_classes.contains(PseudoClassFlags::PLACEHOLDER_SHOWN))
955 .unwrap_or_default()
956 }
957
958 pub fn set_name(&mut self, name: &str) {
962 self.style.name.insert(self.current, name.to_string());
963 }
964
965 pub fn set_role(&mut self, role: Role) {
967 self.style.role.insert(self.current, role);
968 }
969
970 pub fn set_live(&mut self, live: Live) {
977 self.style.live.insert(self.current, live);
978 }
979
980 pub fn labelled_by(&mut self, id: &str) {
982 self.style.labelled_by.insert(self.current, id.to_string());
983 }
984
985 pub fn described_by(&mut self, id: &str) {
987 self.style.described_by.insert(self.current, id.to_string());
988 }
989
990 pub fn controls(&mut self, id: &str) {
992 self.style.controls.insert(self.current, id.to_string());
993 }
994
995 pub fn set_hidden(&mut self, hidden: bool) {
997 self.style.hidden.insert(self.current, hidden)
998 }
999
1000 pub fn text_value(&mut self, text: &str) {
1002 self.style.text_value.insert(self.current, text.to_string());
1003 }
1004
1005 pub fn numeric_value(&mut self, value: f64) {
1007 self.style.numeric_value.insert(self.current, value);
1008 }
1009
1010 pub fn set_display(&mut self, display: Display) {
1016 self.style.display.insert(self.current, display);
1017 }
1018
1019 pub fn set_visibility(&mut self, visibility: Visibility) {
1023 self.style.visibility.insert(self.current, visibility);
1024 }
1025
1026 pub fn set_opacity(&mut self, opacity: f32) {
1030 self.style.opacity.insert(self.current, Opacity(opacity));
1031 }
1032
1033 pub fn set_z_index(&mut self, z_index: i32) {
1035 self.style.z_index.insert(self.current, z_index);
1036 }
1037
1038 pub fn set_clip_path(&mut self, clip_path: ClipPath) {
1040 self.style.clip_path.insert(self.current, clip_path);
1041 self.needs_reclip();
1042 self.needs_redraw();
1043 }
1044
1045 pub fn set_overflowx(&mut self, overflowx: impl Into<Overflow>) {
1047 self.style.overflowx.insert(self.current, overflowx.into());
1048 self.needs_reclip();
1049 self.needs_redraw();
1050 }
1051
1052 pub fn set_overflowy(&mut self, overflowy: impl Into<Overflow>) {
1054 self.style.overflowy.insert(self.current, overflowy.into());
1055 self.needs_reclip();
1056 self.needs_redraw();
1057 }
1058
1059 pub fn set_transform(&mut self, transform: impl Into<Vec<Transform>>) {
1063 self.style.transform.insert(self.current, transform.into());
1064 self.needs_retransform();
1065 self.needs_redraw();
1066 }
1067
1068 pub fn set_transform_origin(&mut self, transform_origin: Translate) {
1070 self.style.transform_origin.insert(self.current, transform_origin);
1071 self.needs_retransform();
1072 self.needs_redraw();
1073 }
1074
1075 pub fn set_translate(&mut self, translate: impl Into<Translate>) {
1077 self.style.translate.insert(self.current, translate.into());
1078 self.needs_retransform();
1079 self.needs_redraw();
1080 }
1081
1082 pub fn set_rotate(&mut self, angle: impl Into<Angle>) {
1084 self.style.rotate.insert(self.current, angle.into());
1085 self.needs_retransform();
1086 self.needs_redraw();
1087 }
1088
1089 pub fn set_scale(&mut self, scale: impl Into<Scale>) {
1091 self.style.scale.insert(self.current, scale.into());
1092 self.needs_retransform();
1093 self.needs_redraw();
1094 }
1095
1096 pub fn set_filter(&mut self, filter: Filter) {
1100 self.style.filter.insert(self.current, filter);
1101 self.needs_redraw();
1102 }
1103
1104 pub fn set_backdrop_filter(&mut self, filter: Filter) {
1106 self.style.backdrop_filter.insert(self.current, filter);
1107 self.needs_redraw();
1108 }
1109
1110 pub fn set_background_color(&mut self, background_color: Color) {
1117 self.style.background_color.insert(self.current, background_color);
1118 self.needs_redraw();
1119 }
1120
1121 pub fn set_width(&mut self, width: Units) {
1124 self.style.width.insert(self.current, width);
1125 self.needs_relayout();
1126 self.needs_redraw();
1127 }
1128
1129 pub fn set_height(&mut self, height: Units) {
1130 self.style.height.insert(self.current, height);
1131 self.needs_relayout();
1132 self.needs_redraw();
1133 }
1134
1135 pub fn set_max_height(&mut self, height: Units) {
1136 self.style.max_height.insert(self.current, height);
1137 self.needs_relayout();
1138 self.needs_redraw();
1139 }
1140
1141 pub fn set_left(&mut self, left: Units) {
1144 self.style.left.insert(self.current, left);
1145 self.needs_relayout();
1146 self.needs_redraw();
1147 }
1148
1149 pub fn set_top(&mut self, top: Units) {
1150 self.style.top.insert(self.current, top);
1151 self.needs_relayout();
1152 self.needs_redraw();
1153 }
1154
1155 pub fn set_right(&mut self, right: Units) {
1156 self.style.right.insert(self.current, right);
1157 self.needs_relayout();
1158 self.needs_redraw();
1159 }
1160
1161 pub fn set_bottom(&mut self, bottom: Units) {
1162 self.style.bottom.insert(self.current, bottom);
1163 self.needs_relayout();
1164 self.needs_redraw();
1165 }
1166
1167 pub fn set_padding_left(&mut self, padding_left: Units) {
1170 self.style.padding_left.insert(self.current, padding_left);
1171 self.needs_relayout();
1172 self.needs_redraw();
1173 }
1174
1175 pub fn set_padding_top(&mut self, padding_top: Units) {
1176 self.style.padding_top.insert(self.current, padding_top);
1177 self.needs_relayout();
1178 self.needs_redraw();
1179 }
1180
1181 pub fn set_padding_right(&mut self, padding_right: Units) {
1182 self.style.padding_right.insert(self.current, padding_right);
1183 self.needs_relayout();
1184 self.needs_redraw();
1185 }
1186
1187 pub fn set_padding_bottom(&mut self, padding_bottom: Units) {
1188 self.style.padding_bottom.insert(self.current, padding_bottom);
1189 self.needs_relayout();
1190 self.needs_redraw();
1191 }
1192
1193 pub fn set_text(&mut self, text: &str) {
1197 self.style.text.insert(self.current, text.to_owned());
1198 self.style.needs_text_update(self.current);
1199 self.needs_relayout();
1200 self.needs_redraw();
1201 }
1202
1203 pub fn set_pointer_events(&mut self, pointer_events: impl Into<PointerEvents>) {
1204 self.style.pointer_events.insert(self.current, pointer_events.into());
1205 }
1206
1207 get_length_property!(
1209 border_width
1211 );
1212
1213 pub fn font_size(&self) -> f32 {
1215 self.logical_to_physical(
1216 self.style
1217 .font_size
1218 .get(self.current)
1219 .cloned()
1220 .map(|f| f.0.to_px().unwrap())
1221 .unwrap_or(16.0),
1222 )
1223 }
1224
1225 pub fn add_timer(
1256 &mut self,
1257 interval: Duration,
1258 duration: Option<Duration>,
1259 callback: impl Fn(&mut EventContext, TimerAction) + 'static,
1260 ) -> Timer {
1261 let id = Timer(self.timers.len());
1262 self.timers.push(TimerState {
1263 entity: Entity::root(),
1264 id,
1265 time: Instant::now(),
1266 interval,
1267 duration,
1268 start_time: Instant::now(),
1269 callback: Rc::new(callback),
1270 ticking: false,
1271 stopping: false,
1272 });
1273
1274 id
1275 }
1276
1277 pub fn start_timer(&mut self, timer: Timer) {
1281 let current = self.current;
1282 if !self.timer_is_running(timer) {
1283 let timer_state = self.timers[timer.0].clone();
1284 self.running_timers.push(timer_state);
1286 }
1287
1288 self.modify_timer(timer, |timer_state| {
1289 let now = Instant::now();
1290 timer_state.start_time = now;
1291 timer_state.time = now;
1292 timer_state.entity = current;
1293 timer_state.ticking = false;
1294 timer_state.stopping = false;
1295 });
1296 }
1297
1298 pub fn modify_timer(&mut self, timer: Timer, timer_function: impl Fn(&mut TimerState)) {
1300 while let Some(next_timer_state) = self.running_timers.peek() {
1301 if next_timer_state.id == timer {
1302 let mut timer_state = self.running_timers.pop().unwrap();
1303
1304 (timer_function)(&mut timer_state);
1305
1306 self.running_timers.push(timer_state);
1307
1308 return;
1309 }
1310 }
1311
1312 for pending_timer in self.timers.iter_mut() {
1313 if pending_timer.id == timer {
1314 (timer_function)(pending_timer);
1315 }
1316 }
1317 }
1318
1319 pub fn query_timer<T>(
1320 &mut self,
1321 timer: Timer,
1322 timer_function: impl Fn(&TimerState) -> T,
1323 ) -> Option<T> {
1324 while let Some(next_timer_state) = self.running_timers.peek() {
1325 if next_timer_state.id == timer {
1326 let timer_state = self.running_timers.pop().unwrap();
1327
1328 let t = (timer_function)(&timer_state);
1329
1330 self.running_timers.push(timer_state);
1331
1332 return Some(t);
1333 }
1334 }
1335
1336 for pending_timer in self.timers.iter() {
1337 if pending_timer.id == timer {
1338 return Some(timer_function(pending_timer));
1339 }
1340 }
1341
1342 None
1343 }
1344
1345 pub fn timer_is_running(&mut self, timer: Timer) -> bool {
1347 for timer_state in self.running_timers.iter() {
1348 if timer_state.id == timer {
1349 return true;
1350 }
1351 }
1352
1353 false
1354 }
1355
1356 pub fn stop_timer(&mut self, timer: Timer) {
1360 let mut running_timers = self.running_timers.clone();
1361
1362 for timer_state in running_timers.iter() {
1363 if timer_state.id == timer {
1364 self.with_current(timer_state.entity, |cx| {
1365 (timer_state.callback)(cx, TimerAction::Stop);
1366 });
1367 }
1368 }
1369
1370 *self.running_timers =
1371 running_timers.drain().filter(|timer_state| timer_state.id != timer).collect();
1372 }
1373}
1374
1375impl DataContext for EventContext<'_> {
1376 fn try_data<T: 'static>(&self) -> Option<&T> {
1377 if let Some(t) = <dyn Any>::downcast_ref::<T>(&()) {
1379 return Some(t);
1380 }
1381
1382 for entity in self.current.parent_iter(self.tree) {
1383 if let Some(models) = self.models.get(&entity) {
1385 if let Some(model) = models.get(&TypeId::of::<T>()) {
1386 return model.downcast_ref::<T>();
1387 }
1388 }
1389
1390 if let Some(view_handler) = self.views.get(&entity) {
1392 if let Some(data) = view_handler.downcast_ref::<T>() {
1393 return Some(data);
1394 }
1395 }
1396 }
1397
1398 None
1399 }
1400
1401 fn localization_context(&self) -> Option<LocalizationContext<'_>> {
1402 Some(LocalizationContext::from_event_context(self))
1403 }
1404}
1405
1406impl EmitContext for EventContext<'_> {
1407 fn emit<M: Any + Send>(&mut self, message: M) {
1408 self.event_queue.push_back(
1409 Event::new(message)
1410 .target(self.current)
1411 .origin(self.current)
1412 .propagate(Propagation::Up),
1413 );
1414 }
1415
1416 fn emit_to<M: Any + Send>(&mut self, target: Entity, message: M) {
1417 self.event_queue.push_back(
1418 Event::new(message).target(target).origin(self.current).propagate(Propagation::Direct),
1419 );
1420 }
1421
1422 fn emit_custom(&mut self, event: Event) {
1423 self.event_queue.push_back(event);
1424 }
1425
1426 fn schedule_emit<M: Any + Send>(&mut self, message: M, at: Instant) -> TimedEventHandle {
1427 self.schedule_emit_custom(
1428 Event::new(message)
1429 .target(self.current)
1430 .origin(self.current)
1431 .propagate(Propagation::Up),
1432 at,
1433 )
1434 }
1435 fn schedule_emit_to<M: Any + Send>(
1436 &mut self,
1437 target: Entity,
1438 message: M,
1439 at: Instant,
1440 ) -> TimedEventHandle {
1441 self.schedule_emit_custom(
1442 Event::new(message).target(target).origin(self.current).propagate(Propagation::Direct),
1443 at,
1444 )
1445 }
1446 fn schedule_emit_custom(&mut self, event: Event, at: Instant) -> TimedEventHandle {
1447 let handle = TimedEventHandle(*self.next_event_id);
1448 self.event_schedule.push(TimedEvent { event, time: at, ident: handle });
1449 *self.next_event_id += 1;
1450 handle
1451 }
1452 fn cancel_scheduled(&mut self, handle: TimedEventHandle) {
1453 *self.event_schedule =
1454 self.event_schedule.drain().filter(|item| item.ident != handle).collect();
1455 }
1456}
1457
1458pub trait TreeProps {
1460 fn parent(&self) -> Entity;
1462 fn first_child(&self) -> Entity;
1464 fn parent_window(&self) -> Entity;
1466}
1467
1468impl TreeProps for EventContext<'_> {
1469 fn parent(&self) -> Entity {
1470 self.tree.get_layout_parent(self.current).unwrap()
1471 }
1472
1473 fn first_child(&self) -> Entity {
1474 self.tree.get_layout_first_child(self.current).unwrap()
1475 }
1476
1477 fn parent_window(&self) -> Entity {
1478 self.tree.get_parent_window(self.current).unwrap_or(Entity::root())
1479 }
1480}