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::{HashMap, HashSet};
8use vizia_storage::{LayoutTreeIterator, TreeIterator};
9
10use crate::animation::{AnimId, Interpolator};
11use crate::cache::CachedData;
12use crate::events::{TimedEvent, TimedEventHandle, TimerState, ViewHandler};
13use crate::prelude::*;
14use crate::resource::ResourceManager;
15use crate::tree::{focus_backward, focus_forward, is_navigatable};
16use vizia_input::MouseState;
17
18use skia_safe::Matrix;
19
20use crate::text::TextContext;
21#[cfg(feature = "clipboard")]
22use copypasta::ClipboardProvider;
23
24use super::{LocalizationContext, ModelData, DARK_THEME, LIGHT_THEME};
25
26type Views = HashMap<Entity, Box<dyn ViewHandler>>;
27type Models = HashMap<Entity, HashMap<TypeId, Box<dyn ModelData>>>;
28
29pub struct EventContext<'a> {
62 pub(crate) current: Entity,
63 pub(crate) captured: &'a mut Entity,
64 pub(crate) focused: &'a mut Entity,
65 pub(crate) hovered: &'a Entity,
66 pub(crate) triggered: &'a mut Entity,
67 pub(crate) style: &'a mut Style,
68 pub(crate) entity_identifiers: &'a HashMap<String, Entity>,
69 pub cache: &'a mut CachedData,
70 pub(crate) tree: &'a Tree<Entity>,
71 pub(crate) models: &'a mut Models,
72 pub(crate) views: &'a mut Views,
73 pub(crate) listeners:
74 &'a mut HashMap<Entity, Box<dyn Fn(&mut dyn ViewHandler, &mut EventContext, &mut Event)>>,
75 pub(crate) resource_manager: &'a mut ResourceManager,
76 pub(crate) text_context: &'a mut TextContext,
77 pub(crate) modifiers: &'a Modifiers,
78 pub(crate) mouse: &'a MouseState<Entity>,
79 pub(crate) event_queue: &'a mut VecDeque<Event>,
80 pub(crate) event_schedule: &'a mut BinaryHeap<TimedEvent>,
81 pub(crate) next_event_id: &'a mut usize,
82 pub(crate) timers: &'a mut Vec<TimerState>,
83 pub(crate) running_timers: &'a mut BinaryHeap<TimerState>,
84 cursor_icon_locked: &'a mut bool,
85 #[cfg(feature = "clipboard")]
86 clipboard: &'a mut Box<dyn ClipboardProvider>,
87 pub(crate) event_proxy: &'a mut Option<Box<dyn crate::context::EventProxy>>,
88 pub(crate) ignore_default_theme: &'a bool,
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 ignore_default_theme: &cx.ignore_default_theme,
142 drop_data: &mut cx.drop_data,
143 windows: &mut cx.windows,
144 }
145 }
146
147 pub fn new_with_current(cx: &'a mut Context, current: Entity) -> Self {
149 Self {
150 current,
151 captured: &mut cx.captured,
152 focused: &mut cx.focused,
153 hovered: &cx.hovered,
154 triggered: &mut cx.triggered,
155 entity_identifiers: &cx.entity_identifiers,
156 style: &mut cx.style,
157 cache: &mut cx.cache,
158 tree: &cx.tree,
159 models: &mut cx.models,
160 views: &mut cx.views,
161 listeners: &mut cx.listeners,
162 resource_manager: &mut cx.resource_manager,
163 text_context: &mut cx.text_context,
164 modifiers: &cx.modifiers,
165 mouse: &cx.mouse,
166 event_queue: &mut cx.event_queue,
167 event_schedule: &mut cx.event_schedule,
168 next_event_id: &mut cx.next_event_id,
169 timers: &mut cx.timers,
170 running_timers: &mut cx.running_timers,
171 cursor_icon_locked: &mut cx.cursor_icon_locked,
172 #[cfg(feature = "clipboard")]
173 clipboard: &mut cx.clipboard,
174 event_proxy: &mut cx.event_proxy,
175 ignore_default_theme: &cx.ignore_default_theme,
176 drop_data: &mut cx.drop_data,
177 windows: &mut cx.windows,
178 }
179 }
180
181 pub fn get_view<V: View>(&self) -> Option<&V> {
183 self.views.get(&self.current).and_then(|view| view.downcast_ref::<V>())
184 }
185
186 pub fn get_view_with<V: View>(&self, entity: Entity) -> Option<&V> {
188 self.views.get(&entity).and_then(|view| view.downcast_ref::<V>())
189 }
190
191 pub fn close_window(&mut self) {
192 if let Some(state) = self.windows.get_mut(&self.current) {
193 state.should_close = true;
194 }
195 }
196
197 pub fn resolve_entity_identifier(&self, id: &str) -> Option<Entity> {
199 self.entity_identifiers.get(id).cloned()
200 }
201
202 pub fn current(&self) -> Entity {
204 self.current
205 }
206
207 pub fn modifiers(&self) -> &Modifiers {
209 self.modifiers
210 }
211
212 pub fn mouse(&self) -> &MouseState<Entity> {
214 self.mouse
215 }
216
217 pub fn nth_child(&self, n: usize) -> Option<Entity> {
218 self.tree.get_child(self.current, n)
219 }
220
221 pub fn last_child(&self) -> Option<Entity> {
222 self.tree.get_last_child(self.current).copied()
223 }
224
225 pub fn with_current<T>(&mut self, entity: Entity, f: impl FnOnce(&mut Self) -> T) -> T {
226 let prev = self.current();
227 self.current = entity;
228 let ret = (f)(self);
229 self.current = prev;
230 ret
231 }
232
233 pub fn has_drop_data(&self) -> bool {
235 self.drop_data.is_some()
236 }
237
238 pub fn bounds(&self) -> BoundingBox {
240 self.cache.get_bounds(self.current)
241 }
242
243 pub fn scale_factor(&self) -> f32 {
249 self.style.dpi_factor as f32
250 }
251
252 pub fn logical_to_physical(&self, logical: f32) -> f32 {
254 self.style.logical_to_physical(logical)
255 }
256
257 pub fn physical_to_logical(&self, physical: f32) -> f32 {
259 self.style.physical_to_logical(physical)
260 }
261
262 pub fn clip_region(&self) -> BoundingBox {
264 let bounds = self.bounds();
265 let overflowx = self.style.overflowx.get(self.current).copied().unwrap_or_default();
266 let overflowy = self.style.overflowy.get(self.current).copied().unwrap_or_default();
267
268 let scale = self.scale_factor();
271
272 let clip_bounds = self
273 .style
274 .clip_path
275 .get(self.current)
276 .map(|clip| match clip {
277 ClipPath::Auto => bounds,
278 ClipPath::Shape(rect) => bounds.shrink_sides(
279 rect.3.to_pixels(bounds.w, scale),
280 rect.0.to_pixels(bounds.h, scale),
281 rect.1.to_pixels(bounds.w, scale),
282 rect.2.to_pixels(bounds.h, scale),
283 ),
284 })
285 .unwrap_or(bounds);
286
287 let root_bounds: BoundingBox =
288 BoundingBox { x: -f32::MAX / 2.0, y: -f32::MAX / 2.0, w: f32::MAX, h: f32::MAX };
289
290 match (overflowx, overflowy) {
291 (Overflow::Visible, Overflow::Visible) => root_bounds,
292 (Overflow::Hidden, Overflow::Visible) => {
293 let left = clip_bounds.left();
294 let right = clip_bounds.right();
295 let top = root_bounds.top();
296 let bottom = root_bounds.bottom();
297 BoundingBox::from_min_max(left, top, right, bottom)
298 }
299 (Overflow::Visible, Overflow::Hidden) => {
300 let left = root_bounds.left();
301 let right = root_bounds.right();
302 let top = clip_bounds.top();
303 let bottom = clip_bounds.bottom();
304 BoundingBox::from_min_max(left, top, right, bottom)
305 }
306 (Overflow::Hidden, Overflow::Hidden) => clip_bounds,
307 }
308 }
309
310 pub fn transform(&self) -> Matrix {
312 let bounds = self.bounds();
313 let scale_factor = self.scale_factor();
314
315 let mut origin = self
317 .style
318 .transform_origin
319 .get(self.current)
320 .map(|transform_origin| {
321 let mut origin = Matrix::translate(bounds.top_left());
322 let offset = transform_origin.as_transform(bounds, scale_factor);
323 origin = offset * origin;
324 origin
325 })
326 .unwrap_or(Matrix::translate(bounds.center()));
327 let mut transform = origin;
329 origin = origin.invert().unwrap();
330
331 if let Some(translate) = self.style.translate.get(self.current) {
333 transform = transform * translate.as_transform(bounds, scale_factor);
334 }
335
336 if let Some(rotate) = self.style.rotate.get(self.current) {
338 transform = transform * rotate.as_transform(bounds, scale_factor);
339 }
340
341 if let Some(scale) = self.style.scale.get(self.current) {
343 transform = transform * scale.as_transform(bounds, scale_factor);
344 }
345
346 if let Some(transforms) = self.style.transform.get(self.current) {
348 if let Some(animation_state) = self.style.transform.get_active_animation(self.current) {
352 if let Some(start) = animation_state.keyframes.first() {
353 if let Some(end) = animation_state.keyframes.last() {
354 let start_transform = start.value.as_transform(bounds, scale_factor);
355 let end_transform = end.value.as_transform(bounds, scale_factor);
356 let t = animation_state.t;
357 let animated_transform =
358 Matrix::interpolate(&start_transform, &end_transform, t);
359 transform = transform * animated_transform;
360 }
361 }
362 } else {
363 transform = transform * transforms.as_transform(bounds, scale_factor);
364 }
365 }
366
367 transform = transform * origin;
368
369 transform
370 }
371
372 pub fn play_animation(&mut self, anim_id: impl AnimId, duration: Duration, delay: Duration) {
374 if let Some(animation_id) = anim_id.get(self) {
375 self.style.enqueue_animation(self.current, animation_id, duration, delay);
376 }
377 }
378
379 pub fn play_animation_for(
381 &mut self,
382 anim_id: impl AnimId,
383 target: &str,
384 duration: Duration,
385 delay: Duration,
386 ) {
387 if let Some(target_entity) = self.resolve_entity_identifier(target) {
388 if let Some(animation_id) = anim_id.get(self) {
389 self.style.enqueue_animation(target_entity, animation_id, duration, delay)
390 }
391 }
392 }
393
394 pub fn is_animating(&self, anim_id: impl AnimId) -> bool {
396 if let Some(animation_id) = anim_id.get(self) {
397 return self.style.is_animating(self.current, animation_id);
398 }
399
400 false
401 }
402
403 pub fn add_listener<F, W>(&mut self, listener: F)
409 where
410 W: View,
411 F: 'static + Fn(&mut W, &mut EventContext, &mut Event),
412 {
413 self.listeners.insert(
414 self.current,
415 Box::new(move |event_handler, context, event| {
416 if let Some(widget) = event_handler.downcast_mut::<W>() {
417 (listener)(widget, context, event);
418 }
419 }),
420 );
421 }
422
423 pub fn set_language(&mut self, lang: LanguageIdentifier) {
425 if let Some(mut models) = self.models.remove(&Entity::root()) {
426 if let Some(model) = models.get_mut(&TypeId::of::<Environment>()) {
427 model.event(self, &mut Event::new(EnvironmentEvent::SetLocale(lang)));
428 }
429
430 self.models.insert(Entity::root(), models);
431 }
432 }
433
434 pub fn capture(&mut self) {
436 *self.captured = self.current;
437 }
438
439 pub fn release(&mut self) {
441 if self.current == *self.captured {
442 *self.captured = Entity::null();
443 }
444 }
445
446 fn set_focus_pseudo_classes(&mut self, focused: Entity, enabled: bool, focus_visible: bool) {
448 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(focused) {
449 pseudo_classes.set(PseudoClassFlags::FOCUS, enabled);
450 if !enabled || focus_visible {
451 pseudo_classes.set(PseudoClassFlags::FOCUS_VISIBLE, enabled);
452 }
453 }
454
455 for ancestor in focused.parent_iter(self.tree) {
456 let entity = ancestor;
457 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(entity) {
458 pseudo_classes.set(PseudoClassFlags::FOCUS_WITHIN, enabled);
459 }
460 }
461 }
462
463 pub fn focus_with_visibility(&mut self, focus_visible: bool) {
465 let old_focus = self.focused();
466 let new_focus = self.current();
467 self.set_focus_pseudo_classes(old_focus, false, focus_visible);
468 if self.current() != self.focused() {
469 self.emit_to(old_focus, WindowEvent::FocusOut);
470 self.emit_to(new_focus, WindowEvent::FocusIn);
471 *self.focused = self.current();
472 }
473 self.set_focus_pseudo_classes(new_focus, true, focus_visible);
474
475 self.emit_custom(Event::new(WindowEvent::FocusVisibility(focus_visible)).target(old_focus));
476 self.emit_custom(Event::new(WindowEvent::FocusVisibility(focus_visible)).target(new_focus));
477
478 self.needs_restyle();
479 }
480
481 pub fn focus(&mut self) {
485 let focused = self.focused();
486 let old_focus_visible = self
487 .style
488 .pseudo_classes
489 .get_mut(focused)
490 .filter(|class| class.contains(PseudoClassFlags::FOCUS_VISIBLE))
491 .is_some();
492 self.focus_with_visibility(old_focus_visible)
493 }
494
495 pub fn focus_next(&mut self) {
497 let lock_focus_to = self.tree.lock_focus_within(*self.focused);
498 let next_focused = if let Some(next_focused) =
499 focus_forward(self.tree, self.style, *self.focused, lock_focus_to)
500 {
501 next_focused
502 } else {
503 TreeIterator::full(self.tree)
504 .find(|node| is_navigatable(self.tree, self.style, *node, lock_focus_to))
505 .unwrap_or(Entity::root())
506 };
507
508 if next_focused != *self.focused {
509 self.event_queue.push_back(
510 Event::new(WindowEvent::FocusOut).target(*self.focused).origin(Entity::root()),
511 );
512 self.event_queue.push_back(
513 Event::new(WindowEvent::FocusIn).target(next_focused).origin(Entity::root()),
514 );
515
516 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(*self.triggered) {
517 pseudo_classes.set(PseudoClassFlags::ACTIVE, false);
518 }
519 self.needs_restyle();
520 *self.triggered = Entity::null();
521 }
522 }
523
524 pub fn focus_prev(&mut self) {
526 let lock_focus_to = self.tree.lock_focus_within(*self.focused);
527 let prev_focused = if let Some(prev_focused) =
528 focus_backward(self.tree, self.style, *self.focused, lock_focus_to)
529 {
530 prev_focused
531 } else {
532 TreeIterator::full(self.tree)
533 .filter(|node| is_navigatable(self.tree, self.style, *node, lock_focus_to))
534 .next_back()
535 .unwrap_or(Entity::root())
536 };
537
538 if prev_focused != *self.focused {
539 self.event_queue.push_back(
540 Event::new(WindowEvent::FocusOut).target(*self.focused).origin(Entity::root()),
541 );
542 self.event_queue.push_back(
543 Event::new(WindowEvent::FocusIn).target(prev_focused).origin(Entity::root()),
544 );
545
546 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(*self.triggered) {
547 pseudo_classes.set(PseudoClassFlags::ACTIVE, false);
548 }
549 self.needs_restyle();
550 *self.triggered = Entity::null();
551 }
552 }
553
554 pub fn hovered(&self) -> Entity {
556 *self.hovered
557 }
558
559 pub fn focused(&self) -> Entity {
561 *self.focused
562 }
563
564 pub fn is_hovered(&self) -> bool {
568 self.hovered() == self.current
569 }
570
571 pub fn is_active(&self) -> bool {
573 if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
574 pseudo_classes.contains(PseudoClassFlags::ACTIVE)
575 } else {
576 false
577 }
578 }
579
580 pub fn is_over(&self) -> bool {
582 if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
583 pseudo_classes.contains(PseudoClassFlags::OVER)
584 } else {
585 false
586 }
587 }
588
589 pub fn is_focused(&self) -> bool {
591 self.focused() == self.current
592 }
593
594 pub fn is_draggable(&self) -> bool {
596 self.style
597 .abilities
598 .get(self.current)
599 .map(|abilities| abilities.contains(Abilities::DRAGGABLE))
600 .unwrap_or_default()
601 }
602
603 pub fn is_disabled(&self) -> bool {
605 self.style.disabled.get(self.current()).cloned().unwrap_or_default()
606 }
607
608 pub fn is_checked(&self) -> bool {
610 if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
611 pseudo_classes.contains(PseudoClassFlags::CHECKED)
612 } else {
613 false
614 }
615 }
616
617 pub fn is_read_only(&self) -> bool {
619 if let Some(pseudo_classes) = self.style.pseudo_classes.get(self.current) {
620 pseudo_classes.contains(PseudoClassFlags::READ_ONLY)
621 } else {
622 false
623 }
624 }
625
626 pub fn lock_cursor_icon(&mut self) {
630 *self.cursor_icon_locked = true;
631 }
632
633 pub fn unlock_cursor_icon(&mut self) {
635 *self.cursor_icon_locked = false;
636 let hovered = *self.hovered;
637 let cursor = self.style.cursor.get(hovered).cloned().unwrap_or_default();
638 self.emit(WindowEvent::SetCursor(cursor));
639 }
640
641 pub fn is_cursor_icon_locked(&self) -> bool {
643 *self.cursor_icon_locked
644 }
645
646 pub fn set_drop_data(&mut self, data: impl Into<DropData>) {
648 *self.drop_data = Some(data.into())
649 }
650
651 #[cfg(feature = "clipboard")]
655 pub fn get_clipboard(&mut self) -> Result<String, Box<dyn Error + Send + Sync + 'static>> {
656 self.clipboard.get_contents()
657 }
658
659 #[cfg(feature = "clipboard")]
663 pub fn set_clipboard(
664 &mut self,
665 text: String,
666 ) -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
667 self.clipboard.set_contents(text)
668 }
669
670 pub fn toggle_class(&mut self, class_name: &str, applied: bool) {
680 let current = self.current();
681 if let Some(class_list) = self.style.classes.get_mut(current) {
682 if applied {
683 class_list.insert(class_name.to_string());
684 } else {
685 class_list.remove(class_name);
686 }
687 } else if applied {
688 let mut class_list = HashSet::new();
689 class_list.insert(class_name.to_string());
690 self.style.classes.insert(current, class_list);
691 }
692
693 self.needs_restyle();
694 }
695
696 pub fn environment(&self) -> &Environment {
698 self.data::<Environment>().unwrap()
699 }
700
701 pub fn set_theme_mode(&mut self, theme_mode: ThemeMode) {
703 if !self.ignore_default_theme {
704 match theme_mode {
705 ThemeMode::LightMode => {
706 self.resource_manager.themes[2] = String::from(LIGHT_THEME);
707 }
708
709 ThemeMode::DarkMode => {
710 self.resource_manager.themes[2] = String::from(DARK_THEME);
711 }
712 }
713 }
714 }
715
716 pub fn needs_redraw(&mut self) {
718 let parent_window = self.tree.get_parent_window(self.current).unwrap_or(Entity::root());
719 if let Some(window_state) = self.windows.get_mut(&parent_window) {
720 window_state.redraw_list.insert(self.current);
721 }
722 }
723
724 pub fn needs_relayout(&mut self) {
726 self.style.needs_relayout();
727 self.needs_redraw();
728 }
729
730 pub fn needs_restyle(&mut self) {
732 self.style.restyle.insert(self.current).unwrap();
733 let iter = if let Some(parent) = self.tree.get_layout_parent(self.current) {
734 LayoutTreeIterator::subtree(self.tree, parent)
735 } else {
736 LayoutTreeIterator::subtree(self.tree, self.current)
737 };
738
739 for descendant in iter {
740 self.style.restyle.insert(descendant).unwrap();
741 }
742 self.style.needs_restyle(self.current);
743 }
744
745 pub fn reload_styles(&mut self) -> Result<(), std::io::Error> {
747 if self.resource_manager.themes.is_empty() && self.resource_manager.styles.is_empty() {
748 return Ok(());
749 }
750
751 self.style.remove_rules();
752
753 self.style.clear_style_rules();
754
755 let mut overall_theme = String::new();
756
757 for theme in self.resource_manager.themes.iter() {
759 overall_theme += theme;
760 }
761
762 for style_string in self.resource_manager.styles.iter().flat_map(|style| style.get_style())
763 {
764 overall_theme += &style_string;
765 }
766
767 self.style.parse_theme(&overall_theme);
768
769 for entity in self.tree.into_iter() {
770 self.style.needs_restyle(entity);
771 self.style.needs_relayout();
772 self.style.needs_text_update(entity);
774 }
775
776 Ok(())
777 }
778
779 pub fn spawn<F>(&self, target: F)
781 where
782 F: 'static + Send + FnOnce(&mut ContextProxy),
783 {
784 let mut cxp = ContextProxy {
785 current: self.current,
786 event_proxy: self.event_proxy.as_ref().map(|p| p.make_clone()),
787 };
788
789 std::thread::spawn(move || target(&mut cxp));
790 }
791
792 pub fn get_proxy(&self) -> ContextProxy {
794 ContextProxy {
795 current: self.current,
796 event_proxy: self.event_proxy.as_ref().map(|p| p.make_clone()),
797 }
798 }
799
800 pub fn modify<V: View>(&mut self, f: impl FnOnce(&mut V)) {
801 if let Some(view) = self
802 .views
803 .get_mut(&self.current)
804 .and_then(|view_handler| view_handler.downcast_mut::<V>())
805 {
806 (f)(view);
807 }
808 }
809
810 pub fn background_color(&mut self) -> Color {
818 self.style.background_color.get(self.current).copied().unwrap_or_default()
819 }
820
821 pub fn set_id(&mut self, id: &str) {
824 self.style.ids.insert(self.current, id.to_string())
825 }
826
827 pub fn set_hover(&mut self, flag: bool) {
839 let current = self.current();
840 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
841 pseudo_classes.set(PseudoClassFlags::HOVER, flag);
842 }
843
844 self.needs_restyle();
845 }
846
847 pub fn set_active(&mut self, active: bool) {
856 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(self.current) {
857 pseudo_classes.set(PseudoClassFlags::ACTIVE, active);
858 }
859
860 self.needs_restyle();
861 }
862
863 pub fn set_read_only(&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_ONLY, flag);
867 }
868
869 self.needs_restyle();
870 }
871
872 pub fn set_read_write(&mut self, flag: bool) {
873 let current = self.current();
874 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
875 pseudo_classes.set(PseudoClassFlags::READ_WRITE, flag);
876 }
877
878 self.needs_restyle();
879 }
880
881 pub fn set_checked(&mut self, flag: bool) {
890 let current = self.current();
891 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
892 pseudo_classes.set(PseudoClassFlags::CHECKED, flag);
893 }
894
895 self.needs_restyle();
896 }
897
898 pub fn set_valid(&mut self, flag: bool) {
907 let current = self.current();
908 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
909 pseudo_classes.set(PseudoClassFlags::VALID, flag);
910 pseudo_classes.set(PseudoClassFlags::INVALID, !flag);
911 }
912
913 self.needs_restyle();
914 }
915
916 pub fn set_placeholder_shown(&mut self, flag: bool) {
917 let current = self.current();
918 if let Some(pseudo_classes) = self.style.pseudo_classes.get_mut(current) {
919 pseudo_classes.set(PseudoClassFlags::PLACEHOLDER_SHOWN, flag);
920 }
921
922 self.needs_restyle();
923 }
924
925 pub fn is_valid(&self) -> bool {
927 self.style
928 .pseudo_classes
929 .get(self.current)
930 .map(|pseudo_classes| pseudo_classes.contains(PseudoClassFlags::VALID))
931 .unwrap_or_default()
932 }
933
934 pub fn is_placeholder_shown(&self) -> bool {
935 self.style
936 .pseudo_classes
937 .get(self.current)
938 .map(|pseudo_classes| pseudo_classes.contains(PseudoClassFlags::PLACEHOLDER_SHOWN))
939 .unwrap_or_default()
940 }
941
942 pub fn set_name(&mut self, name: &str) {
946 self.style.name.insert(self.current, name.to_string());
947 }
948
949 pub fn set_role(&mut self, role: Role) {
951 self.style.role.insert(self.current, role);
952 }
953
954 pub fn set_live(&mut self, live: Live) {
961 self.style.live.insert(self.current, live);
962 }
963
964 pub fn labelled_by(&mut self, id: &str) {
966 if let Some(entity) = self.resolve_entity_identifier(id) {
967 self.style.labelled_by.insert(self.current, entity);
968 }
969 }
970
971 pub fn set_hidden(&mut self, hidden: bool) {
973 self.style.hidden.insert(self.current, hidden)
974 }
975
976 pub fn text_value(&mut self, text: &str) {
978 self.style.text_value.insert(self.current, text.to_string());
979 }
980
981 pub fn numeric_value(&mut self, value: f64) {
983 self.style.numeric_value.insert(self.current, value);
984 }
985
986 pub fn set_display(&mut self, display: Display) {
992 self.style.display.insert(self.current, display);
993 }
994
995 pub fn set_visibility(&mut self, visibility: Visibility) {
999 self.style.visibility.insert(self.current, visibility);
1000 }
1001
1002 pub fn set_opacity(&mut self, opacity: f32) {
1006 self.style.opacity.insert(self.current, Opacity(opacity));
1007 }
1008
1009 pub fn set_z_index(&mut self, z_index: i32) {
1011 self.style.z_index.insert(self.current, z_index);
1012 }
1013
1014 pub fn set_clip_path(&mut self, clip_path: ClipPath) {
1016 self.style.clip_path.insert(self.current, clip_path);
1017 }
1018
1019 pub fn set_overflowx(&mut self, overflowx: impl Into<Overflow>) {
1021 self.style.overflowx.insert(self.current, overflowx.into());
1022 }
1023
1024 pub fn set_overflowy(&mut self, overflowy: impl Into<Overflow>) {
1026 self.style.overflowy.insert(self.current, overflowy.into());
1027 }
1028
1029 pub fn set_transform(&mut self, transform: impl Into<Vec<Transform>>) {
1033 self.style.transform.insert(self.current, transform.into());
1034 }
1035
1036 pub fn set_transform_origin(&mut self, transform_origin: Translate) {
1038 self.style.transform_origin.insert(self.current, transform_origin);
1039 }
1040
1041 pub fn set_translate(&mut self, translate: impl Into<Translate>) {
1043 self.style.translate.insert(self.current, translate.into());
1044 }
1045
1046 pub fn set_rotate(&mut self, angle: impl Into<Angle>) {
1048 self.style.rotate.insert(self.current, angle.into());
1049 }
1050
1051 pub fn set_scale(&mut self, scale: impl Into<Scale>) {
1053 self.style.scale.insert(self.current, scale.into());
1054 }
1055
1056 pub fn set_backdrop_filter(&mut self, filter: Filter) {
1060 self.style.backdrop_filter.insert(self.current, filter);
1061 }
1062
1063 pub fn set_background_color(&mut self, background_color: Color) {
1070 self.style.background_color.insert(self.current, background_color);
1071 self.needs_redraw();
1072 }
1073
1074 pub fn set_width(&mut self, width: Units) {
1077 self.style.width.insert(self.current, width);
1078 self.needs_relayout();
1079 self.needs_redraw();
1080 }
1081
1082 pub fn set_height(&mut self, height: Units) {
1083 self.style.height.insert(self.current, height);
1084 self.needs_relayout();
1085 self.needs_redraw();
1086 }
1087
1088 pub fn set_max_height(&mut self, height: Units) {
1089 self.style.max_height.insert(self.current, height);
1090 self.needs_relayout();
1091 self.needs_redraw();
1092 }
1093
1094 pub fn set_left(&mut self, left: Units) {
1097 self.style.left.insert(self.current, left);
1098 self.needs_relayout();
1099 self.needs_redraw();
1100 }
1101
1102 pub fn set_top(&mut self, top: Units) {
1103 self.style.top.insert(self.current, top);
1104 self.needs_relayout();
1105 self.needs_redraw();
1106 }
1107
1108 pub fn set_right(&mut self, right: Units) {
1109 self.style.right.insert(self.current, right);
1110 self.needs_relayout();
1111 self.needs_redraw();
1112 }
1113
1114 pub fn set_bottom(&mut self, bottom: Units) {
1115 self.style.bottom.insert(self.current, bottom);
1116 self.needs_relayout();
1117 self.needs_redraw();
1118 }
1119
1120 pub fn set_padding_left(&mut self, padding_left: Units) {
1123 self.style.padding_left.insert(self.current, padding_left);
1124 self.needs_relayout();
1125 self.needs_redraw();
1126 }
1127
1128 pub fn set_padding_top(&mut self, padding_top: Units) {
1129 self.style.padding_top.insert(self.current, padding_top);
1130 self.needs_relayout();
1131 self.needs_redraw();
1132 }
1133
1134 pub fn set_padding_right(&mut self, padding_right: Units) {
1135 self.style.padding_right.insert(self.current, padding_right);
1136 self.needs_relayout();
1137 self.needs_redraw();
1138 }
1139
1140 pub fn set_padding_bottom(&mut self, padding_bottom: Units) {
1141 self.style.padding_bottom.insert(self.current, padding_bottom);
1142 self.needs_relayout();
1143 self.needs_redraw();
1144 }
1145
1146 pub fn set_text(&mut self, text: &str) {
1150 self.style.text.insert(self.current, text.to_owned());
1151 self.style.needs_text_update(self.current);
1152 self.needs_relayout();
1153 self.needs_redraw();
1154 }
1155
1156 pub fn set_pointer_events(&mut self, pointer_events: impl Into<PointerEvents>) {
1157 self.style.pointer_events.insert(self.current, pointer_events.into());
1158 }
1159
1160 get_length_property!(
1162 border_width
1164 );
1165
1166 pub fn font_size(&self) -> f32 {
1168 self.logical_to_physical(
1169 self.style.font_size.get(self.current).copied().map(|f| f.0).unwrap_or(16.0),
1170 )
1171 }
1172
1173 pub fn add_timer(
1204 &mut self,
1205 interval: Duration,
1206 duration: Option<Duration>,
1207 callback: impl Fn(&mut EventContext, TimerAction) + 'static,
1208 ) -> Timer {
1209 let id = Timer(self.timers.len());
1210 self.timers.push(TimerState {
1211 entity: Entity::root(),
1212 id,
1213 time: Instant::now(),
1214 interval,
1215 duration,
1216 start_time: Instant::now(),
1217 callback: Rc::new(callback),
1218 ticking: false,
1219 stopping: false,
1220 });
1221
1222 id
1223 }
1224
1225 pub fn start_timer(&mut self, timer: Timer) {
1229 let current = self.current;
1230 if !self.timer_is_running(timer) {
1231 let timer_state = self.timers[timer.0].clone();
1232 self.running_timers.push(timer_state);
1234 }
1235
1236 self.modify_timer(timer, |timer_state| {
1237 let now = Instant::now();
1238 timer_state.start_time = now;
1239 timer_state.time = now;
1240 timer_state.entity = current;
1241 timer_state.ticking = false;
1242 timer_state.stopping = false;
1243 });
1244 }
1245
1246 pub fn modify_timer(&mut self, timer: Timer, timer_function: impl Fn(&mut TimerState)) {
1248 while let Some(next_timer_state) = self.running_timers.peek() {
1249 if next_timer_state.id == timer {
1250 let mut timer_state = self.running_timers.pop().unwrap();
1251
1252 (timer_function)(&mut timer_state);
1253
1254 self.running_timers.push(timer_state);
1255
1256 return;
1257 }
1258 }
1259
1260 for pending_timer in self.timers.iter_mut() {
1261 if pending_timer.id == timer {
1262 (timer_function)(pending_timer);
1263 }
1264 }
1265 }
1266
1267 pub fn query_timer<T>(
1268 &mut self,
1269 timer: Timer,
1270 timer_function: impl Fn(&TimerState) -> T,
1271 ) -> Option<T> {
1272 while let Some(next_timer_state) = self.running_timers.peek() {
1273 if next_timer_state.id == timer {
1274 let timer_state = self.running_timers.pop().unwrap();
1275
1276 let t = (timer_function)(&timer_state);
1277
1278 self.running_timers.push(timer_state);
1279
1280 return Some(t);
1281 }
1282 }
1283
1284 for pending_timer in self.timers.iter() {
1285 if pending_timer.id == timer {
1286 return Some(timer_function(pending_timer));
1287 }
1288 }
1289
1290 None
1291 }
1292
1293 pub fn timer_is_running(&mut self, timer: Timer) -> bool {
1295 for timer_state in self.running_timers.iter() {
1296 if timer_state.id == timer {
1297 return true;
1298 }
1299 }
1300
1301 false
1302 }
1303
1304 pub fn stop_timer(&mut self, timer: Timer) {
1308 let mut running_timers = self.running_timers.clone();
1309
1310 for timer_state in running_timers.iter() {
1311 if timer_state.id == timer {
1312 self.with_current(timer_state.entity, |cx| {
1313 (timer_state.callback)(cx, TimerAction::Stop);
1314 });
1315 }
1316 }
1317
1318 *self.running_timers =
1319 running_timers.drain().filter(|timer_state| timer_state.id != timer).collect();
1320 }
1321}
1322
1323impl DataContext for EventContext<'_> {
1324 fn data<T: 'static>(&self) -> Option<&T> {
1325 if let Some(t) = <dyn Any>::downcast_ref::<T>(&()) {
1327 return Some(t);
1328 }
1329
1330 for entity in self.current.parent_iter(self.tree) {
1331 if let Some(models) = self.models.get(&entity) {
1333 if let Some(model) = models.get(&TypeId::of::<T>()) {
1334 return model.downcast_ref::<T>();
1335 }
1336 }
1337
1338 if let Some(view_handler) = self.views.get(&entity) {
1340 if let Some(data) = view_handler.downcast_ref::<T>() {
1341 return Some(data);
1342 }
1343 }
1344 }
1345
1346 None
1347 }
1348
1349 fn localization_context(&self) -> Option<LocalizationContext<'_>> {
1350 Some(LocalizationContext::from_event_context(self))
1351 }
1352}
1353
1354impl EmitContext for EventContext<'_> {
1355 fn emit<M: Any + Send>(&mut self, message: M) {
1356 self.event_queue.push_back(
1357 Event::new(message)
1358 .target(self.current)
1359 .origin(self.current)
1360 .propagate(Propagation::Up),
1361 );
1362 }
1363
1364 fn emit_to<M: Any + Send>(&mut self, target: Entity, message: M) {
1365 self.event_queue.push_back(
1366 Event::new(message).target(target).origin(self.current).propagate(Propagation::Direct),
1367 );
1368 }
1369
1370 fn emit_custom(&mut self, event: Event) {
1371 self.event_queue.push_back(event);
1372 }
1373
1374 fn schedule_emit<M: Any + Send>(&mut self, message: M, at: Instant) -> TimedEventHandle {
1375 self.schedule_emit_custom(
1376 Event::new(message)
1377 .target(self.current)
1378 .origin(self.current)
1379 .propagate(Propagation::Up),
1380 at,
1381 )
1382 }
1383 fn schedule_emit_to<M: Any + Send>(
1384 &mut self,
1385 target: Entity,
1386 message: M,
1387 at: Instant,
1388 ) -> TimedEventHandle {
1389 self.schedule_emit_custom(
1390 Event::new(message).target(target).origin(self.current).propagate(Propagation::Direct),
1391 at,
1392 )
1393 }
1394 fn schedule_emit_custom(&mut self, event: Event, at: Instant) -> TimedEventHandle {
1395 let handle = TimedEventHandle(*self.next_event_id);
1396 self.event_schedule.push(TimedEvent { event, time: at, ident: handle });
1397 *self.next_event_id += 1;
1398 handle
1399 }
1400 fn cancel_scheduled(&mut self, handle: TimedEventHandle) {
1401 *self.event_schedule =
1402 self.event_schedule.drain().filter(|item| item.ident != handle).collect();
1403 }
1404}
1405
1406pub trait TreeProps {
1408 fn parent(&self) -> Entity;
1410 fn first_child(&self) -> Entity;
1412 fn parent_window(&self) -> Entity;
1414}
1415
1416impl TreeProps for EventContext<'_> {
1417 fn parent(&self) -> Entity {
1418 self.tree.get_layout_parent(self.current).unwrap()
1419 }
1420
1421 fn first_child(&self) -> Entity {
1422 self.tree.get_layout_first_child(self.current).unwrap()
1423 }
1424
1425 fn parent_window(&self) -> Entity {
1426 self.tree.get_parent_window(self.current).unwrap_or(Entity::root())
1427 }
1428}