ferroui_base/
ferro_property_changed_event_args.rs1use crate::data::core::{ValueType, ValueTypes};
2use crate::data::BindingPriority;
3use crate::{BoxedValue, FerroObject, FerroProperty, Ref};
4use std::any::Any;
5
6pub struct FerroPropertyChangedEventArgs<'a> {
11 sender: &'a FerroObject,
12 property: &'static FerroProperty,
13 old_value: Option<&'a dyn Any>,
14 new_value: &'a dyn Any,
15 priority: BindingPriority,
16 is_effective_value_change: bool,
17 is_inherited_value_change: bool,
18}
19
20impl<'a> FerroPropertyChangedEventArgs<'a> {
21 pub(crate) fn new(
22 sender: &'a FerroObject,
23 property: &'static FerroProperty,
24 old_value: Option<&'a dyn Any>,
25 new_value: &'a dyn Any,
26 priority: BindingPriority,
27 is_effective_value_change: bool,
28 ) -> Self {
29 Self { sender, property, old_value, new_value, priority, is_effective_value_change, is_inherited_value_change: false }
30 }
31
32 #[inline]
34 pub fn sender(&self) -> &'a FerroObject {
35 self.sender
36 }
37
38 #[inline]
40 pub fn property(&self) -> &'static FerroProperty {
41 self.property
42 }
43
44 #[inline]
47 pub fn old_value(&self) -> Option<&'a dyn Any> {
48 self.old_value
49 }
50
51 #[inline]
53 pub fn new_value(&self) -> &'a dyn Any {
54 self.new_value
55 }
56
57 #[inline]
59 pub fn priority(&self) -> BindingPriority {
60 self.priority
61 }
62
63 #[inline]
66 pub fn is_effective_value_change(&self) -> bool {
67 self.is_effective_value_change
68 }
69
70 pub fn is_inherited_value_change(&self) -> bool {
74 self.is_inherited_value_change
75 }
76
77 pub(crate) fn from_inheritance(mut self) -> Self {
78 self.is_inherited_value_change = true;
79 self
80 }
81
82 pub fn get_old_value<T: Clone + 'static>(&self) -> Option<T> {
85 self.old_value.map(|v| Self::cast::<T>(self.property, v).clone())
86 }
87
88 pub fn get_new_value<T: Clone + 'static>(&self) -> T {
91 Self::cast::<T>(self.property, self.new_value).clone()
92 }
93
94 pub fn get_old_and_new_value<T: Clone + 'static>(&self) -> (T, T) {
97 (self.get_old_value::<T>().expect("change has no old value"), self.get_new_value::<T>())
98 }
99
100 pub fn to_owned_args(&self) -> OwnedFerroPropertyChangedEventArgs {
103 let routes = self.property.routes();
104 OwnedFerroPropertyChangedEventArgs {
105 sender: self.sender.to_ref(),
106 property: self.property,
107 old_value: self.old_value.and_then(|value| routes.route_box_value(value)).and_then(untyped),
108 new_value: routes.route_box_value(self.new_value).and_then(untyped),
109 priority: self.priority,
110 is_effective_value_change: self.is_effective_value_change,
111 is_inherited_value_change: self.is_inherited_value_change,
112 }
113 }
114
115 pub(crate) fn with_sender<'b>(&'b self, sender: &'b FerroObject) -> FerroPropertyChangedEventArgs<'b> {
118 FerroPropertyChangedEventArgs {
119 sender,
120 property: self.property,
121 old_value: self.old_value,
122 new_value: self.new_value,
123 priority: self.priority,
124 is_effective_value_change: self.is_effective_value_change,
125 is_inherited_value_change: self.is_inherited_value_change,
126 }
127 }
128
129 fn cast<'v, T: 'static>(property: &FerroProperty, value: &'v dyn Any) -> &'v T {
130 value.downcast_ref::<T>().unwrap_or_else(|| {
131 panic!(
132 "property '{}' is of type {}, not {}",
133 property.name(),
134 property.property_type_name(),
135 std::any::type_name::<T>()
136 )
137 })
138 }
139}
140
141fn untyped(value: BoxedValue) -> Option<BoxedValue> {
144 match ValueTypes::try_cast(&value, ValueType::of::<Option<BoxedValue>>()) {
145 Some(untyped) => untyped.downcast_ref::<Option<BoxedValue>>().cloned().flatten(),
146 None => Some(value),
147 }
148}
149
150#[derive(Clone)]
157pub struct OwnedFerroPropertyChangedEventArgs {
158 sender: Ref<FerroObject>,
159 property: &'static FerroProperty,
160 old_value: Option<BoxedValue>,
161 new_value: Option<BoxedValue>,
162 priority: BindingPriority,
163 is_effective_value_change: bool,
164 is_inherited_value_change: bool,
165}
166
167impl OwnedFerroPropertyChangedEventArgs {
168 pub fn sender(&self) -> Ref<FerroObject> {
170 self.sender.clone()
171 }
172
173 pub fn property(&self) -> &'static FerroProperty {
175 self.property
176 }
177
178 pub fn old_value(&self) -> Option<BoxedValue> {
180 self.old_value.clone()
181 }
182
183 pub fn new_value(&self) -> Option<BoxedValue> {
185 self.new_value.clone()
186 }
187
188 pub fn priority(&self) -> BindingPriority {
190 self.priority
191 }
192
193 pub fn is_effective_value_change(&self) -> bool {
196 self.is_effective_value_change
197 }
198
199 pub fn is_inherited_value_change(&self) -> bool {
201 self.is_inherited_value_change
202 }
203}
204
205impl PartialEq for OwnedFerroPropertyChangedEventArgs {
206 fn eq(&self, other: &Self) -> bool {
207 self.sender == other.sender
208 && self.property == other.property
209 && ValueTypes::identity_equals(self.old_value.as_ref(), other.old_value.as_ref())
210 && ValueTypes::identity_equals(self.new_value.as_ref(), other.new_value.as_ref())
211 && self.priority == other.priority
212 && self.is_effective_value_change == other.is_effective_value_change
213 && self.is_inherited_value_change == other.is_inherited_value_change
214 }
215}