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}
18
19impl<'a> FerroPropertyChangedEventArgs<'a> {
20 pub(crate) fn new(
21 sender: &'a FerroObject,
22 property: &'static FerroProperty,
23 old_value: Option<&'a dyn Any>,
24 new_value: &'a dyn Any,
25 priority: BindingPriority,
26 is_effective_value_change: bool,
27 ) -> Self {
28 Self { sender, property, old_value, new_value, priority, is_effective_value_change }
29 }
30
31 #[inline]
33 pub fn sender(&self) -> &'a FerroObject {
34 self.sender
35 }
36
37 #[inline]
39 pub fn property(&self) -> &'static FerroProperty {
40 self.property
41 }
42
43 #[inline]
46 pub fn old_value(&self) -> Option<&'a dyn Any> {
47 self.old_value
48 }
49
50 #[inline]
52 pub fn new_value(&self) -> &'a dyn Any {
53 self.new_value
54 }
55
56 #[inline]
58 pub fn priority(&self) -> BindingPriority {
59 self.priority
60 }
61
62 #[inline]
65 pub fn is_effective_value_change(&self) -> bool {
66 self.is_effective_value_change
67 }
68
69 pub fn get_old_value<T: Clone + 'static>(&self) -> Option<T> {
72 self.old_value.map(|v| Self::cast::<T>(self.property, v).clone())
73 }
74
75 pub fn get_new_value<T: Clone + 'static>(&self) -> T {
78 Self::cast::<T>(self.property, self.new_value).clone()
79 }
80
81 pub fn get_old_and_new_value<T: Clone + 'static>(&self) -> (T, T) {
84 (self.get_old_value::<T>().expect("change has no old value"), self.get_new_value::<T>())
85 }
86
87 pub fn to_owned_args(&self) -> OwnedFerroPropertyChangedEventArgs {
90 let routes = self.property.routes();
91 OwnedFerroPropertyChangedEventArgs {
92 sender: self.sender.to_ref(),
93 property: self.property,
94 old_value: self.old_value.and_then(|value| routes.route_box_value(value)).and_then(untyped),
95 new_value: routes.route_box_value(self.new_value).and_then(untyped),
96 priority: self.priority,
97 is_effective_value_change: self.is_effective_value_change,
98 }
99 }
100
101 pub(crate) fn with_sender<'b>(&'b self, sender: &'b FerroObject) -> FerroPropertyChangedEventArgs<'b> {
104 FerroPropertyChangedEventArgs {
105 sender,
106 property: self.property,
107 old_value: self.old_value,
108 new_value: self.new_value,
109 priority: self.priority,
110 is_effective_value_change: self.is_effective_value_change,
111 }
112 }
113
114 fn cast<'v, T: 'static>(property: &FerroProperty, value: &'v dyn Any) -> &'v T {
115 value.downcast_ref::<T>().unwrap_or_else(|| {
116 panic!(
117 "property '{}' is of type {}, not {}",
118 property.name(),
119 property.property_type_name(),
120 std::any::type_name::<T>()
121 )
122 })
123 }
124}
125
126fn untyped(value: BoxedValue) -> Option<BoxedValue> {
129 match ValueTypes::try_cast(&value, ValueType::of::<Option<BoxedValue>>()) {
130 Some(untyped) => untyped.downcast_ref::<Option<BoxedValue>>().cloned().flatten(),
131 None => Some(value),
132 }
133}
134
135#[derive(Clone)]
142pub struct OwnedFerroPropertyChangedEventArgs {
143 sender: Ref<FerroObject>,
144 property: &'static FerroProperty,
145 old_value: Option<BoxedValue>,
146 new_value: Option<BoxedValue>,
147 priority: BindingPriority,
148 is_effective_value_change: bool,
149}
150
151impl OwnedFerroPropertyChangedEventArgs {
152 pub fn sender(&self) -> Ref<FerroObject> {
154 self.sender.clone()
155 }
156
157 pub fn property(&self) -> &'static FerroProperty {
159 self.property
160 }
161
162 pub fn old_value(&self) -> Option<BoxedValue> {
164 self.old_value.clone()
165 }
166
167 pub fn new_value(&self) -> Option<BoxedValue> {
169 self.new_value.clone()
170 }
171
172 pub fn priority(&self) -> BindingPriority {
174 self.priority
175 }
176
177 pub fn is_effective_value_change(&self) -> bool {
180 self.is_effective_value_change
181 }
182}
183
184impl PartialEq for OwnedFerroPropertyChangedEventArgs {
185 fn eq(&self, other: &Self) -> bool {
186 self.sender == other.sender
187 && self.property == other.property
188 && ValueTypes::identity_equals(self.old_value.as_ref(), other.old_value.as_ref())
189 && ValueTypes::identity_equals(self.new_value.as_ref(), other.new_value.as_ref())
190 && self.priority == other.priority
191 && self.is_effective_value_change == other.is_effective_value_change
192 }
193}