Skip to main content

ferroui_base/markup_types/
plain.rs

1//! Markup metadata of the plain (non object-model) classes and of the
2//! collections of this crate that markup can name, construct or add to.
3//!
4//! A collection is a shared handle (the type itself); a plain class is held
5//! through `Rc`.
6
7use crate::utilities::CultureInfo;
8use crate::animation::{IAnimation, IAnimationSetter, ITransition, KeyFrame, KeyFrames, Transitions};
9use crate::collections::{FerroDictionary, FerroList};
10use crate::data::core::ValueTypes;
11use crate::data::{
12    BindingBase, BindingMode, BindingOperations, BindingPriority, CompiledBinding, CompiledBindingPath, MultiBinding, ReflectionBinding,
13    RelativeSource, RelativeSourceMode, TemplateBinding, TreeType, UpdateSourceTrigger,
14};
15use crate::ferro_markup_type;
16use crate::controls::{IResourceProvider, IThemeVariantProvider, ResourceKey};
17use crate::data::converters::{
18    BoolConverters, DefaultValueConverter, IMultiValueConverter, IValueConverter, ObjectConverters, StringConverters,
19    StringFormatMultiValueConverter, StringFormatValueConverter,
20};
21use crate::input::{InputScopeName, KeyBinding};
22use crate::input::gesture_recognizers::{GestureRecognizer, GestureRecognizerCollection};
23use crate::interactivity::{RoutedEvent, RoutingStrategies};
24use crate::media::{
25    Drawing, DrawingCollection, Geometry, GeometryCollection, GradientStop, GradientStops, MediaCollection,
26    PathFigure, PathFigures, PathSegment, PathSegments, Points, Transform, Transforms,
27};
28use crate::media::transformation::TransformOperations;
29use crate::metadata::{from_markup_value, MarkupType, MarkupTyped};
30use crate::styling::{
31    IStyle, ITemplate, Selector, Setter, SetterBase, SetterValue, StyleChildren, StyleQuery, TargetPropertyPath,
32    ThemeVariant,
33};
34use crate::utilities::NumberFormatInfo;
35use crate::{BoxedValue, FerroProperty, Point, Ref, TypeInfo};
36use std::rc::Rc;
37
38/// The key of a resource from the untyped key markup gives: the managed
39/// original takes any object; the port has text keys, type keys and keys that
40/// already are a [`ResourceKey`] (a theme variant is used through its key).
41pub(super) fn resource_key(key: Option<BoxedValue>) -> Result<ResourceKey, String> {
42    let Some(key) = key else {
43        return Err("The key of a resource cannot be null.".to_string());
44    };
45    if let Some(text) = key.downcast_ref::<String>() {
46        Ok(ResourceKey::from(text.as_str()))
47    } else if let Some(type_) = key.downcast_ref::<&'static TypeInfo>() {
48        Ok(ResourceKey::from(*type_))
49    } else if let Some(key) = key.downcast_ref::<ResourceKey>() {
50        Ok(key.clone())
51    } else if let Some(variant) = key.downcast_ref::<crate::styling::ThemeVariant>() {
52        Ok(variant.key().clone())
53    } else {
54        Err(format!("A value of type '{}' cannot be the key of a resource.", key.type_name()))
55    }
56}
57
58/// The key of a resource as the object it is in the managed original: the text of a
59/// string key, the type of a type key, the key itself otherwise.
60pub(super) fn resource_key_value(key: &ResourceKey) -> Option<BoxedValue> {
61    Some(match key {
62        ResourceKey::String(text) => Rc::new(text.to_string()),
63        ResourceKey::Type(type_) => Rc::new(*type_),
64        ResourceKey::Object(_) => Rc::new(key.clone()),
65    })
66}
67
68/// An untyped value as a value of exactly the type of `property`, as the
69/// property system takes it. Only assignable values are accepted: converting
70/// (parsing, numeric conversion) is the business of the caller.
71pub(super) fn property_value(property: &'static FerroProperty, value: Option<BoxedValue>) -> Result<BoxedValue, String> {
72    let type_ = crate::data::core::ValueType::new(property.property_type(), property.property_type_name());
73    // The unset value is a value of every property.
74    if let Some(unset) = value.as_ref().filter(|value| value.is::<crate::UnsetValueType>()) {
75        return Ok(unset.clone());
76    }
77    let exact = match &value {
78        Some(value) => ValueTypes::try_cast(value, type_),
79        None => ValueTypes::null_value(type_),
80    };
81    exact.ok_or_else(|| format!("The value is not assignable to the property '{}' ({type_}).", property.name()))
82}
83
84/// The key for adding a resource to `dictionary`: adding a key twice is an
85/// error, as in the managed original.
86pub(super) fn new_resource_key(
87    dictionary: &Ref<crate::controls::ResourceDictionary>,
88    key: Option<BoxedValue>,
89) -> Result<ResourceKey, String> {
90    let key = resource_key(key)?;
91    if dictionary.contains_key(&key) {
92        return Err(format!("An item with the same key has already been added. Key: {key}"));
93    }
94    Ok(key)
95}
96
97/// `FerroList<T>.Capacity`.
98fn list_capacity<T: Clone>(list: &FerroList<T>) -> i32 {
99    i32::try_from(list.capacity()).unwrap_or(i32::MAX)
100}
101
102/// The setter of `FerroList<T>.Capacity`: a capacity below the number of
103/// items is an error, as in the managed original.
104fn set_list_capacity<T: Clone>(list: &FerroList<T>, capacity: i32) -> Result<(), &'static str> {
105    match usize::try_from(capacity) {
106        Ok(capacity) if capacity >= list.count() => Ok(list.set_capacity(capacity)),
107        _ => Err("capacity was less than the current size."),
108    }
109}
110
111// System
112
113// A runtime type: the `Type` of the managed original.
114ferro_markup_type!(class TypeInfo as "Type" {
115    this: &'static TypeInfo,
116    namespace: "System",
117    handles: [&'static TypeInfo, Option<&'static TypeInfo>],
118    properties: [
119        Name: String { get: |type_: &&'static TypeInfo| type_.name().to_string() },
120        Namespace: String { get: |type_: &&'static TypeInfo| type_.namespace().to_string() },
121        FullName: String { get: |type_: &&'static TypeInfo| type_.full_name() },
122        BaseType: Option<&'static TypeInfo> { get: |type_: &&'static TypeInfo| type_.base_type() },
123    ],
124});
125
126// System.Globalization
127
128// The mirror of the runtime library's number format, which markup creates as a resource for the
129// `NumberFormat` of numeric inputs (the colour view of the colour picker). Its numeric
130// properties are settable; the text properties are not declared.
131ferro_markup_type!(class NumberFormatInfo {
132    namespace: "System.Globalization",
133    handles: [Rc<NumberFormatInfo>, Option<Rc<NumberFormatInfo>>],
134    this: Rc<NumberFormatInfo>,
135    constructors: [() => || Rc::new(NumberFormatInfo::new())],
136    properties: [
137        CurrencyDecimalDigits: i32 {
138            get: |info: &Rc<NumberFormatInfo>| info.currency_decimal_digits(),
139            set: |info: &Rc<NumberFormatInfo>, value: i32| info.set_currency_decimal_digits(value)
140        },
141        CurrencyNegativePattern: i32 {
142            get: |info: &Rc<NumberFormatInfo>| info.currency_negative_pattern(),
143            set: |info: &Rc<NumberFormatInfo>, value: i32| info.set_currency_negative_pattern(value)
144        },
145        CurrencyPositivePattern: i32 {
146            get: |info: &Rc<NumberFormatInfo>| info.currency_positive_pattern(),
147            set: |info: &Rc<NumberFormatInfo>, value: i32| info.set_currency_positive_pattern(value)
148        },
149        NumberDecimalDigits: i32 {
150            get: |info: &Rc<NumberFormatInfo>| info.number_decimal_digits(),
151            set: |info: &Rc<NumberFormatInfo>, value: i32| info.set_number_decimal_digits(value)
152        },
153        NumberNegativePattern: i32 {
154            get: |info: &Rc<NumberFormatInfo>| info.number_negative_pattern(),
155            set: |info: &Rc<NumberFormatInfo>, value: i32| info.set_number_negative_pattern(value)
156        },
157        PercentDecimalDigits: i32 {
158            get: |info: &Rc<NumberFormatInfo>| info.percent_decimal_digits(),
159            set: |info: &Rc<NumberFormatInfo>, value: i32| info.set_percent_decimal_digits(value)
160        },
161        PercentNegativePattern: i32 {
162            get: |info: &Rc<NumberFormatInfo>| info.percent_negative_pattern(),
163            set: |info: &Rc<NumberFormatInfo>, value: i32| info.set_percent_negative_pattern(value)
164        },
165        PercentPositivePattern: i32 {
166            get: |info: &Rc<NumberFormatInfo>| info.percent_positive_pattern(),
167            set: |info: &Rc<NumberFormatInfo>, value: i32| info.set_percent_positive_pattern(value)
168        },
169    ],
170});
171
172// FerroUI
173
174ferro_markup_type!(class FerroProperty {
175    this: &'static FerroProperty,
176    namespace: "FerroUI",
177    handles: [&'static FerroProperty, Option<&'static FerroProperty>],
178    properties: [
179        Name: String { get: |property: &&'static FerroProperty| property.name().to_string() },
180        OwnerType: &'static TypeInfo { get: |property: &&'static FerroProperty| property.owner_type() },
181    ],
182    // The marker of an unset property value.
183    fields: [UnsetValue: crate::UnsetValueType => || crate::UnsetValueType],
184});
185
186// FerroUI.Data
187
188// The marker that tells a binding target to do nothing is any object in the managed original.
189ferro_markup_type!(static BindingOperations {
190    namespace: "FerroUI.Data",
191    fields: [DoNothing: Option<BoxedValue> => || Some(BindingOperations::do_nothing())],
192});
193
194// FerroUI.Interactivity
195
196// A routed event without the type of its arguments: what the typed handles
197// (`RoutedEvent<TappedEventArgs>`, the static values of the classes) denote.
198ferro_markup_type!(class RoutedEvent as "RoutedEvent" {
199    namespace: "FerroUI.Interactivity",
200    handles: [RoutedEvent, Option<RoutedEvent>],
201    properties: [
202        Name: String { get: |event: &RoutedEvent| event.name().to_string() },
203        OwnerType: &'static TypeInfo { get: RoutedEvent::owner_type },
204        RoutingStrategies: RoutingStrategies { get: RoutedEvent::routing_strategies },
205    ],
206});
207
208// FerroUI.Styling
209
210/// Whether a template is a value of `property` itself (`ITemplate` is
211/// assignable from the type of the property), as opposed to what builds
212/// its value.
213fn is_template_property(property: &'static FerroProperty) -> bool {
214    let type_ = crate::data::core::ValueType::new(property.property_type(), property.property_type_name());
215    ValueTypes::is_assignable(type_, crate::data::core::ValueType::of::<Option<Rc<dyn ITemplate>>>())
216}
217
218/// `Setter.Value` of the managed original holds any object; what the setter
219/// does with it follows from its type, as `Setter.Instance` decides there: a
220/// binding is bound, a template builds the value unless the property itself
221/// holds templates, anything else is the value. The object may arrive in
222/// any of its forms (its concrete handle, the handle of a contract, an "any
223/// value" box holding either).
224fn set_setter_value(setter: &Rc<Setter>, value: Option<BoxedValue>) {
225    let property = setter.property();
226    setter.set_value(value.map(|value| {
227        let object = match value.downcast_ref::<Option<BoxedValue>>() {
228            Some(contents) => contents.clone(),
229            None => Some(value.clone()),
230        };
231        if let Some(binding) = from_markup_value::<Rc<dyn BindingBase>>(&object) {
232            SetterValue::BindingBase(binding)
233        } else if let Some(template) =
234            from_markup_value::<Rc<dyn ITemplate>>(&object).filter(|_| !property.is_some_and(is_template_property))
235        {
236            SetterValue::Template(template)
237        } else {
238            // The value of the property: what is assignable to its type is held as a value
239            // of exactly that type (the setter requires it); anything else is kept as it
240            // is, and reported by the setter when the style is applied.
241            let exact = property.and_then(|property| {
242                property_value(property, Some(value.clone())).or_else(|_| property_value(property, object.clone())).ok()
243            });
244            SetterValue::Value(exact.unwrap_or(value))
245        }
246    }));
247}
248
249/// The value of a setter as the object it was set to. (A setter bound to a
250/// plain source of values, which markup cannot create, reads as null.)
251fn setter_value(setter: &Rc<Setter>) -> Option<BoxedValue> {
252    match setter.value()? {
253        SetterValue::Value(value) => Some(value),
254        SetterValue::BindingBase(binding) => Some(Rc::new(binding)),
255        SetterValue::Template(template) => Some(Rc::new(template)),
256        SetterValue::Binding(_) => None,
257    }
258}
259
260fn new_setter(property: &'static FerroProperty, value: Option<BoxedValue>) -> Rc<Setter> {
261    let setter = Setter::empty();
262    setter.set_property(Some(property));
263    set_setter_value(&setter, value);
264    setter
265}
266
267ferro_markup_type!(class Setter {
268    namespace: "FerroUI.Styling",
269    handles: [Rc<Setter>, Option<Rc<Setter>>],
270    this: Rc<Setter>,
271    base: Rc<dyn SetterBase>,
272    interfaces: [Rc<dyn IAnimationSetter>],
273    content: Value,
274    constructors: [
275        () => Setter::empty,
276        (&'static FerroProperty, Option<BoxedValue>) => new_setter,
277    ],
278    properties: [
279        Property: Option<&'static FerroProperty> { get: Setter::property, set: Setter::set_property },
280        Value: Option<BoxedValue> { get: setter_value, set: set_setter_value } [AssignBinding, DependsOn("Property")],
281        // WinUI's `Setter.Target` (an addition, docs/porting/winui-calculator-gaps.md): the
282        // compiler writes it from the text `Element.Property` of a setter of a visual state.
283        Target: Option<Rc<TargetPropertyPath>> { get: Setter::target, set: Setter::set_target },
284    ],
285});
286
287// WinUI's `TargetPropertyPath` (an addition): the element of a setter of a visual state,
288// resolved by name in the name scope of the document or the template.
289ferro_markup_type!(class TargetPropertyPath {
290    namespace: "FerroUI.Styling",
291    handles: [Rc<TargetPropertyPath>, Option<Rc<TargetPropertyPath>>],
292    this: Rc<TargetPropertyPath>,
293    constructors: [() => TargetPropertyPath::empty],
294    properties: [
295        Path: String {
296            get: |this: &Rc<TargetPropertyPath>| this.path(),
297            set: |this: &Rc<TargetPropertyPath>, value: String| this.set_path(value)
298        },
299        // The name of the target element, resolved when the setter applies (WinUI's target name).
300        TargetName: String {
301            get: |this: &Rc<TargetPropertyPath>| this.target_name(),
302            set: |this: &Rc<TargetPropertyPath>, value: String| this.set_target_name(value)
303        },
304        Property: Option<&'static FerroProperty> {
305            get: |this: &Rc<TargetPropertyPath>| this.property(),
306            set: |this: &Rc<TargetPropertyPath>, value: Option<&'static FerroProperty>| this.set_property(value)
307        },
308        Target: Option<Ref<crate::FerroObject>> {
309            get: |this: &Rc<TargetPropertyPath>| this.target(),
310            set: |this: &Rc<TargetPropertyPath>, value: Option<Ref<crate::FerroObject>>| this.set_target(value)
311        } [ResolveByName],
312    ],
313});
314
315ferro_markup_type!(class Selector {
316    namespace: "FerroUI.Styling",
317    handles: [Selector, Option<Selector>],
318});
319
320ferro_markup_type!(class StyleQuery {
321    namespace: "FerroUI.Styling",
322    handles: [StyleQuery, Option<StyleQuery>],
323});
324
325// The children of a style.
326ferro_markup_type!(class StyleChildren {
327    namespace: "FerroUI.Styling",
328    handles: [StyleChildren, Option<StyleChildren>],
329    properties: [Count: i32 { get: |children: &StyleChildren| children.count() as i32 }],
330    methods: [fn Add(Rc<dyn IStyle>) => |children: &StyleChildren, style: Rc<dyn IStyle>| children.add(style)],
331});
332
333// FerroUI.Data
334
335ferro_markup_type!(class RelativeSource {
336    namespace: "FerroUI.Data",
337    handles: [Rc<RelativeSource>, Option<Rc<RelativeSource>>],
338    this: Rc<RelativeSource>,
339    constructors: [
340        () => RelativeSource::empty,
341        (RelativeSourceMode) => RelativeSource::new,
342    ],
343    properties: [
344        AncestorLevel: i32 { get: RelativeSource::ancestor_level, set: RelativeSource::set_ancestor_level },
345        AncestorType: Option<&'static TypeInfo> {
346            get: RelativeSource::ancestor_type,
347            set: RelativeSource::set_ancestor_type
348        },
349        Mode: RelativeSourceMode { get: RelativeSource::mode, set: RelativeSource::set_mode },
350        Tree: TreeType { get: RelativeSource::tree, set: RelativeSource::set_tree },
351    ],
352});
353
354ferro_markup_type!(class CompiledBinding {
355    namespace: "FerroUI.Data",
356    handles: [Rc<CompiledBinding>, Option<Rc<CompiledBinding>>],
357    this: Rc<CompiledBinding>,
358    base: Rc<dyn BindingBase>,
359    constructors: [
360        () => CompiledBinding::empty,
361        (CompiledBindingPath) => CompiledBinding::new,
362    ],
363    properties: [
364        Delay: i32 { get: CompiledBinding::delay, set: CompiledBinding::set_delay },
365        Converter: Option<Rc<dyn IValueConverter>> { get: CompiledBinding::converter, set: CompiledBinding::set_converter },
366        ConverterCulture: Option<CultureInfo> {
367            get: CompiledBinding::converter_culture,
368            set: CompiledBinding::set_converter_culture
369        },
370        ConverterParameter: Option<BoxedValue> {
371            get: CompiledBinding::converter_parameter,
372            set: CompiledBinding::set_converter_parameter
373        },
374        FallbackValue: Option<BoxedValue> {
375            get: CompiledBinding::fallback_value,
376            set: CompiledBinding::set_fallback_value
377        },
378        Mode: BindingMode { get: CompiledBinding::mode, set: CompiledBinding::set_mode },
379        Path: Option<CompiledBindingPath> { get: CompiledBinding::path, set: CompiledBinding::set_path }
380            [ConstructorArgument("path")],
381        Priority: BindingPriority { get: CompiledBinding::priority, set: CompiledBinding::set_priority },
382        Source: Option<BoxedValue> { get: CompiledBinding::source, set: CompiledBinding::set_source },
383        StringFormat: Option<String> { get: CompiledBinding::string_format, set: CompiledBinding::set_string_format },
384        TargetNullValue: Option<BoxedValue> {
385            get: CompiledBinding::target_null_value,
386            set: CompiledBinding::set_target_null_value
387        },
388        UpdateSourceTrigger: UpdateSourceTrigger {
389            get: CompiledBinding::update_source_trigger,
390            set: CompiledBinding::set_update_source_trigger
391        },
392    ],
393});
394
395ferro_markup_type!(class ReflectionBinding {
396    namespace: "FerroUI.Data",
397    handles: [Rc<ReflectionBinding>, Option<Rc<ReflectionBinding>>],
398    this: Rc<ReflectionBinding>,
399    base: Rc<dyn BindingBase>,
400    constructors: [
401        () => ReflectionBinding::empty,
402        (String) => |path: String| ReflectionBinding::new(&path),
403    ],
404    properties: [
405        Delay: i32 { get: ReflectionBinding::delay, set: ReflectionBinding::set_delay },
406        Converter: Option<Rc<dyn IValueConverter>> {
407            get: ReflectionBinding::converter,
408            set: ReflectionBinding::set_converter
409        },
410        ConverterCulture: Option<CultureInfo> {
411            get: ReflectionBinding::converter_culture,
412            set: ReflectionBinding::set_converter_culture
413        },
414        ConverterParameter: Option<BoxedValue> {
415            get: ReflectionBinding::converter_parameter,
416            set: ReflectionBinding::set_converter_parameter
417        },
418        ElementName: Option<String> { get: ReflectionBinding::element_name, set: ReflectionBinding::set_element_name },
419        FallbackValue: Option<BoxedValue> {
420            get: ReflectionBinding::fallback_value,
421            set: ReflectionBinding::set_fallback_value
422        },
423        Mode: BindingMode { get: ReflectionBinding::mode, set: ReflectionBinding::set_mode },
424        Path: String { get: ReflectionBinding::path, set: ReflectionBinding::set_path } [ConstructorArgument("path")],
425        Priority: BindingPriority { get: ReflectionBinding::priority, set: ReflectionBinding::set_priority },
426        RelativeSource: Option<Rc<RelativeSource>> {
427            get: ReflectionBinding::relative_source,
428            set: ReflectionBinding::set_relative_source
429        },
430        Source: Option<BoxedValue> { get: ReflectionBinding::source, set: ReflectionBinding::set_source },
431        StringFormat: Option<String> {
432            get: ReflectionBinding::string_format,
433            set: ReflectionBinding::set_string_format
434        },
435        TargetNullValue: Option<BoxedValue> {
436            get: ReflectionBinding::target_null_value,
437            set: ReflectionBinding::set_target_null_value
438        },
439        UpdateSourceTrigger: UpdateSourceTrigger {
440            get: ReflectionBinding::update_source_trigger,
441            set: ReflectionBinding::set_update_source_trigger
442        },
443    ],
444});
445
446ferro_markup_type!(class MultiBinding {
447    namespace: "FerroUI.Data",
448    handles: [Rc<MultiBinding>, Option<Rc<MultiBinding>>],
449    this: Rc<MultiBinding>,
450    base: Rc<dyn BindingBase>,
451    content: Bindings,
452    constructors: [() => MultiBinding::new],
453    properties: [
454        Bindings: FerroList<Rc<dyn BindingBase>> { get: MultiBinding::bindings, set: MultiBinding::set_bindings }
455            [AssignBinding],
456        Converter: Option<Rc<dyn IMultiValueConverter>> { get: MultiBinding::converter, set: MultiBinding::set_converter },
457        ConverterCulture: Option<CultureInfo> {
458            get: MultiBinding::converter_culture,
459            set: MultiBinding::set_converter_culture
460        },
461        ConverterParameter: Option<BoxedValue> {
462            get: MultiBinding::converter_parameter,
463            set: MultiBinding::set_converter_parameter
464        },
465        FallbackValue: Option<BoxedValue> { get: MultiBinding::fallback_value, set: MultiBinding::set_fallback_value },
466        TargetNullValue: Option<BoxedValue> {
467            get: MultiBinding::target_null_value,
468            set: MultiBinding::set_target_null_value
469        },
470        Mode: BindingMode { get: MultiBinding::mode, set: MultiBinding::set_mode },
471        Priority: BindingPriority { get: MultiBinding::priority, set: MultiBinding::set_priority },
472        RelativeSource: Option<Rc<RelativeSource>> {
473            get: MultiBinding::relative_source,
474            set: MultiBinding::set_relative_source
475        },
476        StringFormat: Option<String> { get: MultiBinding::string_format, set: MultiBinding::set_string_format },
477    ],
478});
479
480ferro_markup_type!(class TemplateBinding {
481    namespace: "FerroUI.Data",
482    handles: [Rc<TemplateBinding>, Option<Rc<TemplateBinding>>],
483    this: Rc<TemplateBinding>,
484    base: Rc<dyn BindingBase>,
485    constructors: [
486        () => TemplateBinding::empty,
487        (property: &'static FerroProperty [InheritDataTypeFrom(2)]) => TemplateBinding::new,
488    ],
489    properties: [
490        Converter: Option<Rc<dyn IValueConverter>> { get: TemplateBinding::converter, set: TemplateBinding::set_converter },
491        ConverterCulture: Option<CultureInfo> {
492            get: TemplateBinding::converter_culture,
493            set: TemplateBinding::set_converter_culture
494        },
495        ConverterParameter: Option<BoxedValue> {
496            get: TemplateBinding::converter_parameter,
497            set: TemplateBinding::set_converter_parameter
498        },
499        Mode: BindingMode { get: TemplateBinding::mode, set: TemplateBinding::set_mode },
500        // The argument of `InheritDataTypeFrom` is `InheritDataTypeFromScopeKind.ControlTemplate` (2).
501        Property: Option<&'static FerroProperty> { get: TemplateBinding::property, set: TemplateBinding::set_property }
502            [ConstructorArgument("property"), InheritDataTypeFrom(2)],
503    ],
504    // The binding is its own markup extension: it provides itself, as a binding.
505    methods: [
506        fn ProvideValue() -> Rc<dyn BindingBase> =>
507            |this: &Rc<TemplateBinding>| -> Rc<dyn BindingBase> { this.clone() },
508    ],
509});
510
511// FerroUI.Data.Converters
512
513ferro_markup_type!(static ObjectConverters {
514    namespace: "FerroUI.Data.Converters",
515    fields: [
516        IsNull: Rc<dyn IValueConverter> => ObjectConverters::is_null,
517        IsNotNull: Rc<dyn IValueConverter> => ObjectConverters::is_not_null,
518        Equal: Rc<dyn IValueConverter> => ObjectConverters::equal,
519        NotEqual: Rc<dyn IValueConverter> => ObjectConverters::not_equal,
520        AreAllNull: Rc<dyn IMultiValueConverter> => ObjectConverters::are_all_null,
521        AreAnyNull: Rc<dyn IMultiValueConverter> => ObjectConverters::are_any_null,
522        AreAllEqual: Rc<dyn IMultiValueConverter> => ObjectConverters::are_all_equal,
523    ],
524});
525
526ferro_markup_type!(static BoolConverters {
527    namespace: "FerroUI.Data.Converters",
528    fields: [
529        And: Rc<dyn IMultiValueConverter> => BoolConverters::and,
530        Or: Rc<dyn IMultiValueConverter> => BoolConverters::or,
531        Not: Rc<dyn IValueConverter> => BoolConverters::not,
532    ],
533});
534
535ferro_markup_type!(static StringConverters {
536    namespace: "FerroUI.Data.Converters",
537    fields: [
538        IsNullOrEmpty: Rc<dyn IValueConverter> => StringConverters::is_null_or_empty,
539        IsNotNullOrEmpty: Rc<dyn IValueConverter> => StringConverters::is_not_null_or_empty,
540    ],
541});
542
543// The converter classes are reference types: an instance equals itself.
544impl PartialEq for DefaultValueConverter {
545    fn eq(&self, other: &Self) -> bool {
546        std::ptr::eq(self, other)
547    }
548}
549
550impl PartialEq for StringFormatValueConverter {
551    fn eq(&self, other: &Self) -> bool {
552        std::ptr::eq(self, other)
553    }
554}
555
556impl PartialEq for StringFormatMultiValueConverter {
557    fn eq(&self, other: &Self) -> bool {
558        std::ptr::eq(self, other)
559    }
560}
561
562// The static instance is held through the converter contract in this port.
563ferro_markup_type!(class DefaultValueConverter {
564    namespace: "FerroUI.Data.Converters",
565    handles: [Rc<DefaultValueConverter>, Option<Rc<DefaultValueConverter>>],
566    interfaces: [Rc<dyn IValueConverter>],
567    fields: [Instance: Rc<dyn IValueConverter> => DefaultValueConverter::instance],
568});
569
570ferro_markup_type!(class StringFormatValueConverter {
571    namespace: "FerroUI.Data.Converters",
572    handles: [Rc<StringFormatValueConverter>, Option<Rc<StringFormatValueConverter>>],
573    this: Rc<StringFormatValueConverter>,
574    interfaces: [Rc<dyn IValueConverter>],
575    constructors: [
576        (String, Option<Rc<dyn IValueConverter>>) => |format: String, inner: Option<Rc<dyn IValueConverter>>| {
577            Rc::new(StringFormatValueConverter::new(format, inner))
578        },
579    ],
580    properties: [
581        Inner: Option<Rc<dyn IValueConverter>> { get: |c: &Rc<StringFormatValueConverter>| c.inner().cloned() },
582        Format: String { get: |c: &Rc<StringFormatValueConverter>| c.format().to_string() },
583    ],
584});
585
586ferro_markup_type!(class StringFormatMultiValueConverter {
587    namespace: "FerroUI.Data.Converters",
588    handles: [Rc<StringFormatMultiValueConverter>, Option<Rc<StringFormatMultiValueConverter>>],
589    this: Rc<StringFormatMultiValueConverter>,
590    interfaces: [Rc<dyn IMultiValueConverter>],
591    constructors: [
592        (String, Option<Rc<dyn IMultiValueConverter>>) =>
593            |format: String, inner: Option<Rc<dyn IMultiValueConverter>>| {
594                Rc::new(StringFormatMultiValueConverter::new(format, inner))
595            },
596    ],
597    properties: [
598        Inner: Option<Rc<dyn IMultiValueConverter>> {
599            get: |c: &Rc<StringFormatMultiValueConverter>| c.inner().cloned()
600        },
601        Format: String { get: |c: &Rc<StringFormatMultiValueConverter>| c.format().to_string() },
602    ],
603});
604
605// FerroUI.Animation
606
607ferro_markup_type!(class KeyFrames {
608    namespace: "FerroUI.Animation",
609    handles: [KeyFrames, Option<KeyFrames>],
610    base: FerroList<Ref<KeyFrame>>,
611    constructors: [() => KeyFrames::new],
612    methods: [fn Add(Ref<KeyFrame>) => |frames: &KeyFrames, frame: Ref<KeyFrame>| frames.add(frame)],
613});
614
615ferro_markup_type!(class Transitions {
616    namespace: "FerroUI.Animation",
617    handles: [Transitions, Option<Transitions>],
618    base: FerroList<Rc<dyn ITransition>>,
619    constructors: [() => Transitions::new],
620    methods: [
621        fn Add(Rc<dyn ITransition>) => |transitions: &Transitions, item: Rc<dyn ITransition>| transitions.add(item),
622    ],
623});
624
625// FerroUI.Input.GestureRecognizers
626
627ferro_markup_type!(class GestureRecognizerCollection {
628    namespace: "FerroUI.Input.GestureRecognizers",
629    handles: [GestureRecognizerCollection, Option<GestureRecognizerCollection>],
630    methods: [
631        fn Add(Ref<GestureRecognizer>) =>
632            |recognizers: &GestureRecognizerCollection, item: Ref<GestureRecognizer>| recognizers.add(item),
633    ],
634});
635
636// FerroUI.Media
637
638ferro_markup_type!(class GradientStops {
639    namespace: "FerroUI.Media",
640    handles: [GradientStops, Option<GradientStops>],
641    base: FerroList<Ref<GradientStop>>,
642    constructors: [() => GradientStops::new],
643    methods: [fn Add(Ref<GradientStop>) => |stops: &GradientStops, item: Ref<GradientStop>| stops.add(item)],
644});
645
646ferro_markup_type!(class PathFigures {
647    namespace: "FerroUI.Media",
648    handles: [PathFigures, Option<PathFigures>],
649    base: FerroList<Ref<PathFigure>>,
650    parse: PathFigures::parse,
651    constructors: [() => PathFigures::new],
652    methods: [fn Add(Ref<PathFigure>) => |figures: &PathFigures, item: Ref<PathFigure>| figures.add(item)],
653});
654
655ferro_markup_type!(class PathSegments {
656    namespace: "FerroUI.Media",
657    handles: [PathSegments, Option<PathSegments>],
658    base: FerroList<Ref<PathSegment>>,
659    constructors: [() => PathSegments::new],
660    methods: [fn Add(Ref<PathSegment>) => |segments: &PathSegments, item: Ref<PathSegment>| segments.add(item)],
661});
662
663ferro_markup_type!(class Points {
664    namespace: "FerroUI",
665    handles: [Points, Option<Points>],
666    base: FerroList<Point>,
667    constructors: [() => Points::new],
668    methods: [fn Add(Point) => |points: &Points, item: Point| points.add(item)],
669});
670
671ferro_markup_type!(class GeometryCollection {
672    namespace: "FerroUI.Media",
673    handles: [GeometryCollection, Option<GeometryCollection>],
674    base: FerroList<Ref<Geometry>>,
675    constructors: [() => GeometryCollection::new],
676    methods: [
677        fn Add(Ref<Geometry>) => |geometries: &GeometryCollection, item: Ref<Geometry>| geometries.add(item),
678    ],
679});
680
681ferro_markup_type!(class Transforms {
682    namespace: "FerroUI.Media",
683    handles: [Transforms, Option<Transforms>],
684    base: FerroList<Ref<Transform>>,
685    constructors: [() => Transforms::new],
686    methods: [fn Add(Ref<Transform>) => |transforms: &Transforms, item: Ref<Transform>| transforms.add(item)],
687});
688
689ferro_markup_type!(class DrawingCollection {
690    namespace: "FerroUI.Media",
691    handles: [DrawingCollection, Option<DrawingCollection>],
692    base: FerroList<Ref<Drawing>>,
693    constructors: [() => DrawingCollection::new],
694    methods: [fn Add(Ref<Drawing>) => |drawings: &DrawingCollection, item: Ref<Drawing>| drawings.add(item)],
695});
696
697// The font manager: markup names the current one (`{x:Static FontManager.Current}`) and binds
698// to the fonts of the system.
699ferro_markup_type!(class crate::media::FontManager as "FontManager" {
700    namespace: "FerroUI.Media",
701    handles: [Rc<crate::media::FontManager>, Option<Rc<crate::media::FontManager>>],
702    this: Rc<crate::media::FontManager>,
703    properties: [
704        DefaultFontFamily: crate::media::FontFamily {
705            get: |font_manager: &Rc<crate::media::FontManager>| font_manager.default_font_family().clone()
706        },
707        SystemFonts: Rc<dyn crate::media::fonts::IFontCollection> {
708            get: |font_manager: &Rc<crate::media::FontManager>| font_manager.system_fonts()
709        },
710    ],
711    static_properties: [Current: Rc<crate::media::FontManager> { get: crate::media::FontManager::current }],
712});
713
714// FerroUI.Media.Transformation
715
716// A list of transform operations: the text content of an element is its text form.
717ferro_markup_type!(class TransformOperations {
718    namespace: "FerroUI.Media.Transformation",
719    handles: [Rc<TransformOperations>, Option<Rc<TransformOperations>>],
720    this: Rc<TransformOperations>,
721    interfaces: [Rc<dyn crate::media::ITransform>],
722    parse: TransformOperations::parse,
723    properties: [
724        IsIdentity: bool { get: |operations: &Rc<TransformOperations>| operations.is_identity() },
725        Value: crate::Matrix { get: |operations: &Rc<TransformOperations>| operations.value() },
726    ],
727    static_properties: [Identity: Rc<TransformOperations> { get: TransformOperations::identity }],
728});
729
730// FerroUI.Collections
731
732// The list of numbers of dash arrays and tick lists.
733ferro_markup_type!(class MediaCollection<f64> as "FerroList`1" {
734    namespace: "FerroUI.Collections",
735    handles: [MediaCollection<f64>, Option<MediaCollection<f64>>],
736    generic: "FerroList`1" [f64],
737    constructors: [() => MediaCollection::<f64>::new],
738    properties: [
739        Capacity: i32 {
740            get: |list: &MediaCollection<f64>| list_capacity(list.list()),
741            try_set: |list: &MediaCollection<f64>, capacity: i32| set_list_capacity(list.list(), capacity)
742        },
743        Count: i32 { get: |list: &MediaCollection<f64>| list.len() as i32 },
744    ],
745    methods: [fn Add(f64) => |list: &MediaCollection<f64>, item: f64| list.add(item)],
746});
747
748// The instantiations of the notifying list that are types of properties.
749
750ferro_markup_type!(class FerroList<Rc<dyn IAnimationSetter>> as "FerroList`1" {
751    namespace: "FerroUI.Collections",
752    handles: [FerroList<Rc<dyn IAnimationSetter>>, Option<FerroList<Rc<dyn IAnimationSetter>>>],
753    generic: "FerroList`1" [Rc<dyn IAnimationSetter>],
754    constructors: [() => FerroList::<Rc<dyn IAnimationSetter>>::new],
755    properties: [
756        Capacity: i32 { get: list_capacity, try_set: set_list_capacity },
757        Count: i32 { get: |list: &FerroList<Rc<dyn IAnimationSetter>>| list.count() as i32 },
758    ],
759    methods: [fn Add(Rc<dyn IAnimationSetter>) => |list: &FerroList<Rc<dyn IAnimationSetter>>, item: Rc<dyn IAnimationSetter>| list.add(item)],
760});
761
762ferro_markup_type!(class FerroList<Rc<dyn IResourceProvider>> as "FerroList`1" {
763    namespace: "FerroUI.Collections",
764    handles: [FerroList<Rc<dyn IResourceProvider>>, Option<FerroList<Rc<dyn IResourceProvider>>>],
765    generic: "FerroList`1" [Rc<dyn IResourceProvider>],
766    constructors: [() => FerroList::<Rc<dyn IResourceProvider>>::new],
767    properties: [
768        Capacity: i32 { get: list_capacity, try_set: set_list_capacity },
769        Count: i32 { get: |list: &FerroList<Rc<dyn IResourceProvider>>| list.count() as i32 },
770    ],
771    methods: [fn Add(Rc<dyn IResourceProvider>) => |list: &FerroList<Rc<dyn IResourceProvider>>, item: Rc<dyn IResourceProvider>| list.add(item)],
772});
773
774ferro_markup_type!(class FerroList<Ref<InputScopeName>> as "FerroList`1" {
775    namespace: "FerroUI.Collections",
776    handles: [FerroList<Ref<InputScopeName>>, Option<FerroList<Ref<InputScopeName>>>],
777    generic: "FerroList`1" [Ref<InputScopeName>],
778    constructors: [() => FerroList::<Ref<InputScopeName>>::new],
779    properties: [
780        Capacity: i32 { get: list_capacity, try_set: set_list_capacity },
781        Count: i32 { get: |list: &FerroList<Ref<InputScopeName>>| list.count() as i32 },
782    ],
783    methods: [fn Add(Ref<InputScopeName>) => |list: &FerroList<Ref<InputScopeName>>, item: Ref<InputScopeName>| list.add(item)],
784});
785
786ferro_markup_type!(class FerroList<Ref<KeyBinding>> as "FerroList`1" {
787    namespace: "FerroUI.Collections",
788    handles: [FerroList<Ref<KeyBinding>>, Option<FerroList<Ref<KeyBinding>>>],
789    generic: "FerroList`1" [Ref<KeyBinding>],
790    constructors: [() => FerroList::<Ref<KeyBinding>>::new],
791    properties: [
792        Capacity: i32 { get: list_capacity, try_set: set_list_capacity },
793        Count: i32 { get: |list: &FerroList<Ref<KeyBinding>>| list.count() as i32 },
794    ],
795    methods: [fn Add(Ref<KeyBinding>) => |list: &FerroList<Ref<KeyBinding>>, item: Ref<KeyBinding>| list.add(item)],
796});
797
798ferro_markup_type!(class FerroList<Rc<dyn SetterBase>> as "FerroList`1" {
799    namespace: "FerroUI.Collections",
800    handles: [FerroList<Rc<dyn SetterBase>>, Option<FerroList<Rc<dyn SetterBase>>>],
801    generic: "FerroList`1" [Rc<dyn SetterBase>],
802    constructors: [() => FerroList::<Rc<dyn SetterBase>>::new],
803    properties: [
804        Capacity: i32 { get: list_capacity, try_set: set_list_capacity },
805        Count: i32 { get: |list: &FerroList<Rc<dyn SetterBase>>| list.count() as i32 },
806    ],
807    methods: [fn Add(Rc<dyn SetterBase>) => |list: &FerroList<Rc<dyn SetterBase>>, item: Rc<dyn SetterBase>| list.add(item)],
808});
809
810ferro_markup_type!(class FerroList<Rc<dyn IAnimation>> as "FerroList`1" {
811    namespace: "FerroUI.Collections",
812    handles: [FerroList<Rc<dyn IAnimation>>, Option<FerroList<Rc<dyn IAnimation>>>],
813    generic: "FerroList`1" [Rc<dyn IAnimation>],
814    constructors: [() => FerroList::<Rc<dyn IAnimation>>::new],
815    properties: [
816        Capacity: i32 { get: list_capacity, try_set: set_list_capacity },
817        Count: i32 { get: |list: &FerroList<Rc<dyn IAnimation>>| list.count() as i32 },
818    ],
819    methods: [fn Add(Rc<dyn IAnimation>) => |list: &FerroList<Rc<dyn IAnimation>>, item: Rc<dyn IAnimation>| list.add(item)],
820});
821
822ferro_markup_type!(class FerroList<Rc<dyn BindingBase>> as "FerroList`1" {
823    namespace: "FerroUI.Collections",
824    handles: [FerroList<Rc<dyn BindingBase>>, Option<FerroList<Rc<dyn BindingBase>>>],
825    generic: "FerroList`1" [Rc<dyn BindingBase>],
826    constructors: [() => FerroList::<Rc<dyn BindingBase>>::new],
827    properties: [
828        Capacity: i32 { get: list_capacity, try_set: set_list_capacity },
829        Count: i32 { get: |list: &FerroList<Rc<dyn BindingBase>>| list.count() as i32 },
830    ],
831    methods: [fn Add(Rc<dyn BindingBase>) => |list: &FerroList<Rc<dyn BindingBase>>, item: Rc<dyn BindingBase>| list.add(item)],
832});
833
834// The lists the named collections derive from.
835
836ferro_markup_type!(class FerroList<Point> as "FerroList`1" {
837    namespace: "FerroUI.Collections",
838    handles: [FerroList<Point>, Option<FerroList<Point>>],
839    generic: "FerroList`1" [Point],
840    constructors: [() => FerroList::<Point>::new],
841    properties: [
842        Capacity: i32 { get: list_capacity, try_set: set_list_capacity },
843        Count: i32 { get: |list: &FerroList<Point>| list.count() as i32 },
844    ],
845    methods: [fn Add(Point) => |list: &FerroList<Point>, item: Point| list.add(item)],
846});
847
848ferro_markup_type!(class FerroList<String> as "FerroList`1" {
849    namespace: "FerroUI.Collections",
850    handles: [FerroList<String>, Option<FerroList<String>>],
851    generic: "FerroList`1" [String],
852    constructors: [() => FerroList::<String>::new],
853    properties: [
854        Capacity: i32 { get: list_capacity, try_set: set_list_capacity },
855        Count: i32 { get: |list: &FerroList<String>| list.count() as i32 },
856    ],
857    methods: [fn Add(String) => |list: &FerroList<String>, item: String| list.add(item)],
858});
859
860ferro_markup_type!(class FerroList<Ref<GradientStop>> as "FerroList`1" {
861    namespace: "FerroUI.Collections",
862    handles: [FerroList<Ref<GradientStop>>, Option<FerroList<Ref<GradientStop>>>],
863    generic: "FerroList`1" [Ref<GradientStop>],
864    constructors: [() => FerroList::<Ref<GradientStop>>::new],
865    properties: [
866        Capacity: i32 { get: list_capacity, try_set: set_list_capacity },
867        Count: i32 { get: |list: &FerroList<Ref<GradientStop>>| list.count() as i32 },
868    ],
869    methods: [fn Add(Ref<GradientStop>) => |list: &FerroList<Ref<GradientStop>>, item: Ref<GradientStop>| list.add(item)],
870});
871
872ferro_markup_type!(class FerroList<Rc<dyn ITransition>> as "FerroList`1" {
873    namespace: "FerroUI.Collections",
874    handles: [FerroList<Rc<dyn ITransition>>, Option<FerroList<Rc<dyn ITransition>>>],
875    generic: "FerroList`1" [Rc<dyn ITransition>],
876    constructors: [() => FerroList::<Rc<dyn ITransition>>::new],
877    properties: [
878        Capacity: i32 { get: list_capacity, try_set: set_list_capacity },
879        Count: i32 { get: |list: &FerroList<Rc<dyn ITransition>>| list.count() as i32 },
880    ],
881    methods: [fn Add(Rc<dyn ITransition>) => |list: &FerroList<Rc<dyn ITransition>>, item: Rc<dyn ITransition>| list.add(item)],
882});
883
884ferro_markup_type!(class FerroList<Ref<KeyFrame>> as "FerroList`1" {
885    namespace: "FerroUI.Collections",
886    handles: [FerroList<Ref<KeyFrame>>, Option<FerroList<Ref<KeyFrame>>>],
887    generic: "FerroList`1" [Ref<KeyFrame>],
888    constructors: [() => FerroList::<Ref<KeyFrame>>::new],
889    properties: [
890        Capacity: i32 { get: list_capacity, try_set: set_list_capacity },
891        Count: i32 { get: |list: &FerroList<Ref<KeyFrame>>| list.count() as i32 },
892    ],
893    methods: [fn Add(Ref<KeyFrame>) => |list: &FerroList<Ref<KeyFrame>>, item: Ref<KeyFrame>| list.add(item)],
894});
895
896ferro_markup_type!(class FerroList<Ref<PathFigure>> as "FerroList`1" {
897    namespace: "FerroUI.Collections",
898    handles: [FerroList<Ref<PathFigure>>, Option<FerroList<Ref<PathFigure>>>],
899    generic: "FerroList`1" [Ref<PathFigure>],
900    constructors: [() => FerroList::<Ref<PathFigure>>::new],
901    properties: [
902        Capacity: i32 { get: list_capacity, try_set: set_list_capacity },
903        Count: i32 { get: |list: &FerroList<Ref<PathFigure>>| list.count() as i32 },
904    ],
905    methods: [fn Add(Ref<PathFigure>) => |list: &FerroList<Ref<PathFigure>>, item: Ref<PathFigure>| list.add(item)],
906});
907
908ferro_markup_type!(class FerroList<Ref<PathSegment>> as "FerroList`1" {
909    namespace: "FerroUI.Collections",
910    handles: [FerroList<Ref<PathSegment>>, Option<FerroList<Ref<PathSegment>>>],
911    generic: "FerroList`1" [Ref<PathSegment>],
912    constructors: [() => FerroList::<Ref<PathSegment>>::new],
913    properties: [
914        Capacity: i32 { get: list_capacity, try_set: set_list_capacity },
915        Count: i32 { get: |list: &FerroList<Ref<PathSegment>>| list.count() as i32 },
916    ],
917    methods: [fn Add(Ref<PathSegment>) => |list: &FerroList<Ref<PathSegment>>, item: Ref<PathSegment>| list.add(item)],
918});
919
920ferro_markup_type!(class FerroList<Ref<Drawing>> as "FerroList`1" {
921    namespace: "FerroUI.Collections",
922    handles: [FerroList<Ref<Drawing>>, Option<FerroList<Ref<Drawing>>>],
923    generic: "FerroList`1" [Ref<Drawing>],
924    constructors: [() => FerroList::<Ref<Drawing>>::new],
925    properties: [
926        Capacity: i32 { get: list_capacity, try_set: set_list_capacity },
927        Count: i32 { get: |list: &FerroList<Ref<Drawing>>| list.count() as i32 },
928    ],
929    methods: [fn Add(Ref<Drawing>) => |list: &FerroList<Ref<Drawing>>, item: Ref<Drawing>| list.add(item)],
930});
931
932ferro_markup_type!(class FerroList<Ref<Transform>> as "FerroList`1" {
933    namespace: "FerroUI.Collections",
934    handles: [FerroList<Ref<Transform>>, Option<FerroList<Ref<Transform>>>],
935    generic: "FerroList`1" [Ref<Transform>],
936    constructors: [() => FerroList::<Ref<Transform>>::new],
937    properties: [
938        Capacity: i32 { get: list_capacity, try_set: set_list_capacity },
939        Count: i32 { get: |list: &FerroList<Ref<Transform>>| list.count() as i32 },
940    ],
941    methods: [fn Add(Ref<Transform>) => |list: &FerroList<Ref<Transform>>, item: Ref<Transform>| list.add(item)],
942});
943
944ferro_markup_type!(class FerroList<Ref<Geometry>> as "FerroList`1" {
945    namespace: "FerroUI.Collections",
946    handles: [FerroList<Ref<Geometry>>, Option<FerroList<Ref<Geometry>>>],
947    generic: "FerroList`1" [Ref<Geometry>],
948    constructors: [() => FerroList::<Ref<Geometry>>::new],
949    properties: [
950        Capacity: i32 { get: list_capacity, try_set: set_list_capacity },
951        Count: i32 { get: |list: &FerroList<Ref<Geometry>>| list.count() as i32 },
952    ],
953    methods: [fn Add(Ref<Geometry>) => |list: &FerroList<Ref<Geometry>>, item: Ref<Geometry>| list.add(item)],
954});
955
956ferro_markup_type!(class FerroList<crate::media::FontFeature> as "FerroList`1" {
957    namespace: "FerroUI.Collections",
958    handles: [FerroList<crate::media::FontFeature>, Option<FerroList<crate::media::FontFeature>>],
959    generic: "FerroList`1" [crate::media::FontFeature],
960    constructors: [() => FerroList::<crate::media::FontFeature>::new],
961    properties: [
962        Capacity: i32 { get: list_capacity, try_set: set_list_capacity },
963        Count: i32 { get: |list: &FerroList<crate::media::FontFeature>| list.count() as i32 },
964    ],
965    methods: [fn Add(crate::media::FontFeature) => |list: &FerroList<crate::media::FontFeature>, item: crate::media::FontFeature| list.add(item)],
966});
967
968ferro_markup_type!(class FerroList<Ref<crate::media::TextDecoration>> as "FerroList`1" {
969    namespace: "FerroUI.Collections",
970    handles: [FerroList<Ref<crate::media::TextDecoration>>, Option<FerroList<Ref<crate::media::TextDecoration>>>],
971    generic: "FerroList`1" [Ref<crate::media::TextDecoration>],
972    constructors: [() => FerroList::<Ref<crate::media::TextDecoration>>::new],
973    properties: [
974        Capacity: i32 { get: list_capacity, try_set: set_list_capacity },
975        Count: i32 { get: |list: &FerroList<Ref<crate::media::TextDecoration>>| list.count() as i32 },
976    ],
977    methods: [fn Add(Ref<crate::media::TextDecoration>) => |list: &FerroList<Ref<crate::media::TextDecoration>>, item: Ref<crate::media::TextDecoration>| list.add(item)],
978});
979
980// The theme dictionaries of a resource dictionary.
981ferro_markup_type!(class FerroDictionary<ThemeVariant, Rc<dyn IThemeVariantProvider>> as "FerroDictionary`2" {
982    namespace: "FerroUI.Collections",
983    handles: [
984        FerroDictionary<ThemeVariant, Rc<dyn IThemeVariantProvider>>,
985        Option<FerroDictionary<ThemeVariant, Rc<dyn IThemeVariantProvider>>>,
986    ],
987    generic: "FerroDictionary`2" [ThemeVariant, Rc<dyn IThemeVariantProvider>],
988    properties: [
989        Count: i32 { get: |d: &FerroDictionary<ThemeVariant, Rc<dyn IThemeVariantProvider>>| d.count() as i32 },
990    ],
991    methods: [
992        // Adding a key twice is an error, as in the managed original.
993        try fn Add(ThemeVariant, Rc<dyn IThemeVariantProvider>) =>
994            |d: &FerroDictionary<ThemeVariant, Rc<dyn IThemeVariantProvider>>,
995             key: ThemeVariant,
996             value: Rc<dyn IThemeVariantProvider>| {
997                if d.contains_key(&key) {
998                    return Err(format!("An item with the same key has already been added. Key: {key}"));
999                }
1000                Ok(d.add(key, value))
1001            },
1002    ],
1003});
1004
1005/// The types declared in this file.
1006pub(super) const TYPES: &[&MarkupType] = &[
1007    <TypeInfo as MarkupTyped>::MARKUP,
1008    <FerroProperty as MarkupTyped>::MARKUP,
1009    <NumberFormatInfo as MarkupTyped>::MARKUP,
1010    <BindingOperations as MarkupTyped>::MARKUP,
1011    <RoutedEvent as MarkupTyped>::MARKUP,
1012    <Setter as MarkupTyped>::MARKUP,
1013    <TargetPropertyPath as MarkupTyped>::MARKUP,
1014    <Selector as MarkupTyped>::MARKUP,
1015    <StyleQuery as MarkupTyped>::MARKUP,
1016    <StyleChildren as MarkupTyped>::MARKUP,
1017    <RelativeSource as MarkupTyped>::MARKUP,
1018    <CompiledBinding as MarkupTyped>::MARKUP,
1019    <ReflectionBinding as MarkupTyped>::MARKUP,
1020    <MultiBinding as MarkupTyped>::MARKUP,
1021    <TemplateBinding as MarkupTyped>::MARKUP,
1022    <ObjectConverters as MarkupTyped>::MARKUP,
1023    <BoolConverters as MarkupTyped>::MARKUP,
1024    <StringConverters as MarkupTyped>::MARKUP,
1025    <DefaultValueConverter as MarkupTyped>::MARKUP,
1026    <StringFormatValueConverter as MarkupTyped>::MARKUP,
1027    <StringFormatMultiValueConverter as MarkupTyped>::MARKUP,
1028    <KeyFrames as MarkupTyped>::MARKUP,
1029    <Transitions as MarkupTyped>::MARKUP,
1030    <GestureRecognizerCollection as MarkupTyped>::MARKUP,
1031    <GradientStops as MarkupTyped>::MARKUP,
1032    <PathFigures as MarkupTyped>::MARKUP,
1033    <PathSegments as MarkupTyped>::MARKUP,
1034    <Points as MarkupTyped>::MARKUP,
1035    <GeometryCollection as MarkupTyped>::MARKUP,
1036    <Transforms as MarkupTyped>::MARKUP,
1037    <DrawingCollection as MarkupTyped>::MARKUP,
1038    <TransformOperations as MarkupTyped>::MARKUP,
1039    <crate::media::FontManager as MarkupTyped>::MARKUP,
1040    <MediaCollection<f64> as MarkupTyped>::MARKUP,
1041    <FerroList<Rc<dyn IAnimationSetter>> as MarkupTyped>::MARKUP,
1042    <FerroList<Rc<dyn IResourceProvider>> as MarkupTyped>::MARKUP,
1043    <FerroList<Ref<KeyBinding>> as MarkupTyped>::MARKUP,
1044    <FerroList<Rc<dyn SetterBase>> as MarkupTyped>::MARKUP,
1045    <FerroList<Rc<dyn IAnimation>> as MarkupTyped>::MARKUP,
1046    <FerroList<Rc<dyn BindingBase>> as MarkupTyped>::MARKUP,
1047    <FerroList<Point> as MarkupTyped>::MARKUP,
1048    <FerroList<String> as MarkupTyped>::MARKUP,
1049    <FerroList<Ref<GradientStop>> as MarkupTyped>::MARKUP,
1050    <FerroList<Rc<dyn ITransition>> as MarkupTyped>::MARKUP,
1051    <FerroList<Ref<KeyFrame>> as MarkupTyped>::MARKUP,
1052    <FerroList<Ref<InputScopeName>> as MarkupTyped>::MARKUP,
1053    <FerroList<Ref<PathFigure>> as MarkupTyped>::MARKUP,
1054    <FerroList<Ref<PathSegment>> as MarkupTyped>::MARKUP,
1055    <FerroList<Ref<Drawing>> as MarkupTyped>::MARKUP,
1056    <FerroList<Ref<Transform>> as MarkupTyped>::MARKUP,
1057    <FerroList<Ref<Geometry>> as MarkupTyped>::MARKUP,
1058    <FerroList<crate::media::FontFeature> as MarkupTyped>::MARKUP,
1059    <FerroList<Ref<crate::media::TextDecoration>> as MarkupTyped>::MARKUP,
1060    <FerroDictionary<ThemeVariant, Rc<dyn IThemeVariantProvider>> as MarkupTyped>::MARKUP,
1061];
1062
1063/// Registers the nullable forms of the types that can be held in untyped
1064/// values with the untyped value conversions of the current thread.
1065pub(super) fn register_value_types() {
1066    ValueTypes::register_nullable::<&'static TypeInfo>();
1067    ValueTypes::register_nullable::<&'static FerroProperty>();
1068    // The vectors of the element types markup has arrays of (the elements of the runtime
1069    // library and the values the markup compiler parses a list of): a property that holds
1070    // one is null without it (`Option<Vec<T>>`). The run-time XAML loader states the same
1071    // nine when its type system is created; a process that loads compiled markup alone
1072    // never creates one, and reads such a property all the same.
1073    ValueTypes::register_nullable::<Vec<bool>>();
1074    ValueTypes::register_nullable::<Vec<u8>>();
1075    ValueTypes::register_nullable::<Vec<i32>>();
1076    ValueTypes::register_nullable::<Vec<i64>>();
1077    ValueTypes::register_nullable::<Vec<f32>>();
1078    ValueTypes::register_nullable::<Vec<f64>>();
1079    ValueTypes::register_nullable::<Vec<String>>();
1080    ValueTypes::register_nullable::<Vec<Point>>();
1081    ValueTypes::register_nullable::<Vec<BoxedValue>>();
1082    ValueTypes::register_nullable::<Rc<NumberFormatInfo>>();
1083    ValueTypes::register_nullable::<Transitions>();
1084    ValueTypes::register_nullable::<GradientStops>();
1085    ValueTypes::register_nullable::<PathFigures>();
1086    ValueTypes::register_nullable::<PathSegments>();
1087    ValueTypes::register_nullable::<Points>();
1088    ValueTypes::register_nullable::<GeometryCollection>();
1089    ValueTypes::register_nullable::<Transforms>();
1090    ValueTypes::register_nullable::<DrawingCollection>();
1091    ValueTypes::register_nullable::<MediaCollection<f64>>();
1092    ValueTypes::register_nullable::<RoutedEvent>();
1093    ValueTypes::register_nullable::<FerroList<Point>>();
1094    ValueTypes::register_nullable::<FerroList<String>>();
1095    ValueTypes::register_nullable::<FerroList<Ref<GradientStop>>>();
1096    ValueTypes::register_nullable::<FerroList<Rc<dyn ITransition>>>();
1097    ValueTypes::register_nullable::<FerroList<Ref<KeyFrame>>>();
1098    ValueTypes::register_nullable::<FerroList<Ref<InputScopeName>>>();
1099    ValueTypes::register_nullable::<FerroList<Ref<PathFigure>>>();
1100    ValueTypes::register_nullable::<FerroList<Ref<PathSegment>>>();
1101    ValueTypes::register_nullable::<FerroList<Ref<Drawing>>>();
1102    ValueTypes::register_nullable::<FerroList<Ref<Transform>>>();
1103    ValueTypes::register_nullable::<FerroList<Ref<Geometry>>>();
1104    ValueTypes::register_nullable::<Selector>();
1105    ValueTypes::register_nullable::<StyleQuery>();
1106    ValueTypes::register_nullable::<StyleChildren>();
1107    ValueTypes::register_nullable::<KeyFrames>();
1108    ValueTypes::register_nullable::<GestureRecognizerCollection>();
1109    ValueTypes::register_nullable::<Rc<Setter>>();
1110    ValueTypes::register_nullable::<Rc<TargetPropertyPath>>();
1111    ValueTypes::register_nullable::<Rc<RelativeSource>>();
1112    ValueTypes::register_nullable::<Rc<CompiledBinding>>();
1113    ValueTypes::register_nullable::<Rc<ReflectionBinding>>();
1114    ValueTypes::register_nullable::<Rc<MultiBinding>>();
1115    ValueTypes::register_nullable::<Rc<TemplateBinding>>();
1116    ValueTypes::register_nullable::<FerroDictionary<ThemeVariant, Rc<dyn IThemeVariantProvider>>>();
1117    ValueTypes::register_nullable::<FerroList<Rc<dyn IAnimationSetter>>>();
1118    ValueTypes::register_nullable::<FerroList<Rc<dyn IResourceProvider>>>();
1119    ValueTypes::register_nullable::<FerroList<Ref<KeyBinding>>>();
1120    ValueTypes::register_nullable::<FerroList<Rc<dyn SetterBase>>>();
1121    ValueTypes::register_nullable::<FerroList<Rc<dyn IAnimation>>>();
1122    ValueTypes::register_nullable::<FerroList<Rc<dyn BindingBase>>>();
1123    // A named collection is the list it derives from: the same list, so that the members
1124    // of the list (`Capacity`) are reached through the collection.
1125    ValueTypes::register_cast::<KeyFrames, FerroList<Ref<KeyFrame>>>(|c| (**c).clone());
1126    ValueTypes::register_cast::<Transitions, FerroList<Rc<dyn ITransition>>>(|c| (**c).clone());
1127    ValueTypes::register_cast::<GradientStops, FerroList<Ref<GradientStop>>>(|c| (**c.list()).clone());
1128    ValueTypes::register_cast::<PathFigures, FerroList<Ref<PathFigure>>>(|c| (**c.list()).clone());
1129    ValueTypes::register_cast::<PathSegments, FerroList<Ref<PathSegment>>>(|c| (**c.list()).clone());
1130    ValueTypes::register_cast::<Points, FerroList<Point>>(|c| (**c.list()).clone());
1131    ValueTypes::register_cast::<GeometryCollection, FerroList<Ref<Geometry>>>(|c| (**c.list()).clone());
1132    ValueTypes::register_cast::<Transforms, FerroList<Ref<Transform>>>(|c| (**c.list()).clone());
1133    ValueTypes::register_cast::<DrawingCollection, FerroList<Ref<Drawing>>>(|c| (**c.list()).clone());
1134    ValueTypes::register_cast::<crate::media::FontFeatureCollection, FerroList<crate::media::FontFeature>>(|c| {
1135        (**c.list()).clone()
1136    });
1137    ValueTypes::register_cast::<crate::media::TextDecorationCollection, FerroList<Ref<crate::media::TextDecoration>>>(
1138        |c| (**c.list()).clone(),
1139    );
1140    // The named collections whose Rust type dereferences to the list: generated code
1141    // passes a reference to such a collection where a member of the list takes the list.
1142    ValueTypes::register_deref::<KeyFrames, FerroList<Ref<KeyFrame>>>(|c| c);
1143    ValueTypes::register_deref::<Transitions, FerroList<Rc<dyn ITransition>>>(|c| c);
1144    ValueTypes::register_nullable::<FerroList<crate::media::FontFeature>>();
1145    ValueTypes::register_nullable::<FerroList<Ref<crate::media::TextDecoration>>>();
1146    // A list of transform operations is a transform.
1147    ValueTypes::register_nullable::<Rc<TransformOperations>>();
1148    ValueTypes::register_nullable::<Rc<crate::media::FontManager>>();
1149    ValueTypes::register_cast::<Rc<TransformOperations>, Rc<dyn crate::media::ITransform>>(|operations| operations.clone());
1150    // A converter is a converter contract.
1151    ValueTypes::register_nullable::<Rc<DefaultValueConverter>>();
1152    ValueTypes::register_nullable::<Rc<StringFormatValueConverter>>();
1153    ValueTypes::register_nullable::<Rc<StringFormatMultiValueConverter>>();
1154    ValueTypes::register_cast::<Rc<DefaultValueConverter>, Rc<dyn IValueConverter>>(|c| c.clone());
1155    ValueTypes::register_cast::<Rc<StringFormatValueConverter>, Rc<dyn IValueConverter>>(|c| c.clone());
1156    ValueTypes::register_cast::<Rc<StringFormatMultiValueConverter>, Rc<dyn IMultiValueConverter>>(|c| c.clone());
1157    // A setter is a setter base; a binding is a binding base.
1158    ValueTypes::register_cast::<Rc<Setter>, Rc<dyn SetterBase>>(|setter| setter.clone());
1159    // A setter is also the setter of a key frame.
1160    ValueTypes::register_cast::<Rc<Setter>, Rc<dyn IAnimationSetter>>(|setter| setter.clone());
1161    ValueTypes::register_cast::<Rc<CompiledBinding>, Rc<dyn BindingBase>>(|binding| binding.clone());
1162    ValueTypes::register_cast::<Rc<ReflectionBinding>, Rc<dyn BindingBase>>(|binding| binding.clone());
1163    ValueTypes::register_cast::<Rc<MultiBinding>, Rc<dyn BindingBase>>(|binding| binding.clone());
1164    ValueTypes::register_cast::<Rc<TemplateBinding>, Rc<dyn BindingBase>>(|binding| binding.clone());
1165}