1use smol_str::{format_smolstr, SmolStr, StrExt, ToSmolStr};
7use std::cell::RefCell;
8use std::collections::{BTreeMap, HashMap, HashSet};
9use std::rc::Rc;
10
11use crate::expression_tree::BuiltinFunction;
12use crate::langtype::{
13 BuiltinElement, BuiltinPropertyDefault, BuiltinPropertyInfo, ElementType, Enumeration,
14 Function, PropertyLookupResult, Struct, Type,
15};
16use crate::object_tree::{Component, PropertyVisibility};
17use crate::typeloader;
18
19pub const RESERVED_GEOMETRY_PROPERTIES: &[(&str, Type)] = &[
20 ("x", Type::LogicalLength),
21 ("y", Type::LogicalLength),
22 ("width", Type::LogicalLength),
23 ("height", Type::LogicalLength),
24 ("z", Type::Float32),
25];
26
27pub const RESERVED_LAYOUT_PROPERTIES: &[(&str, Type)] = &[
28 ("min-width", Type::LogicalLength),
29 ("min-height", Type::LogicalLength),
30 ("max-width", Type::LogicalLength),
31 ("max-height", Type::LogicalLength),
32 ("padding", Type::LogicalLength),
33 ("padding-left", Type::LogicalLength),
34 ("padding-right", Type::LogicalLength),
35 ("padding-top", Type::LogicalLength),
36 ("padding-bottom", Type::LogicalLength),
37 ("preferred-width", Type::LogicalLength),
38 ("preferred-height", Type::LogicalLength),
39 ("horizontal-stretch", Type::Float32),
40 ("vertical-stretch", Type::Float32),
41];
42
43pub const RESERVED_GRIDLAYOUT_PROPERTIES: &[(&str, Type)] = &[
44 ("col", Type::Int32),
45 ("row", Type::Int32),
46 ("colspan", Type::Int32),
47 ("rowspan", Type::Int32),
48];
49
50macro_rules! declare_enums {
51 ($( $(#[$enum_doc:meta])* enum $Name:ident { $( $(#[$value_doc:meta])* $Value:ident,)* })*) => {
52 #[allow(non_snake_case)]
53 pub struct BuiltinEnums {
54 $(pub $Name : Rc<Enumeration>),*
55 }
56 impl BuiltinEnums {
57 fn new() -> Self {
58 Self {
59 $($Name : Rc::new(Enumeration {
60 name: stringify!($Name).replace_smolstr("_", "-"),
61 values: vec![$(crate::generator::to_kebab_case(stringify!($Value).trim_start_matches("r#")).into()),*],
62 default_value: 0,
63 node: None,
64 })),*
65 }
66 }
67 fn fill_register(&self, register: &mut TypeRegister) {
68 $(if stringify!($Name) != "PathEvent" {
69 register.insert_type_with_name(
70 Type::Enumeration(self.$Name.clone()),
71 stringify!($Name).replace_smolstr("_", "-")
72 );
73 })*
74 }
75 }
76 };
77}
78
79i_slint_common::for_each_enums!(declare_enums);
80
81pub struct BuiltinTypes {
82 pub enums: BuiltinEnums,
83 pub noarg_callback_type: Type,
84 pub strarg_callback_type: Type,
85 pub logical_point_type: Rc<Struct>,
86 pub font_metrics_type: Type,
87 pub layout_info_type: Rc<Struct>,
88 pub path_element_type: Type,
89 pub box_layout_cell_data_type: Type,
90}
91
92impl BuiltinTypes {
93 fn new() -> Self {
94 let layout_info_type = Rc::new(Struct {
95 fields: ["min", "max", "preferred"]
96 .iter()
97 .map(|s| (SmolStr::new_static(s), Type::LogicalLength))
98 .chain(
99 ["min_percent", "max_percent", "stretch"]
100 .iter()
101 .map(|s| (SmolStr::new_static(s), Type::Float32)),
102 )
103 .collect(),
104 name: Some("slint::private_api::LayoutInfo".into()),
105 node: None,
106 rust_attributes: None,
107 });
108 Self {
109 enums: BuiltinEnums::new(),
110 logical_point_type: Rc::new(Struct {
111 fields: IntoIterator::into_iter([
112 (SmolStr::new_static("x"), Type::LogicalLength),
113 (SmolStr::new_static("y"), Type::LogicalLength),
114 ])
115 .collect(),
116 name: Some("slint::LogicalPosition".into()),
117 node: None,
118 rust_attributes: None,
119 }),
120 font_metrics_type: Type::Struct(Rc::new(Struct {
121 fields: IntoIterator::into_iter([
122 (SmolStr::new_static("ascent"), Type::LogicalLength),
123 (SmolStr::new_static("descent"), Type::LogicalLength),
124 (SmolStr::new_static("x-height"), Type::LogicalLength),
125 (SmolStr::new_static("cap-height"), Type::LogicalLength),
126 ])
127 .collect(),
128 name: Some("slint::private_api::FontMetrics".into()),
129 node: None,
130 rust_attributes: None,
131 })),
132 noarg_callback_type: Type::Callback(Rc::new(Function {
133 return_type: Type::Void,
134 args: vec![],
135 arg_names: vec![],
136 })),
137 strarg_callback_type: Type::Callback(Rc::new(Function {
138 return_type: Type::Void,
139 args: vec![Type::String],
140 arg_names: vec![],
141 })),
142 layout_info_type: layout_info_type.clone(),
143 path_element_type: Type::Struct(Rc::new(Struct {
144 fields: Default::default(),
145 name: Some("PathElement".into()),
146 node: None,
147 rust_attributes: None,
148 })),
149 box_layout_cell_data_type: Type::Struct(Rc::new(Struct {
150 fields: IntoIterator::into_iter([("constraint".into(), layout_info_type.into())])
151 .collect(),
152 name: Some("BoxLayoutCellData".into()),
153 node: None,
154 rust_attributes: None,
155 })),
156 }
157 }
158}
159
160thread_local! {
161 pub static BUILTIN: BuiltinTypes = BuiltinTypes::new();
162}
163
164const RESERVED_OTHER_PROPERTIES: &[(&str, Type)] = &[
165 ("clip", Type::Bool),
166 ("opacity", Type::Float32),
167 ("cache-rendering-hint", Type::Bool),
168 ("visible", Type::Bool), ];
170
171pub const RESERVED_DROP_SHADOW_PROPERTIES: &[(&str, Type)] = &[
172 ("drop-shadow-offset-x", Type::LogicalLength),
173 ("drop-shadow-offset-y", Type::LogicalLength),
174 ("drop-shadow-blur", Type::LogicalLength),
175 ("drop-shadow-color", Type::Color),
176];
177
178pub const RESERVED_TRANSFORM_PROPERTIES: &[(&str, Type)] = &[
179 ("transform-rotation", Type::Angle),
180 ("transform-scale-x", Type::Float32),
181 ("transform-scale-y", Type::Float32),
182 ("transform-scale", Type::Float32),
183];
184
185pub fn transform_origin_property() -> (&'static str, Rc<Struct>) {
186 ("transform-origin", logical_point_type())
187}
188
189pub const DEPRECATED_ROTATION_ORIGIN_PROPERTIES: [(&str, Type); 2] =
190 [("rotation-origin-x", Type::LogicalLength), ("rotation-origin-y", Type::LogicalLength)];
191
192pub fn noarg_callback_type() -> Type {
193 BUILTIN.with(|types| types.noarg_callback_type.clone())
194}
195
196fn strarg_callback_type() -> Type {
197 BUILTIN.with(|types| types.strarg_callback_type.clone())
198}
199
200pub fn reserved_accessibility_properties() -> impl Iterator<Item = (&'static str, Type)> {
201 [
202 ("accessible-checkable", Type::Bool),
204 ("accessible-checked", Type::Bool),
205 ("accessible-delegate-focus", Type::Int32),
206 ("accessible-description", Type::String),
207 ("accessible-enabled", Type::Bool),
208 ("accessible-expandable", Type::Bool),
209 ("accessible-expanded", Type::Bool),
210 ("accessible-label", Type::String),
211 ("accessible-value", Type::String),
212 ("accessible-value-maximum", Type::Float32),
213 ("accessible-value-minimum", Type::Float32),
214 ("accessible-value-step", Type::Float32),
215 ("accessible-placeholder-text", Type::String),
216 ("accessible-action-default", noarg_callback_type()),
217 ("accessible-action-increment", noarg_callback_type()),
218 ("accessible-action-decrement", noarg_callback_type()),
219 ("accessible-action-set-value", strarg_callback_type()),
220 ("accessible-action-expand", noarg_callback_type()),
221 ("accessible-item-selectable", Type::Bool),
222 ("accessible-item-selected", Type::Bool),
223 ("accessible-item-index", Type::Int32),
224 ("accessible-item-count", Type::Int32),
225 ("accessible-read-only", Type::Bool),
226 ]
227 .into_iter()
228}
229
230pub fn reserved_properties() -> impl Iterator<Item = (&'static str, Type, PropertyVisibility)> {
232 RESERVED_GEOMETRY_PROPERTIES
233 .iter()
234 .chain(RESERVED_LAYOUT_PROPERTIES.iter())
235 .chain(RESERVED_OTHER_PROPERTIES.iter())
236 .chain(RESERVED_DROP_SHADOW_PROPERTIES.iter())
237 .chain(RESERVED_TRANSFORM_PROPERTIES.iter())
238 .chain(DEPRECATED_ROTATION_ORIGIN_PROPERTIES.iter())
239 .map(|(k, v)| (*k, v.clone(), PropertyVisibility::Input))
240 .chain(
241 std::iter::once(transform_origin_property())
242 .map(|(k, v)| (k, v.into(), PropertyVisibility::Input)),
243 )
244 .chain(reserved_accessibility_properties().map(|(k, v)| (k, v, PropertyVisibility::Input)))
245 .chain(
246 RESERVED_GRIDLAYOUT_PROPERTIES
247 .iter()
248 .map(|(k, v)| (*k, v.clone(), PropertyVisibility::Constexpr)),
249 )
250 .chain(IntoIterator::into_iter([
251 ("absolute-position", logical_point_type().into(), PropertyVisibility::Output),
252 ("forward-focus", Type::ElementReference, PropertyVisibility::Constexpr),
253 (
254 "focus",
255 Type::Function(BuiltinFunction::SetFocusItem.ty()),
256 PropertyVisibility::Public,
257 ),
258 (
259 "clear-focus",
260 Type::Function(BuiltinFunction::ClearFocusItem.ty()),
261 PropertyVisibility::Public,
262 ),
263 (
264 "dialog-button-role",
265 Type::Enumeration(BUILTIN.with(|e| e.enums.DialogButtonRole.clone())),
266 PropertyVisibility::Constexpr,
267 ),
268 (
269 "accessible-role",
270 Type::Enumeration(BUILTIN.with(|e| e.enums.AccessibleRole.clone())),
271 PropertyVisibility::Constexpr,
272 ),
273 ]))
274 .chain(std::iter::once(("init", noarg_callback_type(), PropertyVisibility::Private)))
275}
276
277pub fn reserved_property(name: std::borrow::Cow<'_, str>) -> PropertyLookupResult<'_> {
279 thread_local! {
280 static RESERVED_PROPERTIES: HashMap<&'static str, (Type, PropertyVisibility, Option<BuiltinFunction>)>
281 = reserved_properties().map(|(name, ty, visibility)| (name, (ty, visibility, reserved_member_function(name)))).collect();
282 }
283 if let Some((ty, visibility, builtin_function)) =
284 RESERVED_PROPERTIES.with(|reserved| reserved.get(name.as_ref()).cloned())
285 {
286 return PropertyLookupResult {
287 property_type: ty,
288 resolved_name: name,
289 is_local_to_component: false,
290 is_in_direct_base: false,
291 property_visibility: visibility,
292 declared_pure: None,
293 builtin_function,
294 };
295 }
296
297 for pre in &["min", "max"] {
299 if let Some(a) = name.strip_prefix(pre) {
300 for suf in &["width", "height"] {
301 if let Some(b) = a.strip_suffix(suf) {
302 if b == "imum-" {
303 return PropertyLookupResult {
304 property_type: Type::LogicalLength,
305 resolved_name: format!("{pre}-{suf}").into(),
306 is_local_to_component: false,
307 is_in_direct_base: false,
308 property_visibility: crate::object_tree::PropertyVisibility::InOut,
309 declared_pure: None,
310 builtin_function: None,
311 };
312 }
313 }
314 }
315 }
316 }
317 PropertyLookupResult::invalid(name)
318}
319
320pub fn reserved_member_function(name: &str) -> Option<BuiltinFunction> {
322 for (m, e) in [
323 ("focus", BuiltinFunction::SetFocusItem), ("clear-focus", BuiltinFunction::ClearFocusItem), ] {
326 if m == name {
327 return Some(e);
328 }
329 }
330 None
331}
332
333#[derive(Debug, Default)]
334pub struct TypeRegister {
335 types: HashMap<SmolStr, Type>,
337 elements: HashMap<SmolStr, ElementType>,
339 supported_property_animation_types: HashSet<String>,
340 pub(crate) property_animation_type: ElementType,
341 pub(crate) empty_type: ElementType,
342 context_restricted_types: HashMap<SmolStr, HashSet<SmolStr>>,
345 parent_registry: Option<Rc<RefCell<TypeRegister>>>,
346 pub(crate) expose_internal_types: bool,
348}
349
350impl TypeRegister {
351 pub(crate) fn snapshot(&self, snapshotter: &mut typeloader::Snapshotter) -> Self {
352 Self {
353 types: self.types.clone(),
354 elements: self
355 .elements
356 .iter()
357 .map(|(k, v)| (k.clone(), snapshotter.snapshot_element_type(v)))
358 .collect(),
359 supported_property_animation_types: self.supported_property_animation_types.clone(),
360 property_animation_type: snapshotter
361 .snapshot_element_type(&self.property_animation_type),
362 empty_type: snapshotter.snapshot_element_type(&self.empty_type),
363 context_restricted_types: self.context_restricted_types.clone(),
364 parent_registry: self
365 .parent_registry
366 .as_ref()
367 .map(|tr| snapshotter.snapshot_type_register(tr)),
368 expose_internal_types: self.expose_internal_types,
369 }
370 }
371
372 pub fn insert_type(&mut self, t: Type) -> bool {
376 self.types.insert(t.to_smolstr(), t).is_none()
377 }
378 pub fn insert_type_with_name(&mut self, t: Type, name: SmolStr) -> bool {
382 self.types.insert(name, t).is_none()
383 }
384
385 fn builtin_internal() -> Self {
386 let mut register = TypeRegister::default();
387
388 register.insert_type(Type::Float32);
389 register.insert_type(Type::Int32);
390 register.insert_type(Type::String);
391 register.insert_type(Type::PhysicalLength);
392 register.insert_type(Type::LogicalLength);
393 register.insert_type(Type::Color);
394 register.insert_type(Type::ComponentFactory);
395 register.insert_type(Type::Duration);
396 register.insert_type(Type::Image);
397 register.insert_type(Type::Bool);
398 register.insert_type(Type::Model);
399 register.insert_type(Type::Percent);
400 register.insert_type(Type::Easing);
401 register.insert_type(Type::Angle);
402 register.insert_type(Type::Brush);
403 register.insert_type(Type::Rem);
404 register.types.insert("Point".into(), logical_point_type().into());
405
406 BUILTIN.with(|e| e.enums.fill_register(&mut register));
407
408 register.supported_property_animation_types.insert(Type::Float32.to_string());
409 register.supported_property_animation_types.insert(Type::Int32.to_string());
410 register.supported_property_animation_types.insert(Type::Color.to_string());
411 register.supported_property_animation_types.insert(Type::PhysicalLength.to_string());
412 register.supported_property_animation_types.insert(Type::LogicalLength.to_string());
413 register.supported_property_animation_types.insert(Type::Brush.to_string());
414 register.supported_property_animation_types.insert(Type::Angle.to_string());
415
416 #[rustfmt::skip]
417 macro_rules! map_type {
418 ($pub_type:ident, bool) => { Type::Bool };
419 ($pub_type:ident, i32) => { Type::Int32 };
420 ($pub_type:ident, f32) => { Type::Float32 };
421 ($pub_type:ident, SharedString) => { Type::String };
422 ($pub_type:ident, Image) => { Type::Image };
423 ($pub_type:ident, Coord) => { Type::LogicalLength };
424 ($pub_type:ident, LogicalPosition) => { Type::Struct(logical_point_type()) };
425 ($pub_type:ident, KeyboardModifiers) => { $pub_type.clone() };
426 ($pub_type:ident, $_:ident) => {
427 BUILTIN.with(|e| Type::Enumeration(e.enums.$pub_type.clone()))
428 };
429 }
430 #[rustfmt::skip]
431 macro_rules! maybe_clone {
432 ($pub_type:ident, KeyboardModifiers) => { $pub_type.clone() };
433 ($pub_type:ident, $_:ident) => { $pub_type };
434 }
435 macro_rules! register_builtin_structs {
436 ($(
437 $(#[$attr:meta])*
438 struct $Name:ident {
439 @name = $inner_name:literal
440 export {
441 $( $(#[$pub_attr:meta])* $pub_field:ident : $pub_type:ident, )*
442 }
443 private {
444 $( $(#[$pri_attr:meta])* $pri_field:ident : $pri_type:ty, )*
445 }
446 }
447 )*) => { $(
448 #[allow(non_snake_case)]
449 let $Name = Type::Struct(Rc::new(Struct{
450 fields: BTreeMap::from([
451 $((stringify!($pub_field).replace_smolstr("_", "-"), map_type!($pub_type, $pub_type))),*
452 ]),
453 name: Some(format_smolstr!("{}", $inner_name)),
454 node: None,
455 rust_attributes: None,
456 }));
457 register.insert_type_with_name(maybe_clone!($Name, $Name), SmolStr::new(stringify!($Name)));
458 )* };
459 }
460 i_slint_common::for_each_builtin_structs!(register_builtin_structs);
461
462 crate::load_builtins::load_builtins(&mut register);
463
464 for e in register.elements.values() {
465 if let ElementType::Builtin(b) = e {
466 for accepted_child_type_name in b.additional_accepted_child_types.keys() {
467 register
468 .context_restricted_types
469 .entry(accepted_child_type_name.clone())
470 .or_default()
471 .insert(b.native_class.class_name.clone());
472 }
473 if b.additional_accept_self {
474 register
475 .context_restricted_types
476 .entry(b.native_class.class_name.clone())
477 .or_default()
478 .insert(b.native_class.class_name.clone());
479 }
480 }
481 }
482
483 match &mut register.elements.get_mut("PopupWindow").unwrap() {
484 ElementType::Builtin(ref mut b) => {
485 let popup = Rc::get_mut(b).unwrap();
486 popup.properties.insert(
487 "show".into(),
488 BuiltinPropertyInfo::from(BuiltinFunction::ShowPopupWindow),
489 );
490
491 popup.properties.insert(
492 "close".into(),
493 BuiltinPropertyInfo::from(BuiltinFunction::ClosePopupWindow),
494 );
495
496 popup.properties.get_mut("close-on-click").unwrap().property_visibility =
497 PropertyVisibility::Constexpr;
498
499 popup.properties.get_mut("close-policy").unwrap().property_visibility =
500 PropertyVisibility::Constexpr;
501 }
502 _ => unreachable!(),
503 };
504
505 match &mut register.elements.get_mut("Timer").unwrap() {
506 ElementType::Builtin(ref mut b) => {
507 let timer = Rc::get_mut(b).unwrap();
508 timer
509 .properties
510 .insert("start".into(), BuiltinPropertyInfo::from(BuiltinFunction::StartTimer));
511 timer
512 .properties
513 .insert("stop".into(), BuiltinPropertyInfo::from(BuiltinFunction::StopTimer));
514 timer.properties.insert(
515 "restart".into(),
516 BuiltinPropertyInfo::from(BuiltinFunction::RestartTimer),
517 );
518 }
519 _ => unreachable!(),
520 }
521
522 let font_metrics_prop = crate::langtype::BuiltinPropertyInfo {
523 ty: font_metrics_type(),
524 property_visibility: PropertyVisibility::Output,
525 default_value: BuiltinPropertyDefault::WithElement(|elem| {
526 crate::expression_tree::Expression::FunctionCall {
527 function: BuiltinFunction::ItemFontMetrics.into(),
528 arguments: vec![crate::expression_tree::Expression::ElementReference(
529 Rc::downgrade(elem),
530 )],
531 source_location: None,
532 }
533 }),
534 };
535
536 match &mut register.elements.get_mut("TextInput").unwrap() {
537 ElementType::Builtin(ref mut b) => {
538 let text_input = Rc::get_mut(b).unwrap();
539 text_input.properties.insert(
540 "set-selection-offsets".into(),
541 BuiltinPropertyInfo::from(BuiltinFunction::SetSelectionOffsets),
542 );
543 text_input.properties.insert("font-metrics".into(), font_metrics_prop.clone());
544 }
545
546 _ => unreachable!(),
547 };
548
549 match &mut register.elements.get_mut("Text").unwrap() {
550 ElementType::Builtin(ref mut b) => {
551 let text = Rc::get_mut(b).unwrap();
552 text.properties.insert("font-metrics".into(), font_metrics_prop);
553 }
554
555 _ => unreachable!(),
556 };
557
558 match &mut register.elements.get_mut("Path").unwrap() {
559 ElementType::Builtin(ref mut b) => {
560 let path = Rc::get_mut(b).unwrap();
561 path.properties.get_mut("commands").unwrap().property_visibility =
562 PropertyVisibility::Fake;
563 }
564
565 _ => unreachable!(),
566 };
567
568 register
569 }
570
571 #[doc(hidden)]
572 pub fn builtin_experimental() -> Rc<RefCell<Self>> {
574 let register = Self::builtin_internal();
575 Rc::new(RefCell::new(register))
576 }
577
578 pub fn builtin() -> Rc<RefCell<Self>> {
579 let mut register = Self::builtin_internal();
580
581 register.elements.remove("ComponentContainer").unwrap();
582 register.types.remove("component-factory").unwrap();
583
584 register.elements.remove("DragArea").unwrap();
585 register.elements.remove("DropArea").unwrap();
586 register.types.remove("DropEvent").unwrap(); register.elements.remove("MarkdownText").unwrap();
589
590 Rc::new(RefCell::new(register))
591 }
592
593 pub fn new(parent: &Rc<RefCell<TypeRegister>>) -> Self {
594 Self {
595 parent_registry: Some(parent.clone()),
596 expose_internal_types: parent.borrow().expose_internal_types,
597 ..Default::default()
598 }
599 }
600
601 pub fn lookup(&self, name: &str) -> Type {
602 self.types
603 .get(name)
604 .cloned()
605 .or_else(|| self.parent_registry.as_ref().map(|r| r.borrow().lookup(name)))
606 .unwrap_or_default()
607 }
608
609 fn lookup_element_as_result(
610 &self,
611 name: &str,
612 ) -> Result<ElementType, HashMap<SmolStr, HashSet<SmolStr>>> {
613 match self.elements.get(name).cloned() {
614 Some(ty) => Ok(ty),
615 None => match &self.parent_registry {
616 Some(r) => r.borrow().lookup_element_as_result(name),
617 None => Err(self.context_restricted_types.clone()),
618 },
619 }
620 }
621
622 pub fn lookup_element(&self, name: &str) -> Result<ElementType, String> {
623 self.lookup_element_as_result(name).map_err(|context_restricted_types| {
624 if let Some(permitted_parent_types) = context_restricted_types.get(name) {
625 if permitted_parent_types.len() == 1 {
626 format!(
627 "{} can only be within a {} element",
628 name,
629 permitted_parent_types.iter().next().unwrap()
630 )
631 } else {
632 let mut elements = permitted_parent_types.iter().cloned().collect::<Vec<_>>();
633 elements.sort();
634 format!(
635 "{} can only be within the following elements: {}",
636 name,
637 elements.join(", ")
638 )
639 }
640 } else if let Some(ty) = self.types.get(name) {
641 format!("'{ty}' cannot be used as an element")
642 } else {
643 format!("Unknown element '{name}'")
644 }
645 })
646 }
647
648 pub fn lookup_builtin_element(&self, name: &str) -> Option<ElementType> {
649 self.parent_registry.as_ref().map_or_else(
650 || self.elements.get(name).cloned(),
651 |p| p.borrow().lookup_builtin_element(name),
652 )
653 }
654
655 pub fn lookup_qualified<Member: AsRef<str>>(&self, qualified: &[Member]) -> Type {
656 if qualified.len() != 1 {
657 return Type::Invalid;
658 }
659 self.lookup(qualified[0].as_ref())
660 }
661
662 pub fn add(&mut self, comp: Rc<Component>) -> bool {
666 self.add_with_name(comp.id.clone(), comp)
667 }
668
669 pub fn add_with_name(&mut self, name: SmolStr, comp: Rc<Component>) -> bool {
673 self.elements.insert(name, ElementType::Component(comp)).is_none()
674 }
675
676 pub fn add_builtin(&mut self, builtin: Rc<BuiltinElement>) {
677 self.elements.insert(builtin.name.clone(), ElementType::Builtin(builtin));
678 }
679
680 pub fn property_animation_type_for_property(&self, property_type: Type) -> ElementType {
681 if self.supported_property_animation_types.contains(&property_type.to_string()) {
682 self.property_animation_type.clone()
683 } else {
684 self.parent_registry
685 .as_ref()
686 .map(|registry| {
687 registry.borrow().property_animation_type_for_property(property_type)
688 })
689 .unwrap_or_default()
690 }
691 }
692
693 pub fn all_types(&self) -> HashMap<SmolStr, Type> {
695 let mut all =
696 self.parent_registry.as_ref().map(|r| r.borrow().all_types()).unwrap_or_default();
697 for (k, v) in &self.types {
698 all.insert(k.clone(), v.clone());
699 }
700 all
701 }
702
703 pub fn all_elements(&self) -> HashMap<SmolStr, ElementType> {
705 let mut all =
706 self.parent_registry.as_ref().map(|r| r.borrow().all_elements()).unwrap_or_default();
707 for (k, v) in &self.elements {
708 all.insert(k.clone(), v.clone());
709 }
710 all
711 }
712
713 pub fn empty_type(&self) -> ElementType {
714 match self.parent_registry.as_ref() {
715 Some(parent) => parent.borrow().empty_type(),
716 None => self.empty_type.clone(),
717 }
718 }
719}
720
721pub fn logical_point_type() -> Rc<Struct> {
722 BUILTIN.with(|types| types.logical_point_type.clone())
723}
724
725pub fn font_metrics_type() -> Type {
726 BUILTIN.with(|types| types.font_metrics_type.clone())
727}
728
729pub fn layout_info_type() -> Rc<Struct> {
731 BUILTIN.with(|types| types.layout_info_type.clone())
732}
733
734pub fn path_element_type() -> Type {
736 BUILTIN.with(|types| types.path_element_type.clone())
737}
738
739pub fn box_layout_cell_data_type() -> Type {
741 BUILTIN.with(|types| types.box_layout_cell_data_type.clone())
742}