ferroui_xaml_interactivity/styled_element/
styled_element_trigger.rs1use crate::{
4 ActionCollection, IBehavior, ITrigger, StyledElementAction, StyledElementBehavior, StyledElementBehaviorImpl,
5 StyledElementBehaviorImplExt,
6};
7use ferroui_base::{
8 ferro_class, ferro_class_info, ferro_properties, FerroObject, FerroObjectImpl, FerroObjectImplExt, FerroProperty,
9 FerroPropertyChangedEventArgs, Ref, StyledElement, StyledElementImpl, StyledProperty,
10};
11use ferroui_controls::TopLevel;
12
13#[repr(C)]
20pub struct StyledElementTrigger {
21 base: StyledElementBehavior,
22}
23
24ferro_class!(StyledElementTrigger: StyledElementBehavior);
25ferro_class_info!(StyledElementTrigger {
26 markup: {
27 content: Actions,
28 },
29});
30ferroui_base::ferro_impl_classes!(StyledElementTrigger: StyledElementImpl);
31
32ferro_properties! {
33 impl StyledElementTrigger {
34 pub fn actions_property() -> StyledProperty<Option<ActionCollection>> {
36 FerroProperty::register::<StyledElementTrigger, _>("Actions", None)
37 }
38 }
39}
40
41ferroui_base::ferro_overrides! {
42 impl FerroObjectImpl for StyledElementTrigger {
43 fn constructed(this: &Self) {
46 Self::parent_constructed(this);
47 this.set_current_value(Self::actions_property(), Some(ActionCollection::new()));
48 }
49
50 fn on_property_changed(this: &Self, change: &FerroPropertyChangedEventArgs<'_>) {
51 Self::parent_on_property_changed(this, change);
52
53 if change.property() == Self::actions_property().as_property() {
54 let old_actions = change.get_old_value::<Option<ActionCollection>>().flatten();
55 let new_actions = change.get_new_value::<Option<ActionCollection>>();
56
57 if let Some(old_actions) = &old_actions {
58 if this.is_initialized() {
59 this.detach_actions_from_logical_tree(Some(old_actions));
60 }
61 }
62
63 if let Some(new_actions) = &new_actions {
64 if this.is_initialized() {
65 this.attach_actions_to_logical_tree(Some(new_actions));
66 }
67 }
68 }
69 }
70 }
71}
72
73ferroui_base::ferro_overrides! {
74 impl StyledElementBehaviorImpl for StyledElementTrigger {
75 fn initialize(this: &Self) {
76 Self::parent_initialize(this);
77
78 this.initialize_actions(this.actions().as_ref());
79 }
80
81 fn attach_behavior_to_logical_tree(this: &Self) {
82 Self::parent_attach_behavior_to_logical_tree(this);
83
84 this.attach_actions_to_logical_tree(this.actions().as_ref());
85 }
86
87 fn detach_behavior_from_logical_tree(this: &Self) {
88 this.detach_actions_from_logical_tree(this.actions().as_ref());
89
90 Self::parent_detach_behavior_from_logical_tree(this);
91 }
92 }
93}
94
95impl StyledElementTrigger {
96 fn static_constructor() {
98 <dyn ITrigger>::register::<StyledElementTrigger>();
99 }
100
101 pub fn construct() -> Self {
103 Self { base: StyledElementBehavior::construct() }
104 }
105
106 pub fn actions(&self) -> Option<ActionCollection> {
109 self.get_value(Self::actions_property())
110 }
111
112 pub fn set_actions(&self, value: Option<ActionCollection>) {
113 self.set_value(Self::actions_property(), value)
114 }
115
116 fn attach_actions_to_logical_tree(&self, actions: Option<&ActionCollection>) {
117 let Some(actions) = actions else {
118 return;
119 };
120
121 let parent: Ref<StyledElement> = match self.associated_object().and_then(|o| o.cast::<TopLevel>()) {
122 Some(top_level) => top_level.upcast(),
123 None => {
124 if self.parent().is_none() {
125 return;
126 }
127
128 self.to_ref().upcast()
129 }
130 };
131
132 for action in actions.snapshot().iter() {
133 if let Some(styled_element_action) = action.downcast_ref::<StyledElementAction>() {
134 styled_element_action.attach_action_to_logical_tree(&parent);
135 }
136 }
137 }
138
139 fn detach_actions_from_logical_tree(&self, actions: Option<&ActionCollection>) {
140 let Some(actions) = actions else {
141 return;
142 };
143
144 let parent: &StyledElement = self;
145
146 for action in actions.snapshot().iter() {
147 if let Some(styled_element_action) = action.downcast_ref::<StyledElementAction>() {
148 styled_element_action.detach_action_from_logical_tree(parent);
149 }
150 }
151 }
152
153 fn initialize_actions(&self, actions: Option<&ActionCollection>) {
154 let Some(actions) = actions else {
155 return;
156 };
157
158 for action in actions.snapshot().iter() {
159 if let Some(styled_element_action) = action.downcast_ref::<StyledElementAction>() {
160 styled_element_action.initialize();
161 }
162 }
163 }
164}
165
166impl IBehavior for StyledElementTrigger {
167 fn associated_object(&self) -> Option<Ref<FerroObject>> {
168 StyledElementBehavior::associated_object(self)
169 }
170
171 fn attach(&self, associated_object: Option<Ref<FerroObject>>) {
172 StyledElementBehavior::attach(self, associated_object)
173 }
174
175 fn detach(&self) {
176 StyledElementBehavior::detach(self)
177 }
178}
179
180impl ITrigger for StyledElementTrigger {
181 fn actions(&self) -> Option<ActionCollection> {
182 StyledElementTrigger::actions(self)
183 }
184}