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: Type,
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: Type::Struct(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_ROTATION_PROPERTIES: &[(&str, Type)] = &[
179 ("rotation-angle", Type::Angle),
180 ("rotation-origin-x", Type::LogicalLength),
181 ("rotation-origin-y", Type::LogicalLength),
182];
183
184pub fn noarg_callback_type() -> Type {
185 BUILTIN.with(|types| types.noarg_callback_type.clone())
186}
187
188fn strarg_callback_type() -> Type {
189 BUILTIN.with(|types| types.strarg_callback_type.clone())
190}
191
192pub fn reserved_accessibility_properties() -> impl Iterator<Item = (&'static str, Type)> {
193 [
194 ("accessible-checkable", Type::Bool),
196 ("accessible-checked", Type::Bool),
197 ("accessible-delegate-focus", Type::Int32),
198 ("accessible-description", Type::String),
199 ("accessible-enabled", Type::Bool),
200 ("accessible-expandable", Type::Bool),
201 ("accessible-expanded", Type::Bool),
202 ("accessible-label", Type::String),
203 ("accessible-value", Type::String),
204 ("accessible-value-maximum", Type::Float32),
205 ("accessible-value-minimum", Type::Float32),
206 ("accessible-value-step", Type::Float32),
207 ("accessible-placeholder-text", Type::String),
208 ("accessible-action-default", noarg_callback_type()),
209 ("accessible-action-increment", noarg_callback_type()),
210 ("accessible-action-decrement", noarg_callback_type()),
211 ("accessible-action-set-value", strarg_callback_type()),
212 ("accessible-action-expand", noarg_callback_type()),
213 ("accessible-item-selectable", Type::Bool),
214 ("accessible-item-selected", Type::Bool),
215 ("accessible-item-index", Type::Int32),
216 ("accessible-item-count", Type::Int32),
217 ("accessible-read-only", Type::Bool),
218 ]
219 .into_iter()
220}
221
222pub fn reserved_properties() -> impl Iterator<Item = (&'static str, Type, PropertyVisibility)> {
224 RESERVED_GEOMETRY_PROPERTIES
225 .iter()
226 .chain(RESERVED_LAYOUT_PROPERTIES.iter())
227 .chain(RESERVED_OTHER_PROPERTIES.iter())
228 .chain(RESERVED_DROP_SHADOW_PROPERTIES.iter())
229 .chain(RESERVED_ROTATION_PROPERTIES.iter())
230 .map(|(k, v)| (*k, v.clone(), PropertyVisibility::Input))
231 .chain(reserved_accessibility_properties().map(|(k, v)| (k, v, PropertyVisibility::Input)))
232 .chain(
233 RESERVED_GRIDLAYOUT_PROPERTIES
234 .iter()
235 .map(|(k, v)| (*k, v.clone(), PropertyVisibility::Constexpr)),
236 )
237 .chain(IntoIterator::into_iter([
238 ("absolute-position", logical_point_type(), PropertyVisibility::Output),
239 ("forward-focus", Type::ElementReference, PropertyVisibility::Constexpr),
240 (
241 "focus",
242 Type::Function(BuiltinFunction::SetFocusItem.ty()),
243 PropertyVisibility::Public,
244 ),
245 (
246 "clear-focus",
247 Type::Function(BuiltinFunction::ClearFocusItem.ty()),
248 PropertyVisibility::Public,
249 ),
250 (
251 "dialog-button-role",
252 Type::Enumeration(BUILTIN.with(|e| e.enums.DialogButtonRole.clone())),
253 PropertyVisibility::Constexpr,
254 ),
255 (
256 "accessible-role",
257 Type::Enumeration(BUILTIN.with(|e| e.enums.AccessibleRole.clone())),
258 PropertyVisibility::Constexpr,
259 ),
260 ]))
261 .chain(std::iter::once(("init", noarg_callback_type(), PropertyVisibility::Private)))
262}
263
264pub fn reserved_property(name: &str) -> PropertyLookupResult<'_> {
266 thread_local! {
267 static RESERVED_PROPERTIES: HashMap<&'static str, (Type, PropertyVisibility, Option<BuiltinFunction>)>
268 = reserved_properties().map(|(name, ty, visibility)| (name, (ty, visibility, reserved_member_function(name)))).collect();
269 }
270 if let Some(result) = RESERVED_PROPERTIES.with(|reserved| {
271 reserved.get(name).map(|(ty, visibility, builtin_function)| PropertyLookupResult {
272 property_type: ty.clone(),
273 resolved_name: name.into(),
274 is_local_to_component: false,
275 is_in_direct_base: false,
276 property_visibility: *visibility,
277 declared_pure: None,
278 builtin_function: builtin_function.clone(),
279 })
280 }) {
281 return result;
282 }
283
284 for pre in &["min", "max"] {
286 if let Some(a) = name.strip_prefix(pre) {
287 for suf in &["width", "height"] {
288 if let Some(b) = a.strip_suffix(suf) {
289 if b == "imum-" {
290 return PropertyLookupResult {
291 property_type: Type::LogicalLength,
292 resolved_name: format!("{pre}-{suf}").into(),
293 is_local_to_component: false,
294 is_in_direct_base: false,
295 property_visibility: crate::object_tree::PropertyVisibility::InOut,
296 declared_pure: None,
297 builtin_function: None,
298 };
299 }
300 }
301 }
302 }
303 }
304 PropertyLookupResult::invalid(name.into())
305}
306
307pub fn reserved_member_function(name: &str) -> Option<BuiltinFunction> {
309 for (m, e) in [
310 ("focus", BuiltinFunction::SetFocusItem), ("clear-focus", BuiltinFunction::ClearFocusItem), ] {
313 if m == name {
314 return Some(e);
315 }
316 }
317 None
318}
319
320#[derive(Debug, Default)]
321pub struct TypeRegister {
322 types: HashMap<SmolStr, Type>,
324 elements: HashMap<SmolStr, ElementType>,
326 supported_property_animation_types: HashSet<String>,
327 pub(crate) property_animation_type: ElementType,
328 pub(crate) empty_type: ElementType,
329 context_restricted_types: HashMap<SmolStr, HashSet<SmolStr>>,
332 parent_registry: Option<Rc<RefCell<TypeRegister>>>,
333 pub(crate) expose_internal_types: bool,
335}
336
337impl TypeRegister {
338 pub(crate) fn snapshot(&self, snapshotter: &mut typeloader::Snapshotter) -> Self {
339 Self {
340 types: self.types.clone(),
341 elements: self
342 .elements
343 .iter()
344 .map(|(k, v)| (k.clone(), snapshotter.snapshot_element_type(v)))
345 .collect(),
346 supported_property_animation_types: self.supported_property_animation_types.clone(),
347 property_animation_type: snapshotter
348 .snapshot_element_type(&self.property_animation_type),
349 empty_type: snapshotter.snapshot_element_type(&self.empty_type),
350 context_restricted_types: self.context_restricted_types.clone(),
351 parent_registry: self
352 .parent_registry
353 .as_ref()
354 .map(|tr| snapshotter.snapshot_type_register(tr)),
355 expose_internal_types: self.expose_internal_types,
356 }
357 }
358
359 pub fn insert_type(&mut self, t: Type) -> bool {
363 self.types.insert(t.to_smolstr(), t).is_none()
364 }
365 pub fn insert_type_with_name(&mut self, t: Type, name: SmolStr) -> bool {
369 self.types.insert(name, t).is_none()
370 }
371
372 fn builtin_internal() -> Self {
373 let mut register = TypeRegister::default();
374
375 register.insert_type(Type::Float32);
376 register.insert_type(Type::Int32);
377 register.insert_type(Type::String);
378 register.insert_type(Type::PhysicalLength);
379 register.insert_type(Type::LogicalLength);
380 register.insert_type(Type::Color);
381 register.insert_type(Type::ComponentFactory);
382 register.insert_type(Type::Duration);
383 register.insert_type(Type::Image);
384 register.insert_type(Type::Bool);
385 register.insert_type(Type::Model);
386 register.insert_type(Type::Percent);
387 register.insert_type(Type::Easing);
388 register.insert_type(Type::Angle);
389 register.insert_type(Type::Brush);
390 register.insert_type(Type::Rem);
391 register.types.insert("Point".into(), logical_point_type());
392
393 BUILTIN.with(|e| e.enums.fill_register(&mut register));
394
395 register.supported_property_animation_types.insert(Type::Float32.to_string());
396 register.supported_property_animation_types.insert(Type::Int32.to_string());
397 register.supported_property_animation_types.insert(Type::Color.to_string());
398 register.supported_property_animation_types.insert(Type::PhysicalLength.to_string());
399 register.supported_property_animation_types.insert(Type::LogicalLength.to_string());
400 register.supported_property_animation_types.insert(Type::Brush.to_string());
401 register.supported_property_animation_types.insert(Type::Angle.to_string());
402
403 #[rustfmt::skip]
404 macro_rules! map_type {
405 ($pub_type:ident, bool) => { Type::Bool };
406 ($pub_type:ident, i32) => { Type::Int32 };
407 ($pub_type:ident, f32) => { Type::Float32 };
408 ($pub_type:ident, SharedString) => { Type::String };
409 ($pub_type:ident, Image) => { Type::Image };
410 ($pub_type:ident, Coord) => { Type::LogicalLength };
411 ($pub_type:ident, LogicalPosition) => { logical_point_type() };
412 ($pub_type:ident, KeyboardModifiers) => { $pub_type.clone() };
413 ($pub_type:ident, $_:ident) => {
414 BUILTIN.with(|e| Type::Enumeration(e.enums.$pub_type.clone()))
415 };
416 }
417 #[rustfmt::skip]
418 macro_rules! maybe_clone {
419 ($pub_type:ident, KeyboardModifiers) => { $pub_type.clone() };
420 ($pub_type:ident, $_:ident) => { $pub_type };
421 }
422 macro_rules! register_builtin_structs {
423 ($(
424 $(#[$attr:meta])*
425 struct $Name:ident {
426 @name = $inner_name:literal
427 export {
428 $( $(#[$pub_attr:meta])* $pub_field:ident : $pub_type:ident, )*
429 }
430 private {
431 $( $(#[$pri_attr:meta])* $pri_field:ident : $pri_type:ty, )*
432 }
433 }
434 )*) => { $(
435 #[allow(non_snake_case)]
436 let $Name = Type::Struct(Rc::new(Struct{
437 fields: BTreeMap::from([
438 $((stringify!($pub_field).replace_smolstr("_", "-"), map_type!($pub_type, $pub_type))),*
439 ]),
440 name: Some(format_smolstr!("{}", $inner_name)),
441 node: None,
442 rust_attributes: None,
443 }));
444 register.insert_type_with_name(maybe_clone!($Name, $Name), SmolStr::new(stringify!($Name)));
445 )* };
446 }
447 i_slint_common::for_each_builtin_structs!(register_builtin_structs);
448
449 crate::load_builtins::load_builtins(&mut register);
450
451 for e in register.elements.values() {
452 if let ElementType::Builtin(b) = e {
453 for accepted_child_type_name in b.additional_accepted_child_types.keys() {
454 register
455 .context_restricted_types
456 .entry(accepted_child_type_name.clone())
457 .or_default()
458 .insert(b.native_class.class_name.clone());
459 }
460 if b.additional_accept_self {
461 register
462 .context_restricted_types
463 .entry(b.native_class.class_name.clone())
464 .or_default()
465 .insert(b.native_class.class_name.clone());
466 }
467 }
468 }
469
470 match &mut register.elements.get_mut("PopupWindow").unwrap() {
471 ElementType::Builtin(ref mut b) => {
472 let popup = Rc::get_mut(b).unwrap();
473 popup.properties.insert(
474 "show".into(),
475 BuiltinPropertyInfo::from(BuiltinFunction::ShowPopupWindow),
476 );
477
478 popup.properties.insert(
479 "close".into(),
480 BuiltinPropertyInfo::from(BuiltinFunction::ClosePopupWindow),
481 );
482
483 popup.properties.get_mut("close-on-click").unwrap().property_visibility =
484 PropertyVisibility::Constexpr;
485
486 popup.properties.get_mut("close-policy").unwrap().property_visibility =
487 PropertyVisibility::Constexpr;
488 }
489 _ => unreachable!(),
490 };
491
492 match &mut register.elements.get_mut("Timer").unwrap() {
493 ElementType::Builtin(ref mut b) => {
494 let timer = Rc::get_mut(b).unwrap();
495 timer
496 .properties
497 .insert("start".into(), BuiltinPropertyInfo::from(BuiltinFunction::StartTimer));
498 timer
499 .properties
500 .insert("stop".into(), BuiltinPropertyInfo::from(BuiltinFunction::StopTimer));
501 timer.properties.insert(
502 "restart".into(),
503 BuiltinPropertyInfo::from(BuiltinFunction::RestartTimer),
504 );
505 }
506 _ => unreachable!(),
507 }
508
509 let font_metrics_prop = crate::langtype::BuiltinPropertyInfo {
510 ty: font_metrics_type(),
511 property_visibility: PropertyVisibility::Output,
512 default_value: BuiltinPropertyDefault::WithElement(|elem| {
513 crate::expression_tree::Expression::FunctionCall {
514 function: BuiltinFunction::ItemFontMetrics.into(),
515 arguments: vec![crate::expression_tree::Expression::ElementReference(
516 Rc::downgrade(elem),
517 )],
518 source_location: None,
519 }
520 }),
521 };
522
523 match &mut register.elements.get_mut("TextInput").unwrap() {
524 ElementType::Builtin(ref mut b) => {
525 let text_input = Rc::get_mut(b).unwrap();
526 text_input.properties.insert(
527 "set-selection-offsets".into(),
528 BuiltinPropertyInfo::from(BuiltinFunction::SetSelectionOffsets),
529 );
530 text_input.properties.insert("font-metrics".into(), font_metrics_prop.clone());
531 }
532
533 _ => unreachable!(),
534 };
535
536 match &mut register.elements.get_mut("Text").unwrap() {
537 ElementType::Builtin(ref mut b) => {
538 let text = Rc::get_mut(b).unwrap();
539 text.properties.insert("font-metrics".into(), font_metrics_prop);
540 }
541
542 _ => unreachable!(),
543 };
544
545 match &mut register.elements.get_mut("Path").unwrap() {
546 ElementType::Builtin(ref mut b) => {
547 let path = Rc::get_mut(b).unwrap();
548 path.properties.get_mut("commands").unwrap().property_visibility =
549 PropertyVisibility::Fake;
550 }
551
552 _ => unreachable!(),
553 };
554
555 register
556 }
557
558 #[doc(hidden)]
559 pub fn builtin_experimental() -> Rc<RefCell<Self>> {
561 let register = Self::builtin_internal();
562 Rc::new(RefCell::new(register))
563 }
564
565 pub fn builtin() -> Rc<RefCell<Self>> {
566 let mut register = Self::builtin_internal();
567
568 register.elements.remove("ComponentContainer").unwrap();
569 register.types.remove("component-factory").unwrap();
570
571 register.elements.remove("DragArea").unwrap();
572 register.elements.remove("DropArea").unwrap();
573 register.types.remove("DropEvent").unwrap(); Rc::new(RefCell::new(register))
576 }
577
578 pub fn new(parent: &Rc<RefCell<TypeRegister>>) -> Self {
579 Self {
580 parent_registry: Some(parent.clone()),
581 expose_internal_types: parent.borrow().expose_internal_types,
582 ..Default::default()
583 }
584 }
585
586 pub fn lookup(&self, name: &str) -> Type {
587 self.types
588 .get(name)
589 .cloned()
590 .or_else(|| self.parent_registry.as_ref().map(|r| r.borrow().lookup(name)))
591 .unwrap_or_default()
592 }
593
594 fn lookup_element_as_result(
595 &self,
596 name: &str,
597 ) -> Result<ElementType, HashMap<SmolStr, HashSet<SmolStr>>> {
598 match self.elements.get(name).cloned() {
599 Some(ty) => Ok(ty),
600 None => match &self.parent_registry {
601 Some(r) => r.borrow().lookup_element_as_result(name),
602 None => Err(self.context_restricted_types.clone()),
603 },
604 }
605 }
606
607 pub fn lookup_element(&self, name: &str) -> Result<ElementType, String> {
608 self.lookup_element_as_result(name).map_err(|context_restricted_types| {
609 if let Some(permitted_parent_types) = context_restricted_types.get(name) {
610 if permitted_parent_types.len() == 1 {
611 format!(
612 "{} can only be within a {} element",
613 name,
614 permitted_parent_types.iter().next().unwrap()
615 )
616 } else {
617 let mut elements = permitted_parent_types.iter().cloned().collect::<Vec<_>>();
618 elements.sort();
619 format!(
620 "{} can only be within the following elements: {}",
621 name,
622 elements.join(", ")
623 )
624 }
625 } else if let Some(ty) = self.types.get(name) {
626 format!("'{ty}' cannot be used as an element")
627 } else {
628 format!("Unknown element '{name}'")
629 }
630 })
631 }
632
633 pub fn lookup_builtin_element(&self, name: &str) -> Option<ElementType> {
634 self.parent_registry.as_ref().map_or_else(
635 || self.elements.get(name).cloned(),
636 |p| p.borrow().lookup_builtin_element(name),
637 )
638 }
639
640 pub fn lookup_qualified<Member: AsRef<str>>(&self, qualified: &[Member]) -> Type {
641 if qualified.len() != 1 {
642 return Type::Invalid;
643 }
644 self.lookup(qualified[0].as_ref())
645 }
646
647 pub fn add(&mut self, comp: Rc<Component>) -> bool {
651 self.add_with_name(comp.id.clone(), comp)
652 }
653
654 pub fn add_with_name(&mut self, name: SmolStr, comp: Rc<Component>) -> bool {
658 self.elements.insert(name, ElementType::Component(comp)).is_none()
659 }
660
661 pub fn add_builtin(&mut self, builtin: Rc<BuiltinElement>) {
662 self.elements.insert(builtin.name.clone(), ElementType::Builtin(builtin));
663 }
664
665 pub fn property_animation_type_for_property(&self, property_type: Type) -> ElementType {
666 if self.supported_property_animation_types.contains(&property_type.to_string()) {
667 self.property_animation_type.clone()
668 } else {
669 self.parent_registry
670 .as_ref()
671 .map(|registry| {
672 registry.borrow().property_animation_type_for_property(property_type)
673 })
674 .unwrap_or_default()
675 }
676 }
677
678 pub fn all_types(&self) -> HashMap<SmolStr, Type> {
680 let mut all =
681 self.parent_registry.as_ref().map(|r| r.borrow().all_types()).unwrap_or_default();
682 for (k, v) in &self.types {
683 all.insert(k.clone(), v.clone());
684 }
685 all
686 }
687
688 pub fn all_elements(&self) -> HashMap<SmolStr, ElementType> {
690 let mut all =
691 self.parent_registry.as_ref().map(|r| r.borrow().all_elements()).unwrap_or_default();
692 for (k, v) in &self.elements {
693 all.insert(k.clone(), v.clone());
694 }
695 all
696 }
697
698 pub fn empty_type(&self) -> ElementType {
699 match self.parent_registry.as_ref() {
700 Some(parent) => parent.borrow().empty_type(),
701 None => self.empty_type.clone(),
702 }
703 }
704}
705
706pub fn logical_point_type() -> Type {
707 BUILTIN.with(|types| types.logical_point_type.clone())
708}
709
710pub fn font_metrics_type() -> Type {
711 BUILTIN.with(|types| types.font_metrics_type.clone())
712}
713
714pub fn layout_info_type() -> Rc<Struct> {
716 BUILTIN.with(|types| types.layout_info_type.clone())
717}
718
719pub fn path_element_type() -> Type {
721 BUILTIN.with(|types| types.path_element_type.clone())
722}
723
724pub fn box_layout_cell_data_type() -> Type {
726 BUILTIN.with(|types| types.box_layout_cell_data_type.clone())
727}