ferroui_dialogs/internal/
resource_selector_converter.rs1use ferroui_base::utilities::CultureInfo;
2use ferroui_base::controls::{ResourceDictionary, ResourceKey, ResourceProviderImpl};
3use ferroui_base::data::converters::IValueConverter;
4use ferroui_base::data::core::ValueType;
5use ferroui_base::data::BindingError;
6use ferroui_base::{ferro_class, ferro_class_info, instantiate, BoxedValue, FerroObjectImpl, Ref};
7use std::rc::Rc;
8
9#[repr(C)]
12pub struct ResourceSelectorConverter {
13 base: ResourceDictionary,
14}
15
16ferro_class!(ResourceSelectorConverter: ResourceDictionary);
17ferro_class_info!(ResourceSelectorConverter {
18 new: ResourceSelectorConverter::new,
19 interfaces: [Rc<dyn IValueConverter> => ResourceSelectorConverter::as_value_converter],
20});
21
22impl FerroObjectImpl for ResourceSelectorConverter {}
23
24impl ResourceProviderImpl for ResourceSelectorConverter {}
25
26impl ResourceSelectorConverter {
27 pub fn construct() -> Self {
28 Self { base: ResourceDictionary::construct() }
29 }
30
31 pub fn new() -> Ref<Self> {
32 instantiate(Self::construct())
33 }
34
35 pub fn as_value_converter(this: Ref<Self>) -> Rc<dyn IValueConverter> {
38 Rc::new(ResourceSelectorConverterHandle(this))
39 }
40
41 pub fn convert(&self, key: Option<&BoxedValue>, _culture: &CultureInfo) -> Result<Option<BoxedValue>, BindingError> {
44 let Some(key) = key.and_then(|key| key.downcast_ref::<String>()) else {
45 return Err(BindingError::message("The resource key of the converter must be a string."));
46 };
47
48 Ok(self.try_get_resource(&ResourceKey::from(key.as_str()), None).flatten())
49 }
50
51 pub fn convert_back(&self, _value: Option<&BoxedValue>, _culture: &CultureInfo) -> Result<Option<BoxedValue>, BindingError> {
53 Err(BindingError::message("The method or operation is not implemented."))
54 }
55}
56
57struct ResourceSelectorConverterHandle(Ref<ResourceSelectorConverter>);
59
60impl IValueConverter for ResourceSelectorConverterHandle {
61 fn convert(
62 &self,
63 value: Option<&BoxedValue>,
64 _target_type: ValueType,
65 _parameter: Option<&BoxedValue>,
66 _culture: &CultureInfo,
67 ) -> Result<Option<BoxedValue>, BindingError> {
68 self.0.convert(value, &ferroui_base::utilities::CultureInfo::invariant_culture())
69 }
70
71 fn convert_back(
72 &self,
73 value: Option<&BoxedValue>,
74 _target_type: ValueType,
75 _parameter: Option<&BoxedValue>,
76 _culture: &CultureInfo,
77 ) -> Result<Option<BoxedValue>, BindingError> {
78 self.0.convert_back(value, &ferroui_base::utilities::CultureInfo::invariant_culture())
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
86
87 #[test]
88 fn converts_a_key_to_the_resource_of_the_dictionary() {
89 let converter = ResourceSelectorConverter::new();
90 converter.add("Icon_File", Some(Rc::new(42i32) as BoxedValue));
91 let contract = ResourceSelectorConverter::as_value_converter(converter);
92
93 let found = contract.convert(Some(&(Rc::new("Icon_File".to_string()) as BoxedValue)), ValueType::of::<i32>(), None, &ferroui_base::utilities::CultureInfo::invariant_culture());
94 assert_eq!(Some(&42), found.unwrap().unwrap().downcast_ref::<i32>());
95
96 let missing = contract.convert(Some(&(Rc::new("Icon_Folder".to_string()) as BoxedValue)), ValueType::of::<i32>(), None, &ferroui_base::utilities::CultureInfo::invariant_culture());
97 assert!(missing.unwrap().is_none());
98
99 assert!(contract.convert(Some(&(Rc::new(1i32) as BoxedValue)), ValueType::of::<i32>(), None, &ferroui_base::utilities::CultureInfo::invariant_culture()).is_err());
100 assert!(contract.convert(None, ValueType::of::<i32>(), None, &ferroui_base::utilities::CultureInfo::invariant_culture()).is_err());
101 }
102}