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 windows: &'a mut HashMap<Entity, WindowState>,
91}
92
93macro_rules! get_length_property {
94 (
95 $(#[$meta:meta])*
96 $name:ident
97 ) => {
98 $(#[$meta])*
99 pub fn $name(&self) -> f32 {
100 if let Some(length) = self.style.$name.get(self.current) {
101 let bounds = self.bounds();
102
103 let px = length.to_pixels(bounds.w.min(bounds.h), self.scale_factor());
104 return px.round();
105 }
106
107 0.0
108 }
109 };
110}
111
112impl<'a> EventContext<'a> {
113 pub fn new(cx: &'a mut Context) -> Self {
115 Self {
116 current: cx.current,
117 captured: &mut cx.captured,
118 focused: &mut cx.focused,
119 hovered: &cx.hovered,
120 triggered: &mut cx.triggered,
121 entity_identifiers: &cx.entity_identifiers,
122 style: &mut cx.style,
123 cache: &mut cx.cache,
124 tree: &cx.tree,
125 models: &mut cx.models,
126 views: &mut cx.views,
127 listeners: &mut cx.listeners,
128 resource_manager: &mut cx.resource_manager,
129 text_context: &mut cx.text_context,
130 modifiers: &cx.modifiers,
131 mouse: &cx.mouse,
132 event_queue: &mut cx.event_queue,
133 event_schedule: &mut cx.event_schedule,
134 next_event_id: &mut cx.next_event_id,
135 timers: &mut cx.timers,
136 running_timers: &mut cx.running_timers,
137 cursor_icon_locked: &mut cx.cursor_icon_locked,
138 #[cfg(feature = "clipboard")]
139 clipboard: &mut cx.clipboard,
140 event_proxy: &mut cx.event_proxy,
141 drop_data: &mut cx.drop_data,
142 windows: &mut cx.windows,
143 }
144 }
145
146 pub fn new_with_current(cx: &'a mut Context, current: Entity) -> Self {
148 Self {
149 current,
150 captured: &mut cx.captured,
151 focused: &mut cx.focused,
152 hovered: &cx.hovered,
153 triggered: &mut cx.triggered,
154 entity_identifiers: &cx.entity_identifiers,
155 style: &mut cx.style,
156 cache: &mut cx.cache,
157 tree: &cx.tree,
158 models: &mut cx.models,
159 views: &mut cx.views,
160 listeners: &mut cx.listeners,
161 resource_manager: &mut cx.resource_manager,
162 text_context: &mut cx.text_context,
163 modifiers: &cx.modifiers,
164 mouse: &cx.mouse,
165 event_queue: &mut cx.event_queue,
166 event_schedule: &mut cx.event_schedule,
167 next_event_id: &mut cx.next_event_id,
168 timers: &mut cx.timers,
169 running_timers: &mut cx.running_timers,
170 cursor_icon_locked: &mut cx.cursor_icon_locked,
171 #[cfg(feature = "clipboard")]
172 clipboard: &mut cx.clipboard,
173 event_proxy: &mut cx.event_proxy,
174 drop_data: &mut cx.drop_data,
175 windows: &mut cx.windows,
176 }
177 }
178
179 pub fn get_view<V: View>(&self) -> Option<&V> {
181 self.views.get(&self.current).and_then(|view| view.downcast_ref::<V>())
182 }
183
184 pub fn get_view_with<V: View>(&self, entity: Entity) -> Option<&V> {
186 self.views.get(&entity).and_then(|view| view.downcast_ref::<V>())
187 }
188
189 pub fn close_window(&mut self) {
190 if let Some(state) = self.windows.get_mut(&self.current) {
191 state.should_close = true;
192 }
193 }
194
195 pub fn resolve_entity_identifier(&self, id: &str) -> Option<Entity> {
197 self.entity_identifiers.get(id).cloned()
198 }
199
200 pub fn get_entity_by_element_id(&self, element: &str) -> Option<Entity> {
202 let descendants = LayoutTreeIterator::subtree(self.tree, self.current);
203 for descendant in descendants {
204 if let Some(id) = self.views.get(&descendant).and_then(|view| view.element()) {
205 if id == element {
206 return Some(descendant);
207 }
208 }
209 }
210
211 None
212 }
213
214 pub fn get_entities_by_class(&self, class: &str) -> Vec<Entity> {
216 let mut entities = Vec::new();
217 let descendants = LayoutTreeIterator::subtree(self.tree, self.current);
218 for descendant in descendants {
219 if let Some(class_list) = self.style.classes.get(descendant) {
220 if class_list.contains(class) {
221 entities.push(descendant);
222 }
223 }
224 }
225
226 entities
227 }
228
229 pub fn current(&self) -> Entity {
231 self.current
232 }
233
234 pub fn modifiers(&self) -> &Modifiers {
236 self.modifiers
237 }
238
239 pub fn mouse(&self) -> &MouseState<Entity> {
241 self.mouse
242 }
243
244 pub fn nth_child(&self, n: usize) -> Option<Entity> {
245 self.tree.get_child(self.current, n)
246 }
247
248 pub fn last_child(&self) -> Option<Entity> {
249 self.tree.get_last_child(self.current).copied()
250 }
251
252 pub fn with_current<T>(&mut self, entity: Entity, f: impl FnOnce(&mut Self) -> T) -> T {
253 let prev = self.current();
254 self.current = entity;
255 let ret = (f)(self);
256 self.current = prev;
257 ret
258 }
259
260 pub fn has_drop_data(&self) -> bool {
262 self.drop_data.is_some()
263 }
264
265 pub fn bounds(&self) -> BoundingBox {
267 self.cache.get_bounds(self.current)
268 }
269
270 pub fn scale_factor(&self) -> f32 {
276 self.style.dpi_factor as f32
277 }
278
279 pub fn logical_to_physical(&self, logical: f32) -> f32 {
281 self.style.logical_to_physical(logical)
282 }
283
284 pub fn physical_to_logical(&self, physical: f32) -> f32 {
286 self.style.physical_to_logical(physical)
287 }
288
289 pub fn clip_region(&self) -> BoundingBox {
291 let current_window = if self.tree.is_window(self.current) {
292 self.current
293 } else {
294 self.tree.get_parent_window(self.current).unwrap_or(Entity::root())
295 };
296
297 self.cache
298 .clip_path
299 .get(self.current)
300 .cloned()
301 .flatten()
302 .map(|clip_path| Into::<BoundingBox>::into(*clip_path.bounds()))
303 .or_else(|| {
304 let mut current = self.current;
305 while let Some(parent) = self.tree.get_parent(current) {
306 if let Some(clip_path) = self
307 .cache
308 .clip_path
309 .get(parent)
310 .cloned()
311 .flatten()
312 .map(|clip_path| Into::<BoundingBox>::into(*clip_path.bounds()))
313 {
314 return Some(clip_path);
315 }
316
317 if parent == current_window {
318 break;
319 }
320
321 current = parent;
322 }
323 None
324 })
325 .unwrap_or_else(|| self.cache.get_bounds(current_window))
326 }
327
328 pub fn transform(&self) -> Matrix {
330 self.cache.transform.get(self.current).copied().unwrap_or_default()
331 }
332
333 pub fn play_animation(&mut self, anim_id: impl AnimId, duration: Duration, delay: Duration) {
335 if let Some(animation_id) = anim_id.get(self) {
336 self.style.enqueue_animation(self.current, animation_id, duration, delay);
337 }
338 }
339
340 pub fn play_animation_for(
342 &mut self,
343 anim_id: impl AnimId,
344 target: &str,
345 duration: Duration,
346 delay: Duration,
347 ) {
348 if let Some(target_entity) = self.resolve_entity_identifier(target) {
349 if let Some(animation_id) = anim_id.get(self) {
350 self.style.enqueue_animation(target_entity, animation_id, duration, delay)
351 }
352 }
353 }
354
355 pub fn is_animating(&self, anim_id: impl AnimId) -> bool {
357 if let Some(animation_id) = anim_id.get(self) {
358 return self.style.is_animating(self.current, animation_id);
359 }
360
361 false
362 }
363
364 pub fn add_listener<F, W>(&mut self, listener: F)
370 where
371 W: View,
372 F: 'static + Fn(&mut W, &mut EventContext, &mut Event),
373 {
374 self.listeners.insert(
375 self.current,
376 Box::new(move |event_handler, context, event| {
377 if let Some(widget) = event_handler.downcast_mut::<W>() {
378 (listener)(widget, context, event);
379 }
380 }),
381 );
382 }
383
384 pub fn set_language(&mut self, lang: LanguageIdentifier) {
386 if let Some(mut models) = self.models.remove(&Entity::root()) {
387 if let Some(model) = models.get_mut(&TypeId::of::<Environment>()) {
388 model.event(self, &mut Event::new(EnvironmentEvent::SetLocale(lang)));
389 }
390
391 self.models.insert(Entity::root(), models);
392 }
393 }
394
395 pub fn add_image_encoded(&mut self, path: &str, data: &[u8], policy: ImageRetentionPolicy) {
396 let id = if let Some(image_id) = self.resource_manager.image_ids.get(path) {
397 *image_id
398 } else {
399 let id = self.resource_manager.image_id_manager.create();
400 self.resource_manager.image_ids.insert(path.to_owned(), id);
401 id
402 };
403
404 if let Some(image) = skia_safe::Image::from_encoded(skia_safe::Data::new_copy(data)) {
405 match self.resource_manager.images.entry(id) {
406 Entry::Occupied(mut occ) => {
407 occ.get_mut().image = ImageOrSvg::Image(image);
408 occ.get_mut().dirty = true;
409 occ.get_mut().retention_policy = policy;
410 }
411 Entry::Vacant(vac) => {
412 vac.insert(StoredImage {
413 image: ImageOrSvg::Image(image),
414 retention_policy: policy,
415 used: true,
416 dirty: false,
417 observers: HashSet::new(),
418 });
419 }
420 }
421 self.style.needs_relayout();
422 }
423 }
424
425 pub fn capture(&mut self) {
427 *self.captured = self.current;
428 }
429
430 pub fn release(&mut self) {
432 if self.current == *self.captured {
433 *self.captured = Entity::null();
434 }
435 }
436
437 fn set_focus_pseudo_classes(&mut self, focused: Entity, enabled: bool, focus_visible: bool) {
439 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(focused) {
440 pseudo_classes.set(PseudoClassFlags::FOCUS, enabled);
441 if !enabled || focus_visible {
442 pseudo_classes.set(PseudoClassFlags::FOCUS_VISIBLE, enabled);
443 }
444 }
445
446 for ancestor in focused.parent_iter(self.tree) {
447 let entity = ancestor;
448 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(entity) {
449 pseudo_classes.set(PseudoClassFlags::FOCUS_WITHIN, enabled);
450 }
451 self.style.needs_restyle(entity);
452 }
453 }
454
455 pub fn focus_with_visibility(&mut self, focus_visible: bool) {
457 let old_focus = self.focused();
458 let new_focus = self.current();
459 self.set_focus_pseudo_classes(old_focus, false, focus_visible);
460 if self.current() != self.focused() {
461 self.emit_to(old_focus, WindowEvent::FocusOut);
462 self.emit_to(new_focus, WindowEvent::FocusIn);
463 *self.focused = self.current();
464 }
465 self.set_focus_pseudo_classes(new_focus, true, focus_visible);
466
467 self.emit_custom(Event::new(WindowEvent::FocusVisibility(focus_visible)).target(old_focus));
468 self.emit_custom(Event::new(WindowEvent::FocusVisibility(focus_visible)).target(new_focus));
469
470 self.needs_restyle();
471 }
472
473 pub fn focus(&mut self) {
477 let focused = self.focused();
478 let old_focus_visible = self
479 .style
480 .pseudo_classes
481 .get_mut(focused)
482 .filter(|class| class.contains(PseudoClassFlags::FOCUS_VISIBLE))
483 .is_some();
484 self.focus_with_visibility(old_focus_visible)
485 }
486
487 pub fn focus_next(&mut self) {
489 let lock_focus_to = self.tree.lock_focus_within(*self.focused);
490 let next_focused = if let Some(next_focused) =
491 focus_forward(self.tree, self.style, *self.focused, lock_focus_to)
492 {
493 next_focused
494 } else {
495 TreeIterator::full(self.tree)
496 .find(|node| is_navigatable(self.tree, self.style, *node, lock_focus_to))
497 .unwrap_or(Entity::root())
498 };
499
500 if next_focused != *self.focused {
501 self.event_queue.push_back(
502 Event::new(WindowEvent::FocusOut).target(*self.focused).origin(Entity::root()),
503 );
504 self.event_queue.push_back(
505 Event::new(WindowEvent::FocusIn).target(next_focused).origin(Entity::root()),
506 );
507
508 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(*self.triggered) {
509 pseudo_classes.set(PseudoClassFlags::ACTIVE, false);
510 }
511 self.needs_restyle();
512 *self.triggered = Entity::null();
513 }
514 }
515
516 pub fn focus_prev(&mut self) {
518 let lock_focus_to = self.tree.lock_focus_within(*self.focused);
519 let prev_focused = if let Some(prev_focused) =
520 focus_backward(self.tree, self.style, *self.focused, lock_focus_to)
521 {
522 prev_focused
523 } else {
524 TreeIterator::full(self.tree)
525 .rfind(|node| is_navigatable(self.tree, self.style, *node, lock_focus_to))
526 .unwrap_or(Entity::root())
527 };
528
529 if prev_focused != *self.focused {
530 self.event_queue.push_back(
531 Event::new(WindowEvent::FocusOut).target(*self.focused).origin(Entity::root()),
532 );
533 self.event_queue.push_back(
534 Event::new(WindowEvent::FocusIn).target(prev_focused).origin(Entity::root()),
535 );
536
537 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(*self.triggered) {
538 pseudo_classes.set(PseudoClassFlags::ACTIVE, false);
539 }
540 self.needs_restyle();
541 *self.triggered = Entity::null();
542 }
543 }
544
545 pub fn hovered(&self) -> Entity {
547 *self.hovered
548 }
549
550 pub fn focused(&self) -> Entity {
552 *self.focused
553 }
554
555 pub fn is_hovered(&self) -> bool {
559 self.hovered() == self.current
560 }
561
562 pub fn is_active(&self) -> bool {
564 if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
565 pseudo_classes.contains(PseudoClassFlags::ACTIVE)
566 } else {
567 false
568 }
569 }
570
571 pub fn is_over(&self) -> bool {
573 if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
574 pseudo_classes.contains(PseudoClassFlags::OVER)
575 } else {
576 false
577 }
578 }
579
580 pub fn is_focused(&self) -> bool {
582 self.focused() == self.current
583 }
584
585 pub fn is_draggable(&self) -> bool {
587 self.style
588 .abilities
589 .get(self.current)
590 .map(|abilities| abilities.contains(Abilities::DRAGGABLE))
591 .unwrap_or_default()
592 }
593
594 pub fn is_disabled(&self) -> bool {
596 self.style.disabled.get(self.current()).cloned().unwrap_or_default()
597 }
598
599 pub fn is_checked(&self) -> bool {
601 if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
602 pseudo_classes.contains(PseudoClassFlags::CHECKED)
603 } else {
604 false
605 }
606 }
607
608 pub fn is_read_only(&self) -> bool {
610 if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
611 pseudo_classes.contains(PseudoClassFlags::READ_ONLY)
612 } else {
613 false
614 }
615 }
616
617 pub fn lock_cursor_icon(&mut self) {
621 *self.cursor_icon_locked = true;
622 }
623
624 pub fn unlock_cursor_icon(&mut self) {
626 *self.cursor_icon_locked = false;
627 let hovered = *self.hovered;
628 let cursor = self.style.cursor.get(hovered).cloned().unwrap_or_default();
629 self.emit(WindowEvent::SetCursor(cursor));
630 }
631
632 pub fn is_cursor_icon_locked(&self) -> bool {
634 *self.cursor_icon_locked
635 }
636
637 pub fn set_drop_data(&mut self, data: impl Into<DropData>) {
639 *self.drop_data = Some(data.into())
640 }
641
642 #[cfg(feature = "clipboard")]
646 pub fn get_clipboard(&mut self) -> Result<String, Box<dyn Error + Send + Sync + 'static>> {
647 self.clipboard.get_contents()
648 }
649
650 #[cfg(feature = "clipboard")]
654 pub fn set_clipboard(
655 &mut self,
656 text: String,
657 ) -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
658 self.clipboard.set_contents(text)
659 }
660
661 pub fn toggle_class(&mut self, class_name: &str, applied: bool) {
671 let current = self.current();
672 if let Some(class_list) = self.style.classes.get_mut(current) {
673 if applied {
674 class_list.insert(class_name.to_string());
675 } else {
676 class_list.remove(class_name);
677 }
678 } else if applied {
679 let mut class_list = HashSet::new();
680 class_list.insert(class_name.to_string());
681 self.style.classes.insert(current, class_list);
682 }
683
684 self.needs_restyle();
685 }
686
687 pub fn environment(&self) -> &Environment {
689 self.data::<Environment>()
690 }
691
692 pub fn needs_redraw(&mut self) {
694 let parent_window = self.tree.get_parent_window(self.current).unwrap_or(Entity::root());
695 if let Some(window_state) = self.windows.get_mut(&parent_window) {
696 window_state.redraw_list.insert(self.current);
697 }
698 }
699
700 pub fn needs_relayout(&mut self) {
702 self.style.needs_relayout();
703 self.needs_redraw();
704 }
705
706 pub fn needs_restyle(&mut self) {
708 if self.current == Entity::null() || self.style.restyle.contains(&self.current) {
709 return;
710 }
711
712 self.style.restyle.insert(self.current);
713 let iter = if let Some(parent) = self.tree.get_layout_parent(self.current) {
714 LayoutTreeIterator::subtree(self.tree, parent)
715 } else {
716 LayoutTreeIterator::subtree(self.tree, self.current)
717 };
718
719 for descendant in iter {
720 self.style.restyle.insert(descendant);
721 }
722 self.style.needs_restyle(self.current);
723 }
724
725 pub fn needs_retransform(&mut self) {
726 self.style.needs_retransform(self.current);
727 let iter = LayoutTreeIterator::subtree(self.tree, self.current);
728 for descendant in iter {
729 self.style.needs_retransform(descendant);
730 }
731 }
732
733 pub fn needs_reclip(&mut self) {
734 self.style.needs_reclip(self.current);
735 let iter = LayoutTreeIterator::subtree(self.tree, self.current);
736 for descendant in iter {
737 self.style.needs_reclip(descendant);
738 }
739 }
740
741 pub fn reload_styles(&mut self) -> Result<(), std::io::Error> {
743 if self.resource_manager.styles.is_empty() {
744 return Ok(());
745 }
746
747 self.style.remove_rules();
748
749 self.style.clear_style_rules();
750
751 let mut overall_theme = String::new();
752
753 for style_string in self.resource_manager.styles.iter().flat_map(|style| style.get_style())
754 {
755 overall_theme += &style_string;
756 }
757
758 self.style.parse_theme(&overall_theme);
759
760 for entity in self.tree.into_iter() {
761 self.style.needs_restyle(entity);
762 self.style.needs_relayout();
763 self.style.needs_text_update(entity);
765 }
766
767 Ok(())
768 }
769
770 pub fn spawn<F>(&self, target: F)
772 where
773 F: 'static + Send + FnOnce(&mut ContextProxy),
774 {
775 let mut cxp = ContextProxy {
776 current: self.current,
777 event_proxy: self.event_proxy.as_ref().map(|p| p.make_clone()),
778 };
779
780 std::thread::spawn(move || target(&mut cxp));
781 }
782
783 pub fn get_proxy(&self) -> ContextProxy {
785 ContextProxy {
786 current: self.current,
787 event_proxy: self.event_proxy.as_ref().map(|p| p.make_clone()),
788 }
789 }
790
791 pub fn modify<V: View>(&mut self, f: impl FnOnce(&mut V)) {
792 if let Some(view) = self
793 .views
794 .get_mut(&self.current)
795 .and_then(|view_handler| view_handler.downcast_mut::<V>())
796 {
797 (f)(view);
798 }
799 }
800
801 pub fn background_color(&mut self) -> Color {
809 self.style.background_color.get(self.current).copied().unwrap_or_default()
810 }
811
812 pub fn set_id(&mut self, id: &str) {
815 self.style.ids.insert(self.current, id.to_string())
816 }
817
818 pub fn set_hover(&mut self, flag: bool) {
830 let current = self.current();
831 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
832 pseudo_classes.set(PseudoClassFlags::HOVER, flag);
833 }
834
835 self.needs_restyle();
836 }
837
838 pub fn set_active(&mut self, active: bool) {
847 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(self.current) {
848 pseudo_classes.set(PseudoClassFlags::ACTIVE, active);
849 }
850
851 self.needs_restyle();
852 }
853
854 pub fn set_read_only(&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::READ_ONLY, flag);
858 }
859
860 self.needs_restyle();
861 }
862
863 pub fn set_read_write(&mut self, flag: bool) {
864 let current = self.current();
865 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
866 pseudo_classes.set(PseudoClassFlags::READ_WRITE, flag);
867 }
868
869 self.needs_restyle();
870 }
871
872 pub fn set_checked(&mut self, flag: bool) {
881 let current = self.current();
882 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
883 pseudo_classes.set(PseudoClassFlags::CHECKED, flag);
884 }
885
886 self.needs_restyle();
887 }
888
889 pub fn set_valid(&mut self, flag: bool) {
898 let current = self.current();
899 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
900 pseudo_classes.set(PseudoClassFlags::VALID, flag);
901 pseudo_classes.set(PseudoClassFlags::INVALID, !flag);
902 }
903
904 self.needs_restyle();
905 }
906
907 pub fn set_placeholder_shown(&mut self, flag: bool) {
908 let current = self.current();
909 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
910 pseudo_classes.set(PseudoClassFlags::PLACEHOLDER_SHOWN, flag);
911 }
912
913 self.needs_restyle();
914 }
915
916 pub fn is_valid(&self) -> bool {
918 self.style
919 .pseudo_classes
920 .get(self.current)
921 .map(|pseudo_classes| pseudo_classes.contains(PseudoClassFlags::VALID))
922 .unwrap_or_default()
923 }
924
925 pub fn is_placeholder_shown(&self) -> bool {
926 self.style
927 .pseudo_classes
928 .get(self.current)
929 .map(|pseudo_classes| pseudo_classes.contains(PseudoClassFlags::PLACEHOLDER_SHOWN))
930 .unwrap_or_default()
931 }
932
933 pub fn set_name(&mut self, name: &str) {
937 self.style.name.insert(self.current, name.to_string());
938 }
939
940 pub fn set_role(&mut self, role: Role) {
942 self.style.role.insert(self.current, role);
943 }
944
945 pub fn set_live(&mut self, live: Live) {
952 self.style.live.insert(self.current, live);
953 }
954
955 pub fn labelled_by(&mut self, id: &str) {
957 self.style.labelled_by.insert(self.current, id.to_string());
958 }
959
960 pub fn described_by(&mut self, id: &str) {
962 self.style.described_by.insert(self.current, id.to_string());
963 }
964
965 pub fn controls(&mut self, id: &str) {
967 self.style.controls.insert(self.current, id.to_string());
968 }
969
970 pub fn set_hidden(&mut self, hidden: bool) {
972 self.style.hidden.insert(self.current, hidden)
973 }
974
975 pub fn text_value(&mut self, text: &str) {
977 self.style.text_value.insert(self.current, text.to_string());
978 }
979
980 pub fn numeric_value(&mut self, value: f64) {
982 self.style.numeric_value.insert(self.current, value);
983 }
984
985 pub fn set_display(&mut self, display: Display) {
991 self.style.display.insert(self.current, display);
992 }
993
994 pub fn set_visibility(&mut self, visibility: Visibility) {
998 self.style.visibility.insert(self.current, visibility);
999 }
1000
1001 pub fn set_opacity(&mut self, opacity: f32) {
1005 self.style.opacity.insert(self.current, Opacity(opacity));
1006 }
1007
1008 pub fn set_z_index(&mut self, z_index: i32) {
1010 self.style.z_index.insert(self.current, z_index);
1011 }
1012
1013 pub fn set_clip_path(&mut self, clip_path: ClipPath) {
1015 self.style.clip_path.insert(self.current, clip_path);
1016 self.needs_reclip();
1017 self.needs_redraw();
1018 }
1019
1020 pub fn set_overflowx(&mut self, overflowx: impl Into<Overflow>) {
1022 self.style.overflowx.insert(self.current, overflowx.into());
1023 self.needs_reclip();
1024 self.needs_redraw();
1025 }
1026
1027 pub fn set_overflowy(&mut self, overflowy: impl Into<Overflow>) {
1029 self.style.overflowy.insert(self.current, overflowy.into());
1030 self.needs_reclip();
1031 self.needs_redraw();
1032 }
1033
1034 pub fn set_transform(&mut self, transform: impl Into<Vec<Transform>>) {
1038 self.style.transform.insert(self.current, transform.into());
1039 self.needs_retransform();
1040 self.needs_redraw();
1041 }
1042
1043 pub fn set_transform_origin(&mut self, transform_origin: Translate) {
1045 self.style.transform_origin.insert(self.current, transform_origin);
1046 self.needs_retransform();
1047 self.needs_redraw();
1048 }
1049
1050 pub fn set_translate(&mut self, translate: impl Into<Translate>) {
1052 self.style.translate.insert(self.current, translate.into());
1053 self.needs_retransform();
1054 self.needs_redraw();
1055 }
1056
1057 pub fn set_rotate(&mut self, angle: impl Into<Angle>) {
1059 self.style.rotate.insert(self.current, angle.into());
1060 self.needs_retransform();
1061 self.needs_redraw();
1062 }
1063
1064 pub fn set_scale(&mut self, scale: impl Into<Scale>) {
1066 self.style.scale.insert(self.current, scale.into());
1067 self.needs_retransform();
1068 self.needs_redraw();
1069 }
1070
1071 pub fn set_filter(&mut self, filter: Filter) {
1075 self.style.filter.insert(self.current, filter);
1076 self.needs_redraw();
1077 }
1078
1079 pub fn set_backdrop_filter(&mut self, filter: Filter) {
1081 self.style.backdrop_filter.insert(self.current, filter);
1082 self.needs_redraw();
1083 }
1084
1085 pub fn set_background_color(&mut self, background_color: Color) {
1092 self.style.background_color.insert(self.current, background_color);
1093 self.needs_redraw();
1094 }
1095
1096 pub fn set_width(&mut self, width: Units) {
1099 self.style.width.insert(self.current, width);
1100 self.needs_relayout();
1101 self.needs_redraw();
1102 }
1103
1104 pub fn set_height(&mut self, height: Units) {
1105 self.style.height.insert(self.current, height);
1106 self.needs_relayout();
1107 self.needs_redraw();
1108 }
1109
1110 pub fn set_max_height(&mut self, height: Units) {
1111 self.style.max_height.insert(self.current, height);
1112 self.needs_relayout();
1113 self.needs_redraw();
1114 }
1115
1116 pub fn set_left(&mut self, left: Units) {
1119 self.style.left.insert(self.current, left);
1120 self.needs_relayout();
1121 self.needs_redraw();
1122 }
1123
1124 pub fn set_top(&mut self, top: Units) {
1125 self.style.top.insert(self.current, top);
1126 self.needs_relayout();
1127 self.needs_redraw();
1128 }
1129
1130 pub fn set_right(&mut self, right: Units) {
1131 self.style.right.insert(self.current, right);
1132 self.needs_relayout();
1133 self.needs_redraw();
1134 }
1135
1136 pub fn set_bottom(&mut self, bottom: Units) {
1137 self.style.bottom.insert(self.current, bottom);
1138 self.needs_relayout();
1139 self.needs_redraw();
1140 }
1141
1142 pub fn set_padding_left(&mut self, padding_left: Units) {
1145 self.style.padding_left.insert(self.current, padding_left);
1146 self.needs_relayout();
1147 self.needs_redraw();
1148 }
1149
1150 pub fn set_padding_top(&mut self, padding_top: Units) {
1151 self.style.padding_top.insert(self.current, padding_top);
1152 self.needs_relayout();
1153 self.needs_redraw();
1154 }
1155
1156 pub fn set_padding_right(&mut self, padding_right: Units) {
1157 self.style.padding_right.insert(self.current, padding_right);
1158 self.needs_relayout();
1159 self.needs_redraw();
1160 }
1161
1162 pub fn set_padding_bottom(&mut self, padding_bottom: Units) {
1163 self.style.padding_bottom.insert(self.current, padding_bottom);
1164 self.needs_relayout();
1165 self.needs_redraw();
1166 }
1167
1168 pub fn set_text(&mut self, text: &str) {
1172 self.style.text.insert(self.current, text.to_owned());
1173 self.style.needs_text_update(self.current);
1174 self.needs_relayout();
1175 self.needs_redraw();
1176 }
1177
1178 pub fn set_pointer_events(&mut self, pointer_events: impl Into<PointerEvents>) {
1179 self.style.pointer_events.insert(self.current, pointer_events.into());
1180 }
1181
1182 get_length_property!(
1184 border_width
1186 );
1187
1188 pub fn font_size(&self) -> f32 {
1190 self.logical_to_physical(
1191 self.style
1192 .font_size
1193 .get(self.current)
1194 .cloned()
1195 .map(|f| f.0.to_px().unwrap())
1196 .unwrap_or(16.0),
1197 )
1198 }
1199
1200 pub fn add_timer(
1231 &mut self,
1232 interval: Duration,
1233 duration: Option<Duration>,
1234 callback: impl Fn(&mut EventContext, TimerAction) + 'static,
1235 ) -> Timer {
1236 let id = Timer(self.timers.len());
1237 self.timers.push(TimerState {
1238 entity: Entity::root(),
1239 id,
1240 time: Instant::now(),
1241 interval,
1242 duration,
1243 start_time: Instant::now(),
1244 callback: Rc::new(callback),
1245 ticking: false,
1246 stopping: false,
1247 });
1248
1249 id
1250 }
1251
1252 pub fn start_timer(&mut self, timer: Timer) {
1256 let current = self.current;
1257 if !self.timer_is_running(timer) {
1258 let timer_state = self.timers[timer.0].clone();
1259 self.running_timers.push(timer_state);
1261 }
1262
1263 self.modify_timer(timer, |timer_state| {
1264 let now = Instant::now();
1265 timer_state.start_time = now;
1266 timer_state.time = now;
1267 timer_state.entity = current;
1268 timer_state.ticking = false;
1269 timer_state.stopping = false;
1270 });
1271 }
1272
1273 pub fn modify_timer(&mut self, timer: Timer, timer_function: impl Fn(&mut TimerState)) {
1275 while let Some(next_timer_state) = self.running_timers.peek() {
1276 if next_timer_state.id == timer {
1277 let mut timer_state = self.running_timers.pop().unwrap();
1278
1279 (timer_function)(&mut timer_state);
1280
1281 self.running_timers.push(timer_state);
1282
1283 return;
1284 }
1285 }
1286
1287 for pending_timer in self.timers.iter_mut() {
1288 if pending_timer.id == timer {
1289 (timer_function)(pending_timer);
1290 }
1291 }
1292 }
1293
1294 pub fn query_timer<T>(
1295 &mut self,
1296 timer: Timer,
1297 timer_function: impl Fn(&TimerState) -> T,
1298 ) -> Option<T> {
1299 while let Some(next_timer_state) = self.running_timers.peek() {
1300 if next_timer_state.id == timer {
1301 let timer_state = self.running_timers.pop().unwrap();
1302
1303 let t = (timer_function)(&timer_state);
1304
1305 self.running_timers.push(timer_state);
1306
1307 return Some(t);
1308 }
1309 }
1310
1311 for pending_timer in self.timers.iter() {
1312 if pending_timer.id == timer {
1313 return Some(timer_function(pending_timer));
1314 }
1315 }
1316
1317 None
1318 }
1319
1320 pub fn timer_is_running(&mut self, timer: Timer) -> bool {
1322 for timer_state in self.running_timers.iter() {
1323 if timer_state.id == timer {
1324 return true;
1325 }
1326 }
1327
1328 false
1329 }
1330
1331 pub fn stop_timer(&mut self, timer: Timer) {
1335 let mut running_timers = self.running_timers.clone();
1336
1337 for timer_state in running_timers.iter() {
1338 if timer_state.id == timer {
1339 self.with_current(timer_state.entity, |cx| {
1340 (timer_state.callback)(cx, TimerAction::Stop);
1341 });
1342 }
1343 }
1344
1345 *self.running_timers =
1346 running_timers.drain().filter(|timer_state| timer_state.id != timer).collect();
1347 }
1348}
1349
1350impl DataContext for EventContext<'_> {
1351 fn try_data<T: 'static>(&self) -> Option<&T> {
1352 if let Some(t) = <dyn Any>::downcast_ref::<T>(&()) {
1354 return Some(t);
1355 }
1356
1357 for entity in self.current.parent_iter(self.tree) {
1358 if let Some(models) = self.models.get(&entity) {
1360 if let Some(model) = models.get(&TypeId::of::<T>()) {
1361 return model.downcast_ref::<T>();
1362 }
1363 }
1364
1365 if let Some(view_handler) = self.views.get(&entity) {
1367 if let Some(data) = view_handler.downcast_ref::<T>() {
1368 return Some(data);
1369 }
1370 }
1371 }
1372
1373 None
1374 }
1375
1376 fn localization_context(&self) -> Option<LocalizationContext<'_>> {
1377 Some(LocalizationContext::from_event_context(self))
1378 }
1379}
1380
1381impl EmitContext for EventContext<'_> {
1382 fn emit<M: Any + Send>(&mut self, message: M) {
1383 self.event_queue.push_back(
1384 Event::new(message)
1385 .target(self.current)
1386 .origin(self.current)
1387 .propagate(Propagation::Up),
1388 );
1389 }
1390
1391 fn emit_to<M: Any + Send>(&mut self, target: Entity, message: M) {
1392 self.event_queue.push_back(
1393 Event::new(message).target(target).origin(self.current).propagate(Propagation::Direct),
1394 );
1395 }
1396
1397 fn emit_custom(&mut self, event: Event) {
1398 self.event_queue.push_back(event);
1399 }
1400
1401 fn schedule_emit<M: Any + Send>(&mut self, message: M, at: Instant) -> TimedEventHandle {
1402 self.schedule_emit_custom(
1403 Event::new(message)
1404 .target(self.current)
1405 .origin(self.current)
1406 .propagate(Propagation::Up),
1407 at,
1408 )
1409 }
1410 fn schedule_emit_to<M: Any + Send>(
1411 &mut self,
1412 target: Entity,
1413 message: M,
1414 at: Instant,
1415 ) -> TimedEventHandle {
1416 self.schedule_emit_custom(
1417 Event::new(message).target(target).origin(self.current).propagate(Propagation::Direct),
1418 at,
1419 )
1420 }
1421 fn schedule_emit_custom(&mut self, event: Event, at: Instant) -> TimedEventHandle {
1422 let handle = TimedEventHandle(*self.next_event_id);
1423 self.event_schedule.push(TimedEvent { event, time: at, ident: handle });
1424 *self.next_event_id += 1;
1425 handle
1426 }
1427 fn cancel_scheduled(&mut self, handle: TimedEventHandle) {
1428 *self.event_schedule =
1429 self.event_schedule.drain().filter(|item| item.ident != handle).collect();
1430 }
1431}
1432
1433pub trait TreeProps {
1435 fn parent(&self) -> Entity;
1437 fn first_child(&self) -> Entity;
1439 fn parent_window(&self) -> Entity;
1441}
1442
1443impl TreeProps for EventContext<'_> {
1444 fn parent(&self) -> Entity {
1445 self.tree.get_layout_parent(self.current).unwrap()
1446 }
1447
1448 fn first_child(&self) -> Entity {
1449 self.tree.get_layout_first_child(self.current).unwrap()
1450 }
1451
1452 fn parent_window(&self) -> Entity {
1453 self.tree.get_parent_window(self.current).unwrap_or(Entity::root())
1454 }
1455}