ferroui_xaml_interactivity/styled_element/
styled_element_action.rs1use crate::contract::InterfaceTable;
4use crate::helpers::TemplatedParentHelper;
5use crate::IAction;
6use ferroui_base::{
7 ferro_class, ferro_properties, BoxedValue, FerroObject, FerroObjectImpl, FerroProperty, ObjectType, StyledElement,
8 StyledElementImpl, StyledProperty,
9};
10
11#[repr(C)]
19pub struct StyledElementAction {
20 base: StyledElement,
21}
22
23ferro_class! {
24 StyledElementAction: StyledElement, virtuals StyledElementActionImpl: StyledElementImpl {
25 fn execute(this, sender: Option<&BoxedValue>, parameter: Option<&BoxedValue>) -> Option<BoxedValue>;
34 }
35}
36
37ferroui_base::ferro_impl_classes!(StyledElementAction: FerroObjectImpl, StyledElementImpl);
38
39impl StyledElementActionImpl for StyledElementAction {
40 fn execute(_this: &Self, _sender: Option<&BoxedValue>, _parameter: Option<&BoxedValue>) -> Option<BoxedValue> {
41 panic!("StyledElementAction is abstract: 'execute' must be implemented by the deriving class")
42 }
43}
44
45ferro_properties! {
46 impl StyledElementAction {
47 pub fn is_enabled_property() -> StyledProperty<bool> {
49 FerroProperty::register::<StyledElementAction, _>("IsEnabled", true)
50 }
51 }
52}
53
54impl StyledElementAction {
55 fn static_constructor() {
57 <dyn IAction>::register::<StyledElementAction>();
58 }
59
60 pub fn construct() -> Self {
62 Self { base: StyledElement::construct() }
63 }
64
65 pub fn is_enabled(&self) -> bool {
67 self.get_value(Self::is_enabled_property())
68 }
69
70 pub fn set_is_enabled(&self, value: bool) {
71 self.set_value(Self::is_enabled_property(), value)
72 }
73
74 #[doc(hidden)]
76 pub fn initialize(&self) {
77 self.initialize_if_needed();
78 }
79
80 #[doc(hidden)]
82 pub fn attach_action_to_logical_tree(&self, parent: &StyledElement) {
83 self.set_parent(parent.to_ref());
85
86 if let Some(templated_parent) = parent.templated_parent() {
88 TemplatedParentHelper::set_templated_parent(self, Some(templated_parent));
89 }
90
91 if let Some(lifecycle) = <dyn IActionLogicalTreeLifecycle>::of(self) {
92 lifecycle.attached_to_action_logical_tree();
93 }
94 }
95
96 #[doc(hidden)]
98 pub fn detach_action_from_logical_tree(&self, parent: &StyledElement) {
99 if let Some(lifecycle) = <dyn IActionLogicalTreeLifecycle>::of(self) {
100 lifecycle.detached_from_action_logical_tree();
101 }
102
103 self.set_parent(None);
104
105 if self.templated_parent().is_some() || parent.templated_parent().is_some() {
106 TemplatedParentHelper::set_templated_parent(self, None);
107 }
108 }
109}
110
111impl IAction for StyledElementAction {
112 fn execute(&self, sender: Option<&BoxedValue>, parameter: Option<&BoxedValue>) -> Option<BoxedValue> {
113 StyledElementAction::execute(self, sender, parameter)
114 }
115}
116
117#[doc(hidden)]
120pub trait IActionLogicalTreeLifecycle {
121 fn attached_to_action_logical_tree(&self);
122
123 fn detached_from_action_logical_tree(&self);
124}
125
126static TABLE: InterfaceTable<dyn IActionLogicalTreeLifecycle> = InterfaceTable::new();
127
128fn cast<'a, T: ObjectType + IActionLogicalTreeLifecycle>(
129 object: &'a FerroObject,
130) -> Option<&'a (dyn IActionLogicalTreeLifecycle + 'static)> {
131 object.downcast_ref::<T>().map(|object| object as &(dyn IActionLogicalTreeLifecycle + 'static))
132}
133
134impl dyn IActionLogicalTreeLifecycle {
135 pub fn register<T: ObjectType + IActionLogicalTreeLifecycle>() {
138 TABLE.register(T::TYPE, cast::<T>);
139 }
140
141 pub fn of(object: &FerroObject) -> Option<&dyn IActionLogicalTreeLifecycle> {
143 TABLE.find(object)
144 }
145}