ferroui_base/metadata/
typed_path.rs1use crate::data::core::TypedClrPropertyInfo;
25use crate::data::model::INotifyPropertyChanged;
26use crate::data::{BindingError, CompiledBindingPathBuilder};
27use crate::PropertyValue;
28use std::marker::PhantomData;
29use std::rc::Rc;
30
31pub type TypedPathElement = fn(&CompiledBindingPathBuilder, bool) -> Option<CompiledBindingPathBuilder>;
35
36pub type TypedPathGetter<This, V> = Rc<dyn Fn(&This) -> Result<V, BindingError>>;
38pub type TypedPathSetter<This, V> = Rc<dyn Fn(&This, V)>;
40
41#[doc(hidden)]
44pub struct TypedPathProbe<This, V>(PhantomData<(This, V)>);
45
46impl<This, V> TypedPathProbe<This, V> {
47 #[allow(clippy::new_without_default)]
48 pub const fn new() -> Self {
49 Self(PhantomData)
50 }
51}
52
53#[doc(hidden)]
56pub trait TypedPathNotifying<This, V> {
57 fn typed_path_element(
58 &self,
59 builder: &CompiledBindingPathBuilder,
60 accepts_null: bool,
61 name: &str,
62 get: Option<TypedPathGetter<This, V>>,
63 set: Option<TypedPathSetter<This, V>>,
64 ) -> Option<CompiledBindingPathBuilder>;
65}
66
67impl<S: INotifyPropertyChanged + PartialEq + 'static, V: PropertyValue> TypedPathNotifying<Rc<S>, V>
68 for &TypedPathProbe<Rc<S>, V>
69{
70 fn typed_path_element(
71 &self,
72 builder: &CompiledBindingPathBuilder,
73 accepts_null: bool,
74 name: &str,
75 get: Option<TypedPathGetter<Rc<S>, V>>,
76 set: Option<TypedPathSetter<Rc<S>, V>>,
77 ) -> Option<CompiledBindingPathBuilder> {
78 if is_untyped::<V>() {
79 return None;
80 }
81 let info = TypedClrPropertyInfo::<S, V>::from_handle_accessors(name, get, set);
82 Some(builder.typed_property_info_with(info, accepts_null))
83 }
84}
85
86#[doc(hidden)]
88pub trait TypedPathShared<This, V> {
89 fn typed_path_element(
90 &self,
91 builder: &CompiledBindingPathBuilder,
92 accepts_null: bool,
93 name: &str,
94 get: Option<TypedPathGetter<This, V>>,
95 set: Option<TypedPathSetter<This, V>>,
96 ) -> Option<CompiledBindingPathBuilder>;
97}
98
99impl<S: PartialEq + 'static, V: PropertyValue> TypedPathShared<Rc<S>, V> for &&TypedPathProbe<Rc<S>, V> {
100 fn typed_path_element(
101 &self,
102 builder: &CompiledBindingPathBuilder,
103 accepts_null: bool,
104 name: &str,
105 get: Option<TypedPathGetter<Rc<S>, V>>,
106 set: Option<TypedPathSetter<Rc<S>, V>>,
107 ) -> Option<CompiledBindingPathBuilder> {
108 if is_untyped::<V>() {
109 return None;
110 }
111 let info = TypedClrPropertyInfo::<S, V>::from_handle_accessors(name, get, set);
112 Some(builder.typed_plain_property_info_with(info, accepts_null))
113 }
114}
115
116fn is_untyped<V: 'static>() -> bool {
121 let id = std::any::TypeId::of::<V>();
122 id == std::any::TypeId::of::<crate::BoxedValue>() || id == std::any::TypeId::of::<Option<crate::BoxedValue>>()
123}
124
125#[doc(hidden)]
127pub trait TypedPathFallback<This, V> {
128 fn typed_path_element(
129 &self,
130 _builder: &CompiledBindingPathBuilder,
131 _accepts_null: bool,
132 _name: &str,
133 _get: Option<TypedPathGetter<This, V>>,
134 _set: Option<TypedPathSetter<This, V>>,
135 ) -> Option<CompiledBindingPathBuilder> {
136 None
137 }
138}
139
140impl<This, V> TypedPathFallback<This, V> for TypedPathProbe<This, V> {}