ferroui_base/data/
multi_binding.rs1use crate::collections::FerroList;
2use crate::data::compiled_binding::binding_properties;
3use crate::data::converters::{IMultiValueConverter, StringFormatMultiValueConverter};
4use crate::data::core::plugins::property_value_type;
5use crate::data::core::{MultiBindingExpression, ValueType};
6use crate::data::{BindingBase, BindingExpressionBase, BindingMode, BindingPriority, RelativeSource};
7use crate::utilities::CultureInfo;
8use crate::{BoxedValue, FerroObject, FerroProperty, Ref};
9use std::rc::Rc;
10
11binding_properties! {
12 pub struct MultiBinding {
22 bindings / set_bindings / with_bindings_list: FerroList<Rc<dyn BindingBase>> = FerroList::new(),
25 converter / set_converter / with_converter_value: Option<Rc<dyn IMultiValueConverter>> = None,
27 converter_culture / set_converter_culture / with_converter_culture: Option<CultureInfo> = None,
30 converter_parameter / set_converter_parameter / with_converter_parameter: Option<BoxedValue> = None,
32 fallback_value / set_fallback_value / with_fallback_value: Option<BoxedValue> = Some(FerroProperty::unset_value()),
35 mode / set_mode / with_mode: BindingMode = BindingMode::OneWay,
37 priority / set_priority / with_priority: BindingPriority = BindingPriority::LocalValue,
39 relative_source / set_relative_source / with_relative_source: Option<Rc<RelativeSource>> = None,
41 string_format / set_string_format / with_string_format: Option<String> = None,
43 target_null_value / set_target_null_value / with_target_null_value: Option<BoxedValue> = Some(FerroProperty::unset_value()),
46 }
47}
48
49impl MultiBinding {
50 pub fn new() -> Rc<Self> {
52 Rc::new(Self::default())
53 }
54
55 pub fn with_bindings(self: Rc<Self>, bindings: Vec<Rc<dyn BindingBase>>) -> Rc<Self> {
58 let list = self.bindings();
59 list.clear();
60 list.add_range(bindings);
61 self
62 }
63
64 pub fn with_converter(self: Rc<Self>, converter: Rc<dyn IMultiValueConverter>) -> Rc<Self> {
67 self.with_converter_value(Some(converter))
68 }
69}
70
71impl BindingBase for MultiBinding {
72 fn as_any(&self) -> Option<&dyn std::any::Any> {
73 Some(self)
74 }
75
76 fn create_instance(
77 &self,
78 _target: &FerroObject,
79 target_property: Option<&'static FerroProperty>,
80 _anchor: Option<&Ref<FerroObject>>,
81 ) -> Rc<dyn BindingExpressionBase> {
82 let target_type = target_property.map_or_else(ValueType::object, property_value_type);
83 let mut converter = self.converter();
84
85 let string_format = self.string_format();
88 if let Some(format) = string_format.as_deref().filter(|s| !s.trim().is_empty()) {
89 if target_type.is_string() || target_type.is_object() {
90 converter = Some(Rc::new(StringFormatMultiValueConverter::new(format, converter)));
91 }
92 }
93
94 MultiBindingExpression::new(
95 self.priority(),
96 self.bindings().to_vec(),
97 converter,
98 self.converter_culture(),
99 self.converter_parameter(),
100 self.fallback_value(),
101 self.target_null_value(),
102 )
103 }
104}