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::{DARK_THEME, LIGHT_THEME, 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) ignore_default_theme: &'a bool,
90 pub(crate) drop_data: &'a mut Option<DropData>,
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 ignore_default_theme: &cx.ignore_default_theme,
143 drop_data: &mut cx.drop_data,
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 ignore_default_theme: &cx.ignore_default_theme,
177 drop_data: &mut cx.drop_data,
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 bounds(&self) -> BoundingBox {
270 self.cache.get_bounds(self.current)
271 }
272
273 pub fn scale_factor(&self) -> f32 {
279 self.style.dpi_factor as f32
280 }
281
282 pub fn logical_to_physical(&self, logical: f32) -> f32 {
284 self.style.logical_to_physical(logical)
285 }
286
287 pub fn physical_to_logical(&self, physical: f32) -> f32 {
289 self.style.physical_to_logical(physical)
290 }
291
292 pub fn clip_region(&self) -> BoundingBox {
294 self.cache
295 .clip_path
296 .get(self.current)
297 .cloned()
298 .flatten()
299 .map(|clip_path| Into::<BoundingBox>::into(*clip_path.bounds()))
300 .or_else(|| {
301 let mut current = self.current;
302 while let Some(parent) = self.tree.get_parent(current) {
303 if let Some(clip_path) = self
304 .cache
305 .clip_path
306 .get(parent)
307 .cloned()
308 .flatten()
309 .map(|clip_path| Into::<BoundingBox>::into(*clip_path.bounds()))
310 {
311 return Some(clip_path);
312 }
313 current = parent;
314 }
315 None
316 })
317 .unwrap_or_else(|| {
318 let parent_window =
319 self.tree.get_parent_window(self.current).unwrap_or(Entity::root());
320 self.cache.get_bounds(parent_window)
321 })
322 }
323
324 pub fn transform(&self) -> Matrix {
326 self.cache.transform.get(self.current).copied().unwrap_or_default()
327 }
328
329 pub fn play_animation(&mut self, anim_id: impl AnimId, duration: Duration, delay: Duration) {
331 if let Some(animation_id) = anim_id.get(self) {
332 self.style.enqueue_animation(self.current, animation_id, duration, delay);
333 }
334 }
335
336 pub fn play_animation_for(
338 &mut self,
339 anim_id: impl AnimId,
340 target: &str,
341 duration: Duration,
342 delay: Duration,
343 ) {
344 if let Some(target_entity) = self.resolve_entity_identifier(target) {
345 if let Some(animation_id) = anim_id.get(self) {
346 self.style.enqueue_animation(target_entity, animation_id, duration, delay)
347 }
348 }
349 }
350
351 pub fn is_animating(&self, anim_id: impl AnimId) -> bool {
353 if let Some(animation_id) = anim_id.get(self) {
354 return self.style.is_animating(self.current, animation_id);
355 }
356
357 false
358 }
359
360 pub fn add_listener<F, W>(&mut self, listener: F)
366 where
367 W: View,
368 F: 'static + Fn(&mut W, &mut EventContext, &mut Event),
369 {
370 self.listeners.insert(
371 self.current,
372 Box::new(move |event_handler, context, event| {
373 if let Some(widget) = event_handler.downcast_mut::<W>() {
374 (listener)(widget, context, event);
375 }
376 }),
377 );
378 }
379
380 pub fn set_language(&mut self, lang: LanguageIdentifier) {
382 if let Some(mut models) = self.models.remove(&Entity::root()) {
383 if let Some(model) = models.get_mut(&TypeId::of::<Environment>()) {
384 model.event(self, &mut Event::new(EnvironmentEvent::SetLocale(lang)));
385 }
386
387 self.models.insert(Entity::root(), models);
388 }
389 }
390
391 pub fn add_image_encoded(&mut self, path: &str, data: &[u8], policy: ImageRetentionPolicy) {
392 let id = if let Some(image_id) = self.resource_manager.image_ids.get(path) {
393 *image_id
394 } else {
395 let id = self.resource_manager.image_id_manager.create();
396 self.resource_manager.image_ids.insert(path.to_owned(), id);
397 id
398 };
399
400 if let Some(image) = skia_safe::Image::from_encoded(skia_safe::Data::new_copy(data)) {
401 match self.resource_manager.images.entry(id) {
402 Entry::Occupied(mut occ) => {
403 occ.get_mut().image = ImageOrSvg::Image(image);
404 occ.get_mut().dirty = true;
405 occ.get_mut().retention_policy = policy;
406 }
407 Entry::Vacant(vac) => {
408 vac.insert(StoredImage {
409 image: ImageOrSvg::Image(image),
410 retention_policy: policy,
411 used: true,
412 dirty: false,
413 observers: HashSet::new(),
414 });
415 }
416 }
417 self.style.needs_relayout();
418 }
419 }
420
421 pub fn capture(&mut self) {
423 *self.captured = self.current;
424 }
425
426 pub fn release(&mut self) {
428 if self.current == *self.captured {
429 *self.captured = Entity::null();
430 }
431 }
432
433 fn set_focus_pseudo_classes(&mut self, focused: Entity, enabled: bool, focus_visible: bool) {
435 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(focused) {
436 pseudo_classes.set(PseudoClassFlags::FOCUS, enabled);
437 if !enabled || focus_visible {
438 pseudo_classes.set(PseudoClassFlags::FOCUS_VISIBLE, enabled);
439 }
440 }
441
442 for ancestor in focused.parent_iter(self.tree) {
443 let entity = ancestor;
444 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(entity) {
445 pseudo_classes.set(PseudoClassFlags::FOCUS_WITHIN, enabled);
446 }
447 }
448 }
449
450 pub fn focus_with_visibility(&mut self, focus_visible: bool) {
452 let old_focus = self.focused();
453 let new_focus = self.current();
454 self.set_focus_pseudo_classes(old_focus, false, focus_visible);
455 if self.current() != self.focused() {
456 self.emit_to(old_focus, WindowEvent::FocusOut);
457 self.emit_to(new_focus, WindowEvent::FocusIn);
458 *self.focused = self.current();
459 }
460 self.set_focus_pseudo_classes(new_focus, true, focus_visible);
461
462 self.emit_custom(Event::new(WindowEvent::FocusVisibility(focus_visible)).target(old_focus));
463 self.emit_custom(Event::new(WindowEvent::FocusVisibility(focus_visible)).target(new_focus));
464
465 self.needs_restyle();
466 }
467
468 pub fn focus(&mut self) {
472 let focused = self.focused();
473 let old_focus_visible = self
474 .style
475 .pseudo_classes
476 .get_mut(focused)
477 .filter(|class| class.contains(PseudoClassFlags::FOCUS_VISIBLE))
478 .is_some();
479 self.focus_with_visibility(old_focus_visible)
480 }
481
482 pub fn focus_next(&mut self) {
484 let lock_focus_to = self.tree.lock_focus_within(*self.focused);
485 let next_focused = if let Some(next_focused) =
486 focus_forward(self.tree, self.style, *self.focused, lock_focus_to)
487 {
488 next_focused
489 } else {
490 TreeIterator::full(self.tree)
491 .find(|node| is_navigatable(self.tree, self.style, *node, lock_focus_to))
492 .unwrap_or(Entity::root())
493 };
494
495 if next_focused != *self.focused {
496 self.event_queue.push_back(
497 Event::new(WindowEvent::FocusOut).target(*self.focused).origin(Entity::root()),
498 );
499 self.event_queue.push_back(
500 Event::new(WindowEvent::FocusIn).target(next_focused).origin(Entity::root()),
501 );
502
503 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(*self.triggered) {
504 pseudo_classes.set(PseudoClassFlags::ACTIVE, false);
505 }
506 self.needs_restyle();
507 *self.triggered = Entity::null();
508 }
509 }
510
511 pub fn focus_prev(&mut self) {
513 let lock_focus_to = self.tree.lock_focus_within(*self.focused);
514 let prev_focused = if let Some(prev_focused) =
515 focus_backward(self.tree, self.style, *self.focused, lock_focus_to)
516 {
517 prev_focused
518 } else {
519 TreeIterator::full(self.tree)
520 .rfind(|node| is_navigatable(self.tree, self.style, *node, lock_focus_to))
521 .unwrap_or(Entity::root())
522 };
523
524 if prev_focused != *self.focused {
525 self.event_queue.push_back(
526 Event::new(WindowEvent::FocusOut).target(*self.focused).origin(Entity::root()),
527 );
528 self.event_queue.push_back(
529 Event::new(WindowEvent::FocusIn).target(prev_focused).origin(Entity::root()),
530 );
531
532 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(*self.triggered) {
533 pseudo_classes.set(PseudoClassFlags::ACTIVE, false);
534 }
535 self.needs_restyle();
536 *self.triggered = Entity::null();
537 }
538 }
539
540 pub fn hovered(&self) -> Entity {
542 *self.hovered
543 }
544
545 pub fn focused(&self) -> Entity {
547 *self.focused
548 }
549
550 pub fn is_hovered(&self) -> bool {
554 self.hovered() == self.current
555 }
556
557 pub fn is_active(&self) -> bool {
559 if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
560 pseudo_classes.contains(PseudoClassFlags::ACTIVE)
561 } else {
562 false
563 }
564 }
565
566 pub fn is_over(&self) -> bool {
568 if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
569 pseudo_classes.contains(PseudoClassFlags::OVER)
570 } else {
571 false
572 }
573 }
574
575 pub fn is_focused(&self) -> bool {
577 self.focused() == self.current
578 }
579
580 pub fn is_draggable(&self) -> bool {
582 self.style
583 .abilities
584 .get(self.current)
585 .map(|abilities| abilities.contains(Abilities::DRAGGABLE))
586 .unwrap_or_default()
587 }
588
589 pub fn is_disabled(&self) -> bool {
591 self.style.disabled.get(self.current()).cloned().unwrap_or_default()
592 }
593
594 pub fn is_checked(&self) -> bool {
596 if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
597 pseudo_classes.contains(PseudoClassFlags::CHECKED)
598 } else {
599 false
600 }
601 }
602
603 pub fn is_read_only(&self) -> bool {
605 if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
606 pseudo_classes.contains(PseudoClassFlags::READ_ONLY)
607 } else {
608 false
609 }
610 }
611
612 pub fn lock_cursor_icon(&mut self) {
616 *self.cursor_icon_locked = true;
617 }
618
619 pub fn unlock_cursor_icon(&mut self) {
621 *self.cursor_icon_locked = false;
622 let hovered = *self.hovered;
623 let cursor = self.style.cursor.get(hovered).cloned().unwrap_or_default();
624 self.emit(WindowEvent::SetCursor(cursor));
625 }
626
627 pub fn is_cursor_icon_locked(&self) -> bool {
629 *self.cursor_icon_locked
630 }
631
632 pub fn set_drop_data(&mut self, data: impl Into<DropData>) {
634 *self.drop_data = Some(data.into())
635 }
636
637 #[cfg(feature = "clipboard")]
641 pub fn get_clipboard(&mut self) -> Result<String, Box<dyn Error + Send + Sync + 'static>> {
642 self.clipboard.get_contents()
643 }
644
645 #[cfg(feature = "clipboard")]
649 pub fn set_clipboard(
650 &mut self,
651 text: String,
652 ) -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
653 self.clipboard.set_contents(text)
654 }
655
656 pub fn toggle_class(&mut self, class_name: &str, applied: bool) {
666 let current = self.current();
667 if let Some(class_list) = self.style.classes.get_mut(current) {
668 if applied {
669 class_list.insert(class_name.to_string());
670 } else {
671 class_list.remove(class_name);
672 }
673 } else if applied {
674 let mut class_list = HashSet::new();
675 class_list.insert(class_name.to_string());
676 self.style.classes.insert(current, class_list);
677 }
678
679 self.needs_restyle();
680 }
681
682 pub fn environment(&self) -> &Environment {
684 self.data::<Environment>().unwrap()
685 }
686
687 pub fn set_theme_mode(&mut self, theme_mode: ThemeMode) {
689 if !self.ignore_default_theme {
690 match theme_mode {
691 ThemeMode::LightMode => {
692 self.resource_manager.themes[2] = String::from(LIGHT_THEME);
693 }
694
695 ThemeMode::DarkMode => {
696 self.resource_manager.themes[2] = String::from(DARK_THEME);
697 }
698 }
699 }
700 }
701
702 pub fn needs_redraw(&mut self) {
704 let parent_window = self.tree.get_parent_window(self.current).unwrap_or(Entity::root());
705 if let Some(window_state) = self.windows.get_mut(&parent_window) {
706 window_state.redraw_list.insert(self.current);
707 }
708 }
709
710 pub fn needs_relayout(&mut self) {
712 self.style.needs_relayout();
713 self.needs_redraw();
714 }
715
716 pub fn needs_restyle(&mut self) {
718 if self.current == Entity::null() || self.style.restyle.contains(&self.current) {
719 return;
720 }
721
722 self.style.restyle.insert(self.current);
723 let iter = if let Some(parent) = self.tree.get_layout_parent(self.current) {
724 LayoutTreeIterator::subtree(self.tree, parent)
725 } else {
726 LayoutTreeIterator::subtree(self.tree, self.current)
727 };
728
729 for descendant in iter {
730 self.style.restyle.insert(descendant);
731 }
732 self.style.needs_restyle(self.current);
733 }
734
735 pub fn needs_retransform(&mut self) {
736 self.style.needs_retransform(self.current);
737 let iter = LayoutTreeIterator::subtree(self.tree, self.current);
738 for descendant in iter {
739 self.style.needs_retransform(descendant);
740 }
741 }
742
743 pub fn needs_reclip(&mut self) {
744 self.style.needs_reclip(self.current);
745 let iter = LayoutTreeIterator::subtree(self.tree, self.current);
746 for descendant in iter {
747 self.style.needs_reclip(descendant);
748 }
749 }
750
751 pub fn reload_styles(&mut self) -> Result<(), std::io::Error> {
753 if self.resource_manager.themes.is_empty() && self.resource_manager.styles.is_empty() {
754 return Ok(());
755 }
756
757 self.style.remove_rules();
758
759 self.style.clear_style_rules();
760
761 let mut overall_theme = String::new();
762
763 for theme in self.resource_manager.themes.iter() {
765 overall_theme += theme;
766 }
767
768 for style_string in self.resource_manager.styles.iter().flat_map(|style| style.get_style())
769 {
770 overall_theme += &style_string;
771 }
772
773 self.style.parse_theme(&overall_theme);
774
775 for entity in self.tree.into_iter() {
776 self.style.needs_restyle(entity);
777 self.style.needs_relayout();
778 self.style.needs_text_update(entity);
780 }
781
782 Ok(())
783 }
784
785 pub fn spawn<F>(&self, target: F)
787 where
788 F: 'static + Send + FnOnce(&mut ContextProxy),
789 {
790 let mut cxp = ContextProxy {
791 current: self.current,
792 event_proxy: self.event_proxy.as_ref().map(|p| p.make_clone()),
793 };
794
795 std::thread::spawn(move || target(&mut cxp));
796 }
797
798 pub fn get_proxy(&self) -> ContextProxy {
800 ContextProxy {
801 current: self.current,
802 event_proxy: self.event_proxy.as_ref().map(|p| p.make_clone()),
803 }
804 }
805
806 pub fn modify<V: View>(&mut self, f: impl FnOnce(&mut V)) {
807 if let Some(view) = self
808 .views
809 .get_mut(&self.current)
810 .and_then(|view_handler| view_handler.downcast_mut::<V>())
811 {
812 (f)(view);
813 }
814 }
815
816 pub fn background_color(&mut self) -> Color {
824 self.style.background_color.get(self.current).copied().unwrap_or_default()
825 }
826
827 pub fn set_id(&mut self, id: &str) {
830 self.style.ids.insert(self.current, id.to_string())
831 }
832
833 pub fn set_hover(&mut self, flag: bool) {
845 let current = self.current();
846 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
847 pseudo_classes.set(PseudoClassFlags::HOVER, flag);
848 }
849
850 self.needs_restyle();
851 }
852
853 pub fn set_active(&mut self, active: bool) {
862 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(self.current) {
863 pseudo_classes.set(PseudoClassFlags::ACTIVE, active);
864 }
865
866 self.needs_restyle();
867 }
868
869 pub fn set_read_only(&mut self, flag: bool) {
870 let current = self.current();
871 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
872 pseudo_classes.set(PseudoClassFlags::READ_ONLY, flag);
873 }
874
875 self.needs_restyle();
876 }
877
878 pub fn set_read_write(&mut self, flag: bool) {
879 let current = self.current();
880 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
881 pseudo_classes.set(PseudoClassFlags::READ_WRITE, flag);
882 }
883
884 self.needs_restyle();
885 }
886
887 pub fn set_checked(&mut self, flag: bool) {
896 let current = self.current();
897 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
898 pseudo_classes.set(PseudoClassFlags::CHECKED, flag);
899 }
900
901 self.needs_restyle();
902 }
903
904 pub fn set_valid(&mut self, flag: bool) {
913 let current = self.current();
914 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
915 pseudo_classes.set(PseudoClassFlags::VALID, flag);
916 pseudo_classes.set(PseudoClassFlags::INVALID, !flag);
917 }
918
919 self.needs_restyle();
920 }
921
922 pub fn set_placeholder_shown(&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::PLACEHOLDER_SHOWN, flag);
926 }
927
928 self.needs_restyle();
929 }
930
931 pub fn is_valid(&self) -> bool {
933 self.style
934 .pseudo_classes
935 .get(self.current)
936 .map(|pseudo_classes| pseudo_classes.contains(PseudoClassFlags::VALID))
937 .unwrap_or_default()
938 }
939
940 pub fn is_placeholder_shown(&self) -> bool {
941 self.style
942 .pseudo_classes
943 .get(self.current)
944 .map(|pseudo_classes| pseudo_classes.contains(PseudoClassFlags::PLACEHOLDER_SHOWN))
945 .unwrap_or_default()
946 }
947
948 pub fn set_name(&mut self, name: &str) {
952 self.style.name.insert(self.current, name.to_string());
953 }
954
955 pub fn set_role(&mut self, role: Role) {
957 self.style.role.insert(self.current, role);
958 }
959
960 pub fn set_live(&mut self, live: Live) {
967 self.style.live.insert(self.current, live);
968 }
969
970 pub fn labelled_by(&mut self, id: &str) {
972 if let Some(entity) = self.resolve_entity_identifier(id) {
973 self.style.labelled_by.insert(self.current, entity);
974 }
975 }
976
977 pub fn set_hidden(&mut self, hidden: bool) {
979 self.style.hidden.insert(self.current, hidden)
980 }
981
982 pub fn text_value(&mut self, text: &str) {
984 self.style.text_value.insert(self.current, text.to_string());
985 }
986
987 pub fn numeric_value(&mut self, value: f64) {
989 self.style.numeric_value.insert(self.current, value);
990 }
991
992 pub fn set_display(&mut self, display: Display) {
998 self.style.display.insert(self.current, display);
999 }
1000
1001 pub fn set_visibility(&mut self, visibility: Visibility) {
1005 self.style.visibility.insert(self.current, visibility);
1006 }
1007
1008 pub fn set_opacity(&mut self, opacity: f32) {
1012 self.style.opacity.insert(self.current, Opacity(opacity));
1013 }
1014
1015 pub fn set_z_index(&mut self, z_index: i32) {
1017 self.style.z_index.insert(self.current, z_index);
1018 }
1019
1020 pub fn set_clip_path(&mut self, clip_path: ClipPath) {
1022 self.style.clip_path.insert(self.current, clip_path);
1023 self.needs_reclip();
1024 self.needs_redraw();
1025 }
1026
1027 pub fn set_overflowx(&mut self, overflowx: impl Into<Overflow>) {
1029 self.style.overflowx.insert(self.current, overflowx.into());
1030 self.needs_reclip();
1031 self.needs_redraw();
1032 }
1033
1034 pub fn set_overflowy(&mut self, overflowy: impl Into<Overflow>) {
1036 self.style.overflowy.insert(self.current, overflowy.into());
1037 self.needs_reclip();
1038 self.needs_redraw();
1039 }
1040
1041 pub fn set_transform(&mut self, transform: impl Into<Vec<Transform>>) {
1045 self.style.transform.insert(self.current, transform.into());
1046 self.needs_retransform();
1047 self.needs_redraw();
1048 }
1049
1050 pub fn set_transform_origin(&mut self, transform_origin: Translate) {
1052 self.style.transform_origin.insert(self.current, transform_origin);
1053 self.needs_retransform();
1054 self.needs_redraw();
1055 }
1056
1057 pub fn set_translate(&mut self, translate: impl Into<Translate>) {
1059 self.style.translate.insert(self.current, translate.into());
1060 self.needs_retransform();
1061 self.needs_redraw();
1062 }
1063
1064 pub fn set_rotate(&mut self, angle: impl Into<Angle>) {
1066 self.style.rotate.insert(self.current, angle.into());
1067 self.needs_retransform();
1068 self.needs_redraw();
1069 }
1070
1071 pub fn set_scale(&mut self, scale: impl Into<Scale>) {
1073 self.style.scale.insert(self.current, scale.into());
1074 self.needs_retransform();
1075 self.needs_redraw();
1076 }
1077
1078 pub fn set_backdrop_filter(&mut self, filter: Filter) {
1082 self.style.backdrop_filter.insert(self.current, filter);
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 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}