ferroui_xaml_interactions_custom/debugging/
visual_debug_behavior.rs1use super::visual_debug_adorner::VisualDebugAdorner;
4use ferroui_base::animation::TimeSpan;
5use ferroui_base::media::{Color, Colors, SolidColorBrush};
6use ferroui_base::threading::{DispatcherPriority, DispatcherTimer};
7use ferroui_base::{
8 ferro_class, ferro_class_info, ferro_properties, instantiate, BoxedValue, FerroObjectImpl, FerroProperty, Ref,
9 StyledElementImpl, StyledProperty, Visual,
10};
11use ferroui_controls::primitives::AdornerLayer;
12use ferroui_controls::Control;
13use ferroui_xaml_interactivity::{
14 EventTriggerBase, EventTriggerBaseImpl, EventTriggerBaseImplExt, StyledElementBehaviorImpl,
15};
16
17#[repr(C)]
21pub struct VisualDebugBehavior {
22 base: EventTriggerBase,
23}
24
25ferro_class!(VisualDebugBehavior: EventTriggerBase);
26ferro_class_info!(VisualDebugBehavior { new: VisualDebugBehavior::new });
27ferroui_base::ferro_impl_classes!(
28 VisualDebugBehavior: FerroObjectImpl,
29 StyledElementImpl,
30 StyledElementBehaviorImpl,
31);
32
33ferro_properties! {
34 impl VisualDebugBehavior {
35 pub fn highlight_color_property() -> StyledProperty<Color> {
37 FerroProperty::register::<VisualDebugBehavior, _>("HighlightColor", Colors::RED)
38 }
39
40 pub fn duration_property() -> StyledProperty<TimeSpan> {
42 FerroProperty::register::<VisualDebugBehavior, _>("Duration", TimeSpan::from_seconds(0.5))
43 }
44 }
45}
46
47ferroui_base::ferro_overrides! {
48 impl EventTriggerBaseImpl for VisualDebugBehavior {
49 fn on_event(this: &Self, event_args: Option<&BoxedValue>) {
50 Self::parent_on_event(this, event_args);
52
53 if let Some(control) = this.associated_object().and_then(|associated_object| associated_object.cast::<Control>()) {
54 this.show_highlight(&control);
55 }
56 }
57 }
58}
59
60impl VisualDebugBehavior {
61 pub fn construct() -> Self {
63 Self { base: EventTriggerBase::construct() }
64 }
65
66 pub fn new() -> Ref<Self> {
68 instantiate(Self::construct())
69 }
70
71 pub fn highlight_color(&self) -> Color {
73 self.get_value(Self::highlight_color_property())
74 }
75
76 pub fn set_highlight_color(&self, value: Color) {
77 self.set_value(Self::highlight_color_property(), value)
78 }
79
80 pub fn duration(&self) -> TimeSpan {
82 self.get_value(Self::duration_property())
83 }
84
85 pub fn set_duration(&self, value: TimeSpan) {
86 self.set_value(Self::duration_property(), value)
87 }
88
89 fn show_highlight(&self, control: &Ref<Control>) {
90 let visual: &Visual = control;
91 let Some(adorner_layer) = AdornerLayer::get_adorner_layer(visual) else {
92 return;
93 };
94
95 let brush = SolidColorBrush::with_color(self.highlight_color());
96 let adorner = VisualDebugAdorner::new(control.clone(), brush);
97
98 let adorner_visual: &Visual = &adorner;
99 AdornerLayer::set_adorned_element(adorner_visual, control);
100 adorner_layer.children().add(adorner.clone());
101
102 let _ = DispatcherTimer::run_once(
103 move || {
104 adorner_layer.children().remove(adorner.clone());
105 },
106 self.duration().to_duration().unwrap_or_default(),
107 DispatcherPriority::BACKGROUND,
108 );
109 }
110}