Skip to main content

i_slint_compiler/
builtin_elements.rs

1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
3
4// cSpell: ignore langtype typeregister borderless commonmark Strikethroughs
5
6//! The builtin elements of the language and the runtime items they lower to.
7//!
8//! `item!` declares a runtime item, one per item struct, with the properties, callbacks and
9//! functions the item implements. An item that has every property of another one names it
10//! after a colon, so the compiler can lower to the smaller item when the larger one isn't needed:
11//!
12//! ```text
13//! item! { SimpleText: Empty {
14//!     /// Documentation of the member.
15//!     in property <string> text;
16//!     in property <length> font-size: 12px;
17//!     @deprecated in property <angle> rotation-angle <=> transform-rotation;   // deprecated alias
18//!     //! ### Section heading           // free-form documentation kept in source order
19//!     callback edited(text: string) -> bool;
20//!     function close() { }                                  // implemented by a compiler pass
21//!     function start() { BuiltinFunction.StartTimer }       // implemented by a BuiltinFunction
22//!     out property <FontMetrics> font-metrics { BuiltinFunction.ItemFontMetrics } // computed per element
23//! } }
24//! ```
25//!
26//! `element!` declares an element `.slint` code can use. An element names the native item it
27//! lowers to; the compiler picks the smallest item in that item's parent chain that has every
28//! property the element uses, so a `Rectangle { }` becomes an `Empty`. Members declared on the
29//! element itself only exist in the compiler. Accepted child elements are listed with
30//! `children:`.
31//!
32//! ```text
33//! element! {
34//!     /// Documentation of the element.
35//!     @implicit_size
36//!     Text: ComplexText
37//! }
38//!
39//! element! { Window: WindowItem { children: MenuBar; } }
40//!
41//! element! {
42//!     @is_non_item_type
43//!     Timer {
44//!         in property <duration> interval;
45//!         function start() { BuiltinFunction.StartTimer }
46//!     }
47//! }
48//! ```
49//!
50//! The `@flags` of an element are the boolean fields of `BuiltinElement` (`is_internal`,
51//! `is_global`, ...) plus `expands_to_parent_geometry` or `implicit_size` for the default size,
52//! `builtin_struct(Name)`, `sc` for an element of the Slint SC subset and `skip_inherited` to
53//! leave the docs of the native items out of the element's.
54//! Member modifiers `@shadowable`, `@deprecated` (aliases only) and `@pure` keep their Slint
55//! meaning; `@constexpr` marks a property whose value is known at compile time, `@fake` one
56//! that exists only at compile time and `@sc` one of the Slint SC subset. A default value is a
57//! literal (`true`, `4`, `8px`, `500ms`, `"text"`, `#00f`) or an enum value
58//! (`ImageFit.contain`); the compiler sets it as the property's binding.
59//!
60//! Elements that are accepted children of another element are only reachable through it.
61//! A native item or an element must be declared before the items and elements using it, so each
62//! item sits right before the element that lowers to it. The macros expand to calls on a
63//! [`Builder`] that fill a [`NativeClass`] and a [`BuiltinElement`]; [`load`] runs them.
64
65use crate::expression_tree::{BuiltinFunction, Unit};
66use crate::langtype::{
67    BuiltinElement, BuiltinPropertyDefault, BuiltinPropertyInfo, BuiltinStruct, ConstantExpression,
68    DefaultSizeBinding, ElementDocEntry, ElementType, Function, NativeClass, Type,
69};
70use crate::object_tree::{Component, Element, PropertyVisibility};
71use crate::typeregister::TypeRegister;
72use smol_str::SmolStr;
73use std::cell::RefCell;
74use std::collections::HashMap;
75use std::rc::Rc;
76use std::sync::Arc;
77
78/// `stringify!` output of a hyphenated name, without the spaces it puts around `-`.
79fn kebab(spelled: &str) -> SmolStr {
80    debug_assert!(!spelled.contains('_'), "`{spelled}` must be spelled with dashes");
81    spelled.split(' ').collect()
82}
83
84/// Joins doc lines like the parser did for `///` comments: one space after the marker is
85/// dropped, lines are separated by `\n`.
86fn join_docs(lines: &[&str]) -> Option<String> {
87    (!lines.is_empty()).then(|| {
88        lines.iter().map(|l| l.strip_prefix(' ').unwrap_or(l)).collect::<Vec<_>>().join("\n")
89    })
90}
91
92/// The default value as written after the property: a literal (`true`, `4`, `8px`, `"text"`,
93/// `#00f`) or an enum value (`ImageFit.contain`). A number on an `int` property is cast, as the
94/// compiler does for a binding.
95fn default(ty: &Type, text: &str) -> Option<ConstantExpression> {
96    if text.is_empty() {
97        return None;
98    }
99    if text.starts_with('"') {
100        return Some(ConstantExpression::StringLiteral(
101            crate::literals::unescape_string(text).unwrap(),
102        ));
103    }
104    let text = text.replace(' ', "");
105    Some(match text.as_str() {
106        "true" => ConstantExpression::BoolLiteral(true),
107        "false" => ConstantExpression::BoolLiteral(false),
108        color if color.starts_with('#') => {
109            let argb = i_slint_common::color_parsing::parse_color_literal(color).unwrap();
110            ConstantExpression::Cast {
111                from: Box::new(ConstantExpression::NumberLiteral(argb as f64, Unit::None)),
112                to: Type::Color,
113            }
114        }
115        value if value.starts_with(|c: char| c.is_ascii_alphabetic()) => {
116            let (qualifier, value) = value.split_once('.').unwrap();
117            let Type::Enumeration(enumeration) = ty else {
118                panic!("enum default `{qualifier}.{value}` on a property of type {ty}")
119            };
120            assert_eq!(qualifier, enumeration.name, "wrong enum in `{qualifier}.{value}`");
121            let value = enumeration.clone().try_value_from_string(&kebab(value)).unwrap();
122            ConstantExpression::EnumerationValue(value)
123        }
124        number => {
125            let (value, unit) =
126                crate::literals::parse_number_literal(SmolStr::new(number)).unwrap();
127            let (value, unit) = unit.normalize(value);
128            let number = ConstantExpression::NumberLiteral(value, unit);
129            match ty {
130                Type::Int32 => ConstantExpression::Cast { from: Box::new(number), to: Type::Int32 },
131                _ => number,
132            }
133        }
134    })
135}
136
137#[cfg(feature = "builtin-docs")]
138macro_rules! docs {
139    ($($l:literal)*) => { &[$($l),*] };
140}
141/// Without the feature the doc strings stay out of the binary.
142#[cfg(not(feature = "builtin-docs"))]
143macro_rules! docs {
144    ($($l:literal)*) => {
145        &[]
146    };
147}
148
149#[rustfmt::skip]
150macro_rules! visibility {
151    (in) => { PropertyVisibility::Input };
152    (out) => { PropertyVisibility::Output };
153    (in - out) => { PropertyVisibility::InOut };
154    (private) => { PropertyVisibility::Private };
155}
156
157/// An `@flag` of an element; a bare flag names a `BuiltinElement` field.
158macro_rules! flag {
159    ($e:ident sc) => { $e.element.slint_sc = true };
160    ($e:ident skip_inherited) => { $e.element.docs.truncate(1) };
161    ($e:ident expands_to_parent_geometry) => { $e.element.default_size_binding = DefaultSizeBinding::ExpandsToParentGeometry };
162    ($e:ident implicit_size) => { $e.element.default_size_binding = DefaultSizeBinding::ImplicitSize };
163    ($e:ident builtin_struct($s:ident)) => { $e.class.builtin_struct = Some(BuiltinStruct::$s) };
164    ($e:ident $flag:ident) => { $e.element.$flag = true };
165}
166
167/// The members of a native item or builtin element, as calls on the builder `$e`.
168macro_rules! members {
169    ($l:ident $e:ident $(#![doc = $s:literal])*) => { $e.section(docs!($($s)*)); };
170    // property
171    ($l:ident $e:ident $(#![doc = $s:literal])* $(#[doc = $d:literal])* $(@$mod:ident)*
172        $vis:ident $(- $vis2:ident)? property < $($ty:tt)-+ > $($name:tt)-+ $(: $default:tt $(. $($dv:tt)-+)? $($hex:literal)?)? $(<=> $($alias:tt)-+)? ;
173        $($rest:tt)*) => {
174        $e.section(docs!($($s)*));
175        {
176            let ty = $l.ty(stringify!($($ty)-+));
177            let default = default(&ty, stringify!($($default $(. $($dv)-+)? $($hex)?)?));
178            $e.property(stringify!($($name)-+), ty, visibility!($vis $(- $vis2)?), default,
179                None $(.or(Some(stringify!($($alias)-+))))?, &[$(stringify!($mod)),*], docs!($($d)*));
180        }
181        members!($l $e $($rest)*);
182    };
183    // property computed by a BuiltinFunction, per element or per process
184    ($l:ident $e:ident $(#![doc = $s:literal])* $(#[doc = $d:literal])* $(@$mod:ident)*
185        $vis:ident property < $($ty:tt)-+ > $($name:tt)-+ { BuiltinFunction . $bf:ident } $($rest:tt)*) => {
186        $e.section(docs!($($s)*));
187        {
188            let mut info = BuiltinPropertyInfo::new($l.ty(stringify!($($ty)-+)));
189            info.property_visibility = visibility!($vis);
190            info.default_value = computed_default(BuiltinFunction::$bf);
191            $e.add(stringify!($($name)-+), info, &[$(stringify!($mod)),*], docs!($($d)*));
192        }
193        members!($l $e $($rest)*);
194    };
195    // callback
196    ($l:ident $e:ident $(#![doc = $s:literal])* $(#[doc = $d:literal])* $(@$mod:ident)*
197        callback $($name:tt)-+ $(( $($n:tt : $($t:tt)-+),* ))? $(-> $($ret:tt)-+)? ; $($rest:tt)*) => {
198        $e.section(docs!($($s)*));
199        $e.function(stringify!($($name)-+), Type::Callback,
200            $l.function(&[$($((stringify!($n), stringify!($($t)-+))),*)?], stringify!($($($ret)-+)?)),
201            None, &[$(stringify!($mod)),*], docs!($($d)*));
202        members!($l $e $($rest)*);
203    };
204    // function, implemented by a compiler pass or by the BuiltinFunction named in its body
205    ($l:ident $e:ident $(#![doc = $s:literal])* $(#[doc = $d:literal])* $(@$mod:ident)*
206        function $($name:tt)-+ ( $($n:tt : $($t:tt)-+),* ) $(-> $($ret:tt)-+)? { $(BuiltinFunction . $bf:ident)? } $($rest:tt)*) => {
207        $e.section(docs!($($s)*));
208        $e.function(stringify!($($name)-+), Type::Function,
209            $l.function(&[$((stringify!($n), stringify!($($t)-+))),*], stringify!($($($ret)-+)?)),
210            None $(.or(Some(BuiltinFunction::$bf)))?, &[$(stringify!($mod)),*], docs!($($d)*));
211        members!($l $e $($rest)*);
212    };
213    // accepted child elements
214    ($l:ident $e:ident $(#![doc = $s:literal])* children : $($child:ident),+ ; $($rest:tt)*) => {
215        $e.section(docs!($($s)*));
216        $l.children(&mut $e, &[$(stringify!($child)),+]);
217        members!($l $e $($rest)*);
218    };
219}
220
221/// The default of a property a `BuiltinFunction` computes.
222/// A function that takes the element computes a value per element, one that takes nothing
223/// answers for the whole process.
224fn computed_default(function: BuiltinFunction) -> BuiltinPropertyDefault {
225    if function.ty().args.is_empty() {
226        BuiltinPropertyDefault::RuntimeValue(function)
227    } else {
228        BuiltinPropertyDefault::ElementFunction(function)
229    }
230}
231
232/// A native item or builtin element being built.
233struct Builder {
234    class: NativeClass,
235    element: BuiltinElement,
236}
237
238impl Builder {
239    /// `//!` lines, kept in the docs in source order.
240    fn section(&mut self, lines: &[&str]) {
241        if let Some(text) = join_docs(lines) {
242            self.element.docs.push(ElementDocEntry::Text(text));
243        }
244    }
245
246    fn add(&mut self, name: &str, mut info: BuiltinPropertyInfo, mods: &[&str], docs: &[&str]) {
247        info.shadowable = mods.contains(&"shadowable");
248        info.slint_sc = mods.contains(&"sc");
249        info.docs = join_docs(docs);
250        let name = kebab(name);
251        self.member_doc(name.clone());
252        // A property computed per element isn't a property of the native item.
253        match info.default_value {
254            BuiltinPropertyDefault::ElementFunction(_) => {
255                self.element.properties.insert(name, info)
256            }
257            _ => self.class.properties.insert(name, info),
258        };
259    }
260
261    /// The docs are only assembled when they reach the binary.
262    fn member_doc(&mut self, name: SmolStr) {
263        if cfg!(feature = "builtin-docs") {
264            self.element.docs.push(ElementDocEntry::Member(name));
265        }
266    }
267
268    #[inline(never)]
269    fn property(
270        &mut self,
271        name: &str,
272        ty: Type,
273        vis: PropertyVisibility,
274        default: Option<ConstantExpression>,
275        alias: Option<&str>,
276        mods: &[&str],
277        docs: &[&str],
278    ) {
279        debug_assert_eq!(
280            mods.contains(&"deprecated"),
281            alias.is_some(),
282            "`@deprecated` on {}::{name} is only for two-way-binding aliases, and every alias must have it",
283            self.class.class_name
284        );
285        if let Some(target) = alias {
286            let name = kebab(name);
287            self.class.deprecated_aliases.insert(name.clone(), kebab(target));
288            self.member_doc(name);
289            return;
290        }
291        let mut info = BuiltinPropertyInfo::new(ty);
292        info.property_visibility = if mods.contains(&"constexpr") {
293            PropertyVisibility::Constexpr
294        } else if mods.contains(&"fake") {
295            PropertyVisibility::Fake
296        } else {
297            vis
298        };
299        if let Some(default) = default {
300            assert!(
301                !mods.contains(&"shadowable"),
302                "shadowable property {}::{name} can't have a default value as it would end up on the shadowing declaration",
303                self.class.class_name
304            );
305            debug_assert_eq!(
306                default.to_expression().ty(),
307                info.ty,
308                "the default value of {}::{name} has the wrong type",
309                self.class.class_name
310            );
311            info.default_value = BuiltinPropertyDefault::Expr(default);
312        }
313        self.add(name, info, mods, docs);
314    }
315
316    /// A callback or a function; `ty` is the `Type` constructor. A function is implemented by
317    /// a compiler pass, or by `builtin`.
318    #[inline(never)]
319    fn function(
320        &mut self,
321        name: &str,
322        ty: fn(Arc<Function>) -> Type,
323        function: Function,
324        builtin: Option<BuiltinFunction>,
325        mods: &[&str],
326        docs: &[&str],
327    ) {
328        let declared_pure = mods.contains(&"pure");
329        let info = match builtin {
330            Some(builtin) => {
331                // The BuiltinFunction type prepends implicit ElementReference arguments.
332                let builtin_ty = builtin.ty();
333                let implicit = builtin_ty.args.len().saturating_sub(function.args.len());
334                debug_assert!(
335                    builtin_ty.args.ends_with(&function.args)
336                        && builtin_ty.args[..implicit]
337                            .iter()
338                            .all(|t| matches!(t, Type::ElementReference))
339                        && builtin_ty.return_type == function.return_type,
340                    "the declared signature of {}::{name} doesn't match {builtin:?}: {builtin_ty:?}",
341                    self.class.class_name
342                );
343                let mut merged = (*builtin_ty).clone();
344                merged.arg_names = std::iter::repeat_n(SmolStr::default(), implicit)
345                    .chain(function.arg_names)
346                    .collect();
347                debug_assert_eq!(
348                    declared_pure,
349                    builtin.is_pure(),
350                    "the 'pure' qualifier of {}::{name} doesn't match {builtin:?}",
351                    self.class.class_name
352                );
353                // `pure` comes from the BuiltinFunction, see BuiltinPropertyInfo::pure.
354                let mut info = BuiltinPropertyInfo::from(builtin);
355                info.ty = ty(Arc::new(merged));
356                info
357            }
358            None => {
359                let mut info = BuiltinPropertyInfo::new(ty(Arc::new(function)));
360                info.pure = declared_pure;
361                info
362            }
363        };
364        self.add(name, info, mods, docs);
365    }
366}
367
368struct Loader<'a> {
369    register: &'a mut TypeRegister,
370    /// The native items by name, each with the properties and docs of its whole parent chain.
371    items: HashMap<SmolStr, (Arc<NativeClass>, BuiltinElement)>,
372    /// The builtin elements by name.
373    elements: HashMap<SmolStr, Rc<BuiltinElement>>,
374}
375
376impl Loader<'_> {
377    /// A type as written: `length`, `[MenuEntry]`, or nothing for `void`.
378    fn ty(&self, text: &str) -> Type {
379        if text.is_empty() {
380            return Type::Void;
381        }
382        if let Some(inner) = text.strip_prefix('[').and_then(|t| t.strip_suffix(']')) {
383            return Type::Array(Arc::new(self.ty(inner)));
384        }
385        let ty = self.register.lookup(&kebab(text));
386        assert!(ty != Type::Invalid, "unknown type `{text}` in a builtin element");
387        ty
388    }
389
390    /// The signature of a callback or function from its `(name: type, ..)` and return type.
391    fn function(&self, args: &[(&str, &str)], ret: &str) -> Function {
392        Function {
393            return_type: self.ty(ret),
394            args: args.iter().map(|(_, t)| self.ty(t)).collect(),
395            arg_names: args.iter().map(|(n, _)| kebab(n)).collect(),
396        }
397    }
398
399    fn item_chain(&self, name: &str) -> &(Arc<NativeClass>, BuiltinElement) {
400        self.items
401            .get(name)
402            .unwrap_or_else(|| panic!("native item `{name}` must be declared before its use"))
403    }
404
405    #[inline(never)]
406    fn item(&self, name: &str, parent: Option<&str>) -> Builder {
407        let mut class = NativeClass::new(name);
408        let mut element = BuiltinElement::default();
409        if let Some(parent) = parent {
410            let (parent_class, chain) = self.item_chain(parent);
411            class.parent = Some(parent_class.clone());
412            element.properties = chain.properties.clone();
413            element.docs = chain.docs.clone();
414        }
415        Builder { class, element }
416    }
417
418    fn finish_item(&mut self, mut e: Builder) {
419        e.element.properties.extend(e.class.properties.clone());
420        self.items.insert(e.class.class_name.clone(), (Arc::new(e.class), e.element));
421    }
422
423    #[inline(never)]
424    fn element(&self, name: &str, docs: &[&str]) -> Builder {
425        let mut e = self.item(name, None);
426        if cfg!(feature = "builtin-docs") {
427            e.element.docs.push(ElementDocEntry::Text(join_docs(docs).unwrap_or_default()));
428        }
429        e
430    }
431
432    /// The native item the element lowers to. The element gets the properties and docs of the
433    /// item and of its parents.
434    fn base(&self, e: &mut Builder, item: &str) {
435        let (class, chain) = self.item_chain(item);
436        e.element.properties.extend(chain.properties.clone());
437        e.element.docs.extend(chain.docs.iter().cloned());
438        e.class.parent = Some(class.clone());
439    }
440
441    /// The accepted child elements, which can only be used within this one.
442    fn children(&mut self, e: &mut Builder, names: &[&str]) {
443        let parent = e.class.class_name.clone();
444        for name in names {
445            let name = SmolStr::new(name);
446            if name == parent {
447                e.element.additional_accept_self = true;
448            } else {
449                let child = self.elements.get(&name).unwrap_or_else(|| {
450                    panic!(
451                        "`{name}` must be declared before the builtin elements using it as a child"
452                    )
453                });
454                e.element.additional_accepted_child_types.insert(name.clone(), child.clone());
455            }
456            self.register.context_restricted_types.entry(name).or_default().insert(parent.clone());
457        }
458    }
459
460    fn finish_element(&mut self, e: Builder) {
461        let mut builtin = e.element;
462        builtin.name = e.class.class_name.clone();
463        builtin.properties.extend(e.class.properties.clone());
464        // An element without members of its own is the native item it lowers to.
465        let own_members = !e.class.properties.is_empty()
466            || !e.class.deprecated_aliases.is_empty()
467            || e.class.builtin_struct.is_some();
468        builtin.native_class = match e.class.parent.clone() {
469            Some(item) if !own_members => item,
470            _ => Arc::new(e.class),
471        };
472        let builtin = Rc::new(builtin);
473        if builtin.is_global {
474            let global = Rc::new(Component {
475                id: builtin.name.clone(),
476                root_element: Rc::new(RefCell::new(Element {
477                    base_type: ElementType::Builtin(builtin.clone()),
478                    ..Default::default()
479                })),
480                ..Default::default()
481            });
482            global.root_element.borrow_mut().enclosing_component = Rc::downgrade(&global);
483            self.register.add(global);
484        }
485        self.elements.insert(builtin.name.clone(), builtin);
486    }
487}
488
489/// The declarations. `item!` declares a runtime item, `element!` an element of the language.
490fn build(l: &mut Loader) {
491    macro_rules! item {
492        ($Name:ident $(: $Parent:ident)? { $($body:tt)* }) => {{
493            let mut e = l.item(stringify!($Name), None $(.or(Some(stringify!($Parent))))?);
494            members!(l e $($body)*);
495            l.finish_item(e);
496        }};
497    }
498    macro_rules! element {
499        ($(#[doc = $d:literal])* $(@$flag:ident $(($arg:ident))?)* $Name:ident $(: $Item:ident)? $({ $($body:tt)* })?) => {{
500            let mut e = l.element(stringify!($Name), docs!($($d)*));
501            $( l.base(&mut e, stringify!($Item)); )?
502            $( flag!(e $flag $(($arg))?); )*
503            members!(l e $($($body)*)?);
504            l.finish_element(e);
505        }};
506    }
507
508    item! { Empty { } }
509
510    element! {
511        @is_internal
512        Empty: Empty
513    }
514
515    item! { Rectangle: Empty {
516        /// The background brush of this `Rectangle`, filling its geometry. \{#sls.ref.rectangle.background}
517        ///
518        /// Without a `background` and without a border, the `Rectangle` paints nothing. \{#sls.ref.rectangle.empty}
519        ///
520        /// A translucent background lets the content underneath show through. \{#sls.ref.rectangle.translucent}
521        ///
522        /// ```slint imageAlt="rectangle background" width="200" height="400"
523        /// property <brush> rainbow-gradient: @linear-gradient(40deg, rgba(255, 0, 0, 1) 0%, rgba(255, 154, 0, 1) 10%, rgba(208, 222, 33, 1) 20%,rgba(79, 220, 74, 1) 30%, rgba(63, 218, 216, 1) 40%, rgba(47, 201, 226, 1) 50%, rgba(28, 127, 238, 1) 60%, rgba(95, 21, 242, 1) 70%, rgba(186, 12, 248, 1) 80%, rgba(251, 7, 217, 1) 90%, rgba(255, 0, 0, 1) 100%);
524        ///
525        /// Rectangle {
526        ///     x: 10px;
527        ///     y: 10px;
528        ///     width: 180px;
529        ///     height: 180px;
530        ///     background: #315afd;
531        /// }
532        ///
533        ///
534        /// Rectangle {
535        ///     x: 10px;
536        ///     y: 210px;
537        ///     width: 180px;
538        ///     height: 180px;
539        ///     background: rainbow-gradient;
540        /// }
541        /// ```
542        /// \default transparent
543        @sc in property <brush> background;
544        @deprecated in property <brush> color <=> background;
545    } }
546
547    item! { BasicBorderRectangle: Rectangle {
548        /// ```slint imageAlt="rectangle border-color" width="200" height="200"
549        /// Rectangle {
550        ///     width: 200px;
551        ///     height: 200px;
552        ///     border-width: 10px;
553        ///     border-color: lightslategray;
554        /// }
555        /// ```
556        /// The color of the border.
557        /// :::caution[Caution]
558        /// The default `border-width` is `0px`, so the border is invisible. After setting a color also ensure that the `border-width` is set to a non-zero value.
559        /// :::
560        /// \default transparent
561        in property <brush> border-color;
562        /// ```slint imageAlt="rectangle border-width" width="200" height="200"
563        /// Rectangle {
564        ///     width: 200px;
565        ///     height: 200px;
566        ///     border-width: 30px;
567        ///     border-color: lightslategray;
568        /// }
569        /// ```
570        /// The width of the border.
571        /// \default 0
572        in property <length> border-width;
573        //! ### clip
574        //! <SlintProperty propName="clip" typeName="bool" defaultValue="false">
575        //! ```slint imageAlt="rectangle clip" width="200" height="400"
576        //! // clip: false; the default
577        //! Rectangle {
578        //!     x: 50px; y: 50px;
579        //!     width: 150px;
580        //!     height: 150px;
581        //!     background: darkslategray;
582        //! # Text {
583        //! #     text: "clip: false";
584        //! #     font-size: 20pt;
585        //! #     color: white;
586        //! # }
587        //!     Rectangle {
588        //!         x: -40px; y: -40px;
589        //!         width: 100px;
590        //!         height: 100px;
591        //!         background: lightslategray;
592        //!     }
593        //! }
594        //!
595        //! // clip: true; Clips the children of this Rectangle
596        //! Rectangle {
597        //!     x: 50px; y: 250px;
598        //!     width: 150px;
599        //!     height: 150px;
600        //!     background: darkslategray;
601        //!     clip: true;
602        //! # Text {
603        //! #     text: "clip: true";
604        //! #     font-size: 20pt;
605        //! #     color: white;
606        //! # }
607        //!     Rectangle {
608        //!         x: -40px; y: -40px;
609        //!         width: 100px;
610        //!         height: 100px;
611        //!         background: lightslategray;
612        //!     }
613        //! }
614        //!
615        //! ```
616        //! By default, when child elements are outside the bounds of a parent,
617        //! they are still shown. When this property is set to `true`, the children
618        //! of this `Rectangle` are clipped and only the contents inside the elements bounds are shown.
619        //! </SlintProperty>
620        //!
621        //!
622        //! ## Border Radius Properties
623        /// The size of the radius. This single value is applied to all four corners.
624        /// \default 0
625        in property <length> border-radius;
626    } }
627
628    item! { BorderRectangle: BasicBorderRectangle {
629        //! To target specific corners with different values use the following properties:
630        ///
631        in property <length> border-top-left-radius;
632        ///
633        in property <length> border-top-right-radius;
634        ///
635        in property <length> border-bottom-left-radius;
636        ///
637        in property <length> border-bottom-right-radius;
638        //! ## Drop Shadows
639        //!
640        //! To achieve the graphical effect of a visually elevated shape that shows a shadow effect underneath the frame of
641        //! an element, it's possible to set the following `drop-shadow` properties:
642        //!
643        //! The CSS equivalent is `box-shadow`: `box-shadow: 2px 2px 4px 1px black` translates to
644        //! `drop-shadow-offset-x: 2px; drop-shadow-offset-y: 2px; drop-shadow-blur: 4px;
645        //! drop-shadow-spread: 1px; drop-shadow-color: black;`.
646        //!
647        //! ### drop-shadow-blur
648        //! <SlintProperty propName="drop-shadow-blur" typeName="length"/>
649        //! The radius of the shadow that also describes the level of blur applied to the shadow. Negative values are ignored and zero means no blur.
650        //!
651        //! ### drop-shadow-color
652        //! <SlintProperty propName="drop-shadow-color" typeName="color"/>
653        //! The base color of the shadow to use. Typically that color is the starting color of a gradient that fades into transparency.
654        //!
655        //! ### drop-shadow-offset-x
656        //! <SlintProperty propName="drop-shadow-offset-x" typeName="length"/>
657        //! The horizontal distance of the shadow from the element's frame.
658        //!
659        //!
660        //! ### drop-shadow-offset-y
661        //! <SlintProperty propName="drop-shadow-offset-y" typeName="length"/>
662        //! The vertical distance of the shadow from the element's frame.
663        //!
664        //! ### drop-shadow-spread
665        //! <SlintProperty propName="drop-shadow-spread" typeName="length"/>
666        //! Grows (positive) or shrinks (negative) the shadow shape on all sides before the blur is applied.
667        //! Equivalent to the spread radius in CSS `box-shadow`. Currently only supported by the Skia renderer.
668        //!
669        //! ## Inner Shadows
670        //!
671        //! Inner shadows are rendered inside the element's geometry (inverted from drop shadows), giving
672        //! the appearance of an inwards-cast shadow. They follow the same parameters as drop shadows.
673        //! Currently only supported by the Skia renderer.
674        //!
675        //! The CSS equivalent is `box-shadow` with the `inset` keyword: `box-shadow: inset 2px 2px 4px 1px black`
676        //! translates to `inner-shadow-offset-x: 2px; inner-shadow-offset-y: 2px; inner-shadow-blur: 4px;
677        //! inner-shadow-spread: 1px; inner-shadow-color: black;`.
678        //!
679        //! ### inner-shadow-blur
680        //! <SlintProperty propName="inner-shadow-blur" typeName="length"/>
681        //! The blur radius of the inner shadow.
682        //!
683        //! ### inner-shadow-color
684        //! <SlintProperty propName="inner-shadow-color" typeName="color"/>
685        //! The base color of the inner shadow.
686        //!
687        //! ### inner-shadow-offset-x
688        //! <SlintProperty propName="inner-shadow-offset-x" typeName="length"/>
689        //! Horizontal offset of the inner shadow inside the element.
690        //!
691        //! ### inner-shadow-offset-y
692        //! <SlintProperty propName="inner-shadow-offset-y" typeName="length"/>
693        //! Vertical offset of the inner shadow inside the element.
694        //!
695        //! ### inner-shadow-spread
696        //! <SlintProperty propName="inner-shadow-spread" typeName="length"/>
697        //! Positive spread thickens the shadow band along the element's interior boundary; negative spread
698        //! thins it.
699    } }
700
701    element! {
702        /// By default, a `Rectangle` is just an empty item that shows nothing. By setting a color or configuring a border,
703        /// it's then possible to draw a rectangle on the screen. \{#sls.meta.rectangle.purpose}
704        ///
705        /// <NotInSC>
706        /// When not part of a layout, its width and height default to 100% of the parent element.
707        /// </NotInSC>
708        ///
709        /// ```slint playground imageAlt="rectangle example"
710        /// export component ExampleRectangle inherits Window {
711        ///     width: 200px; height: 800px; background: transparent;
712        ///
713        ///     Rectangle {
714        ///         x: 10px; y: 10px;
715        ///         width: 180px;
716        ///         height: 180px;
717        ///         background: #315afd;
718        ///     }
719        ///
720        ///     // Rectangle with a border
721        ///     Rectangle {
722        ///         x: 10px; y: 210px;
723        ///         width: 180px;
724        ///         height: 180px;
725        ///         background: green;
726        ///         border-width: 2px;
727        ///         border-color: red;
728        ///     }
729        ///
730        ///     // Transparent Rectangle with a border and a radius
731        ///     Rectangle {
732        ///         x: 10px; y: 410px;
733        ///         width: 180px;
734        ///         height: 180px;
735        ///         border-width: 4px;
736        ///         border-color: black;
737        ///         border-radius: 30px;
738        ///     }
739        ///
740        ///     // A radius of width/2 makes it a circle
741        ///     Rectangle {
742        ///         x: 10px; y: 610px;
743        ///         width: 180px;
744        ///         height: 180px;
745        ///         background: yellow;
746        ///         border-width: 2px;
747        ///         border-color: blue;
748        ///         border-radius: self.width/2;
749        ///     }
750        /// }
751        /// ```
752        /// \group:elements
753        @sc @expands_to_parent_geometry
754        Rectangle: BorderRectangle
755    }
756
757    item! { ImageItem: Empty {
758        in property <length> width;
759        in property <length> height;
760        /// When set, the image is used as an alpha mask and is drawn in the given color (or with the gradient).
761        /// ```slint imageAlt="image example" width="300" height="200"
762        /// Image {
763        ///     source: @image-url("slint-logo-simple-dark.png");
764        ///     colorize: darkorange;
765        /// }
766        /// ```
767        in property <brush> colorize;
768        /// The [image](/reference/property-types/images/) to draw, created with
769        /// [`@image-url()`](/reference/language/expressions/#sls.expr.image.form)
770        /// or set by the application: by default no image, drawing
771        /// nothing. \{#sls.ref.image.source}
772        ///
773        /// Access an `image`'s source dimension using its `source.width` and
774        /// `source.height` properties. \{#sls.ref.image.source.dimensions}
775        ///
776        /// ```slint
777        /// export component Example inherits Window {
778        ///     in property <image> some_image: @image-url("images/logo.png");
779        ///
780        ///     out property <int> image-width: some_image.width;
781        ///     out property <int> image-height: some_image.height;
782        /// }
783        /// ```
784        @sc in property <image> source;
785        /// ```slint imageAlt="image fill example" width="300" height="200"
786        /// Image {
787        ///     width: 200px; height: 50px;
788        ///     source: @image-url("mini-banner.png");
789        ///     image-fit: fill;
790        /// }
791        /// ```
792        ///
793        /// ```slint imageAlt="image contain example" width="300" height="200"
794        /// Image {
795        ///     width: 250px; height: 40px;
796        ///     source: @image-url("mini-banner.png");
797        ///     image-fit: contain;
798        /// }
799        /// ```
800        ///
801        /// ```slint imageAlt="image cover example" width="300" height="200"
802        /// Image {
803        ///     width: 250px; height: 250px;
804        ///     source: @image-url("mini-banner.png");
805        ///     image-fit: cover;
806        /// }
807        /// ```
808        ///
809        /// ```slint imageAlt="image preserve example" width="400" height="400"
810        /// Image {
811        ///     width: 400px; height: 400px;
812        ///     source: @image-url("mini-banner.png");
813        ///     image-fit: preserve;
814        /// }
815        /// ```
816        /// \default `contain` when the `Image` element is part of a layout, `fill` otherwise
817        in property <ImageFit> image-fit;
818        /// ```slint imageAlt="image smooth example" width="300" height="300"
819        /// Image {
820        ///     width: 800px;
821        ///     source: @image-url("mini-banner.png");
822        ///     image-rendering: smooth;
823        /// }
824        /// ```
825        ///
826        /// ```slint imageAlt="image pixelated example" width="300" height="300"
827        /// Image {
828        ///     width: 800px;
829        ///     source: @image-url("mini-banner.png");
830        ///     image-rendering: pixelated;
831        /// }
832        /// ```
833        /// \default smooth
834        in property <ImageRendering> image-rendering;
835
836        @deprecated in property <angle> rotation-angle <=> transform-rotation;
837    } }
838
839    item! { ClippedImage: ImageItem {
840        /// The horizontal alignment of the image within the element.
841        /// \default center
842        in property <ImageHorizontalAlignment> horizontal-alignment;
843        /// The vertical alignment of the image within the element.
844        /// \default center
845        in property <ImageVerticalAlignment> vertical-alignment;
846        //! ## Image Tiling
847        /// How the image is tiled horizontally.
848        /// \default none
849        in property <ImageTiling> horizontal-tiling;
850        /// ```slint imageAlt="image horizontal tiling repeat example" width="400" height="400"
851        /// Image {
852        ///     width: 400px;
853        ///     height: 400px;
854        ///     source: @image-url("slint-logo.png");
855        ///     horizontal-tiling: repeat;
856        /// }
857        /// ```
858        ///
859        /// ```slint imageAlt="image horizontal tiling round example" width="400" height="400"
860        /// Image {
861        ///     width: 400px;
862        ///     height: 400px;
863        ///     source: @image-url("slint-logo.png");
864        ///     horizontal-tiling: round;
865        /// }
866        /// ```
867        /// ```slint imageAlt="image vertical tiling repeat example" width="400" height="400"
868        /// Image {
869        ///     width: 400px;
870        ///     height: 400px;
871        ///     source: @image-url("slint-logo.png");
872        ///     vertical-tiling: repeat;
873        /// }
874        /// ```
875        ///
876        /// ```slint imageAlt="image vertical tiling round example" width="400" height="400"
877        /// Image {
878        ///     width: 400px;
879        ///     height: 400px;
880        ///     source: @image-url("slint-logo.png");
881        ///     vertical-tiling: round;
882        /// }
883        /// ```
884        ///
885        /// ```slint imageAlt="image vertical and horizontal tiling round example" width="400" height="400"
886        /// Image {
887        ///     width: 400px;
888        ///     height: 400px;
889        ///     source: @image-url("slint-logo.png");
890        ///     vertical-tiling: round;
891        ///     horizontal-tiling: round;
892        /// }
893        /// ```
894        /// \default none
895        in property <ImageTiling> vertical-tiling;
896        // TODO: sets both horizontal-tiling and vertical-tiling at the same time.
897        // in property <ImageTiling> tiling;
898        //! ## Source Clip
899        ///
900        in property <int> source-clip-x;
901        ///
902        in property <int> source-clip-y;
903        /// \default source.width - source.clip-x
904        in property <int> source-clip-width;
905        /// \default source.height - source.clip-y
906        in property <int> source-clip-height;
907        //! Properties in source image coordinates that define the region of the source image that is rendered.
908        //! By default the entire source image is visible:
909    } }
910
911    element! {
912        /// ```slint imageAlt="image example" width="300" height="200"
913        /// Image {
914        ///     source: @image-url("mini-banner.png");
915        /// }
916        /// ```
917        ///
918        /// Use the `Image` element to display an
919        /// [image](/reference/property-types/images/). \{#sls.meta.image.purpose}
920        ///
921        /// <OnlyInSC>
922        /// The element draws the image of its `source` property pixel for pixel:
923        /// the image's top-left pixel is at the element's position, and one image
924        /// pixel covers one frame-buffer pixel, without scaling. \{#sls.ref.image.draw}
925        ///
926        /// The element is always the size of its source image: `width` and `height`
927        /// hold the dimensions of that image, and setting them is an
928        /// error. \{#sls.ref.image.size}
929        /// </OnlyInSC>
930        ///
931        /// \footer
932        /// <NotInSC>
933        /// ## Accessibility
934        ///
935        /// ### Alternative text
936        ///
937        /// Consider giving an alternative text description of your image by setting the `accessible-label` property:
938        ///
939        /// ```slint
940        /// Image {
941        ///     width: 100px;
942        ///     height: 100px;
943        ///     source: @image-url("slint-logo.png");
944        ///     accessible-label: "Slint logo";
945        /// }
946        /// ```
947        ///
948        /// ### Filtering out images for users of assistive technologies
949        ///
950        /// By default, images have the `accessible-role` property set to `image`.
951        /// If your image is purely decorative and doesn't convey any information,
952        /// consider removing it from the accessibility tree:
953        ///
954        /// ```slint
955        /// Image {
956        ///     source: @image-url("mini-banner.png");
957        ///     accessible-role: none;
958        /// }
959        /// ```
960        /// </NotInSC>
961        /// \group:elements
962        @sc @implicit_size
963        Image: ClippedImage
964    }
965
966    item! { ComponentContainer: Empty {
967        in property <component-factory> component-factory;
968        out property <bool> has-component;
969
970        in-out property <length> width;
971        in-out property <length> height;
972    } }
973
974    element! {
975        @accepts_focus
976        ComponentContainer: ComponentContainer
977    }
978
979    item! { Transform: Empty {
980        in property <angle> transform-rotation;
981        in property <percent> transform-scale-x;
982        in property <percent> transform-scale-y;
983        in property <Point> transform-origin;
984    } }
985
986    element! {
987        @is_internal @expands_to_parent_geometry
988        Transform: Transform
989    }
990
991    item! { SimpleText: Empty {
992        in property <length> width;
993        in property <length> height;
994        /// The color of the text.
995        ///
996        /// ```slint "color: #3586f4;" imageAlt="text color" width="200" height="200" needsBackground
997        /// Text {
998        ///     text: "Hello";
999        ///     color: #3586f4;
1000        ///     font-size: 40pt;
1001        /// }
1002        /// ```
1003        /// \default <depends on theme>
1004        in property <brush> color;  // StyleMetrics.default-text-color  set in apply_default_properties_from_style
1005        /// The font size of the text.
1006        ///
1007        /// ```slint "font-size: 70pt;" imageAlt="text font-size" width="200" height="200" needsBackground
1008        /// Text {
1009        ///     text: "Big";
1010        ///     color: black;
1011        ///     font-size: 70pt;
1012        /// }
1013        /// ```
1014        in property <length> font-size;
1015        /// The weight of the font. The values range from 100 (lightest) to 900 (thickest). 400 is the normal weight. Use the <Link type="FontWeight" /> namespace for predefined constants.
1016        ///
1017        /// ```slint 'font-weight: FontWeight.extra-bold;' imageAlt="text font-weight" width="200" height="200" needsBackground
1018        /// Text {
1019        ///     text: "BOLD";
1020        ///     color: black;
1021        ///     font-size: 30pt;
1022        ///     font-weight: FontWeight.extra-bold;
1023        /// }
1024        /// ```
1025        in property <int> font-weight;
1026        /// ```slint "horizontal-alignment: left;" imageAlt="text-horizontal-alignment" width="200" height="200" needsBackground
1027        /// Text {
1028        ///     x: 0;
1029        ///     text: "Hello";
1030        ///     color: black;
1031        ///     font-size: 40pt;
1032        ///     horizontal-alignment: left;
1033        /// }
1034        /// ```
1035        in property <TextHorizontalAlignment> horizontal-alignment;
1036        /// The maximum number of lines to display. Wrapped lines count towards the limit, and
1037        /// with `overflow` set to `elide`, the ellipsis is placed on the last visible line.
1038        /// Values less than or equal to zero don't limit the number of lines.
1039        /// \default 0
1040        in property <int> max-lines;
1041        /// The text rendered.
1042        /// \default ""
1043        in property <string> text;
1044        /// The vertical alignment of the text.
1045        in property <TextVerticalAlignment> vertical-alignment;
1046
1047
1048        @deprecated in property <angle> rotation-angle <=> transform-rotation;
1049    } }
1050
1051    item! { ComplexText: SimpleText {
1052        /// The name of the font family selected for rendering the text.
1053        ///
1054        /// ```slint 'font-family: "Comic Sans MS";' imageAlt="text font-family" width="200" height="200" needsBackground
1055        /// Text {
1056        ///     text: "CoMiC!";
1057        ///     color: black;
1058        ///     font-size: 40pt;
1059        ///     font-family: "Comic Sans MS";
1060        /// }
1061        /// ```
1062        ///
1063        /// :::note[Note]
1064        ///   Make sure the font is loaded before using it in a `Text` element.
1065        ///   See <Link type="FontHandling" /> for more.
1066        /// :::
1067        in property <string> font-family;
1068        /// Whether or not the font face should be drawn italicized or not.
1069        ///
1070        /// ```slint "font-italic: true;" imageAlt="text font-family" width="200" height="200" needsBackground
1071        /// Text {
1072        ///     text: "Italic";
1073        ///     color: black;
1074        ///     font-italic: true;
1075        ///     font-size: 40pt;
1076        /// }
1077        /// ```
1078        /// \default false
1079        in property <bool> font-italic;
1080        /// How the text should behave when it exceeds the available space.
1081        in property <TextOverflow> overflow;
1082        /// ```slint "wrap: word-wrap;" imageAlt="wrap" width="200" height="200" needsBackground
1083        /// Text {
1084        ///     text: "This paragraph breaks into multiple lines of text";
1085        ///     font-size: 20pt;
1086        ///     wrap: word-wrap;
1087        ///     width: 180px;
1088        /// }
1089        /// ```
1090        in property <TextWrap> wrap;
1091        /// The letter spacing allows changing the spacing between the glyphs. A positive value increases the spacing and a negative value decreases the distance.
1092        /// ```slint "letter-spacing: 4px;" imageAlt="text-horizontal-alignment" width="200" height="200" needsBackground
1093        /// Text {
1094        ///     text: "Spaced!";
1095        ///     color: black;
1096        ///     font-size: 30pt;
1097        ///     letter-spacing: 4px;
1098        /// }
1099        /// ```
1100        in property <length> letter-spacing;
1101        /// The line height as a unitless factor (or a percentage: `150%` equals `1.5`) applied to
1102        /// the font's natural line height (ascent + descent + line gap). The default of `1` keeps
1103        /// the natural line height; larger values spread the lines apart, smaller values pull them
1104        /// together, and `0` collapses them onto each other. Negative or non-numeric values behave
1105        /// like `1`. Unlike CSS `line-height`, the factor is relative to the natural line height,
1106        /// not the font size, and keyword or length values aren't supported.
1107        ///
1108        /// ```slint "line-height-factor: 1.5;" imageAlt="text with increased line height" width="200" height="200" needsBackground
1109        /// Text {
1110        ///     text: "Two lines\nof text";
1111        ///     color: black;
1112        ///     font-size: 30pt;
1113        ///     line-height-factor: 1.5;
1114        /// }
1115        /// ```
1116        /// \default 1
1117        in property <float> line-height-factor: 1;
1118        /// The brush used for the text outline.
1119        /// ```slint "stroke: darkblue;" imageAlt="text stroke" width="300" height="200" needsBackground
1120        /// Text {
1121        ///     text: "Stroke";
1122        ///     stroke-width: 2px;
1123        ///     stroke: darkblue;
1124        ///     stroke-style: center;
1125        ///     font-size: 80px;
1126        ///     color: lightblue;
1127        /// }
1128        /// ```
1129        in property <brush> stroke;
1130        /// The width of the text outline. If the width is zero, then a hairline stroke (1 physical pixel) will be rendered.
1131        in property <length> stroke-width;
1132        /// ```slint "stroke-style: center;" imageAlt="stroke-style" width="200" height="200" needsBackground
1133        /// Text {
1134        ///     text: "Style";
1135        ///     stroke-width: 2px;
1136        ///     stroke: #3586f4;
1137        ///     stroke-style: center;
1138        ///     font-size: 60px;
1139        ///     color: white;
1140        /// }
1141        /// ```
1142        in property <TextStrokeStyle> stroke-style;
1143        /// The design metrics of the font scaled to the font pixel size used by the element.
1144        out property <FontMetrics> font-metrics { BuiltinFunction.ItemFontMetrics }
1145    } }
1146
1147    element! {
1148        /// ```slint playground
1149        /// // text-example.slint
1150        /// export component TextExample inherits Window {
1151        ///     // Text colored red.
1152        ///     Text {
1153        ///         x:0; y:0;
1154        ///         text: "Hello World";
1155        ///         color: red;
1156        ///     }
1157        ///
1158        ///     // This paragraph breaks into multiple lines of text.
1159        ///     Text {
1160        ///         x:0; y: 30px;
1161        ///         text: "This paragraph breaks into multiple lines of text";
1162        ///         wrap: word-wrap;
1163        ///         width: 150px;
1164        ///         height: 100%;
1165        ///     }
1166        /// }
1167        /// ```
1168        ///
1169        /// A `Text` element for displaying text.
1170        ///
1171        /// By default, the `min-width`, `min-height`, `preferred-width`, and `preferred-height`
1172        /// of a `Text` element are set to fit the full text as if it were displayed on a single line
1173        /// (unless the text contains explicit line breaks).
1174        /// However, if the `wrap` property is set to `word-wrap`, and/or if the `overflow` property is set to `elide`,
1175        /// the `min-width` is reduced to zero, allowing the text to wrap or be elided,
1176        /// while the `preferred-width` and `preferred-height` remain unchanged.
1177        ///
1178        /// \footer
1179        /// ## Accessibility
1180        ///
1181        /// By default, `Text` elements have the following accessibility properties set:
1182        ///
1183        ///  - `accessible-role: text;`
1184        ///  - `accessible-label: text;`
1185        /// \group:elements
1186        @implicit_size
1187        Text: ComplexText
1188    }
1189
1190    item! { StyledTextItem: Empty {
1191        in property <length> width;
1192        in property <length> height;
1193        /// The default color of the text, used when no color is specified via markup.
1194        /// \default <depends on theme>
1195        in property <brush> default-color;
1196        /// The default font family used to render the text, when no font is specified via markup. If left empty, the value falls back to the enclosing `Window`'s `default-font-family`.
1197        in property <string> default-font-family;
1198        /// The default font size used to render the text, when no size is specified via markup. If unset (or zero), the value falls back to the enclosing `Window`'s `default-font-size`.
1199        in property <length> default-font-size;
1200        /// The horizontal alignment of the text.
1201        in property <TextHorizontalAlignment> horizontal-alignment;
1202        /// The color used for rendering links in the text.
1203        in property <color> link-color: #00f;
1204        /// The maximum number of lines to display. Wrapped lines count towards the limit.
1205        /// Values less than or equal to zero don't limit the number of lines.
1206        /// \default 0
1207        in property <int> max-lines;
1208        /// The styled text rendered, using CommonMark markup with additional HTML tags for styling.
1209        /// \default ""
1210        in property <styled-text> text;
1211        /// The vertical alignment of the text.
1212        in property <TextVerticalAlignment> vertical-alignment;
1213        /// A callback that's invoked when a link in the text is clicked. The parameter contains the clicked link as a string.
1214        callback link-clicked(link: string);
1215    } }
1216
1217    element! {
1218        /// The `StyledText` element renders text with various styling and interactive properties, such as bolded, underlined and colored sections as well as HTTP links. It is based on a subset of the [commonmark](https://commonmark.org/) spec.
1219        ///
1220        /// ```slint imageAlt="Styled Text Example" width="200" height="200" scale="3"
1221        /// export component Example inherits Window {
1222        ///     in property <string> value: 55;
1223        ///     width: 200px;
1224        ///     height: 200px;
1225        ///     StyledText {
1226        ///       text: @markdown("This is a piece of <u>Styled Text</u>\n"
1227        ///                       "with a red value inserted:"
1228        ///                       "<font color=\"red\">\{value}</font>");
1229        ///     }
1230        /// }
1231        /// ```
1232        ///
1233        ///
1234        /// ## Features
1235        ///
1236        /// Styled Text supports the following features:
1237        ///
1238        /// Feature        | Method
1239        /// ---------------|-------
1240        /// Italics        | Builtin
1241        /// Strikethroughs | Builtin
1242        /// Inline code    | Builtin
1243        /// Links          | Builtin
1244        /// Ordered and unordered lists | Builtin
1245        /// Underlines     | `<u>` HTML tag
1246        /// Text Colors    |`<font color="...">` HTML tags
1247        ///
1248        /// ### Currently Unsupported
1249        ///
1250        /// Feature          |
1251        /// -----------------|
1252        /// Headings         |
1253        /// Images           |
1254        /// Tables           |
1255        /// Block Quotes     |
1256        /// Subscripts       |
1257        /// Superscripts     |
1258        /// Horizontal Rules |
1259        /// Footnotes        |
1260        /// Math expressions |
1261        /// Other HTML tags  |
1262        /// \group:elements
1263        @implicit_size
1264        StyledText: StyledTextItem
1265    }
1266
1267    item! { TouchArea {
1268        /// When disabled, the `TouchArea` doesn't recognize any touch or mouse events and they are
1269        /// passed through to elements underneath.
1270        ///
1271        /// ```slint playground imageAlt="Basic syntax" width="200" height="100" scale="2"
1272        /// import { Button, CheckBox } from "std-widgets.slint";
1273        ///
1274        /// export component Example inherits Window {
1275        ///     width: 200px; height: 100px;
1276        ///
1277        ///     VerticalLayout {
1278        ///         Rectangle {
1279        ///             Button {
1280        ///                 text: "Try to press me";
1281        ///             }
1282        ///             TouchArea {
1283        ///                 enabled: event-blocker.checked;
1284        ///             }
1285        ///         }
1286        ///         event-blocker := CheckBox {
1287        ///             text: "Block Access";
1288        ///         }
1289        ///     }
1290        /// }
1291        /// ```
1292        ///
1293        /// :::note{Note}
1294        /// When `enabled` is set to false while the `TouchArea` is pressed, `pointer-event` will be
1295        /// invoked with `PointerEventKind.Cancel`, and the `pressed` and `has-hover` properties will
1296        /// be reset to `false`.
1297        /// :::
1298        in property <bool> enabled: true;
1299        /// Set to true when the mouse is over the `TouchArea` area.
1300        out property <bool> has-hover;
1301        /// The mouse cursor when the mouse is hovering the `TouchArea`.
1302        in property <MouseCursor> mouse-cursor;
1303        /// Set by the `TouchArea` to the position of the mouse within it.
1304        out property <length> mouse-x;
1305        /// Set by the `TouchArea` to the position of the mouse within it.
1306        out property <length> mouse-y;
1307        /// Set by the `TouchArea` to the position of the mouse at the moment it was last pressed.
1308        out property <length> pressed-x;
1309        /// Set by the `TouchArea` to the position of the mouse at the moment it was last pressed.
1310        out property <length> pressed-y;
1311        /// Set to `true` by the `TouchArea` when the mouse is pressed over it.
1312        out property <bool> pressed;
1313        /// Invoked when clicked: A finger or the left mouse button is pressed, then released on this element. \{#sls.ref.toucharea.clicked}
1314        ///
1315        /// <OnlyInSC>
1316        /// The Touch Input chapter specifies when a press and a release count as a click. \{#sls.ref.toucharea.clicked.input}
1317        /// </OnlyInSC>
1318        @sc callback clicked;
1319        /// Invoked when double-clicked. The left mouse button is pressed and released twice on this element in a short
1320        /// period of time, or the same is done with a finger. The `clicked()` callbacks will be triggered before the `double-clicked()` callback is triggered.
1321        callback double-clicked;
1322        /// The mouse or finger has been moved. This will only be called if the mouse is also pressed or the finger continues to touch
1323        /// the display. See also **pointer-event(PointerEvent)**.
1324        callback moved;
1325        /// <PointerEvent />
1326        callback pointer-event(event: PointerEvent);
1327        /// Invoked when the mouse wheel was rotated or another scroll gesture was made.
1328        /// The `PointerScrollEvent` argument contains information about how much to scroll in what direction.
1329        /// <PointerScrollEvent />
1330        /// The returned `EventResult`indicates whether to accept or ignore the event. Ignored events are
1331        /// forwarded to the parent element.
1332        /// <EventResult />
1333        callback scroll-event(event: PointerScrollEvent) -> EventResult;
1334    } }
1335
1336    element! {
1337        /// Use `TouchArea` to control what happens when the region it covers is touched or interacted with
1338        /// using the mouse. \{#sls.meta.toucharea.purpose}
1339        ///
1340        /// When not part of a layout, its width or height default to 100% of the parent element. \{#sls.ref.toucharea.size}
1341        ///
1342        /// <OnlyInSC>
1343        /// Of the members of `TouchArea`, only `clicked` and the geometry properties are part of Slint SC. \{#sls.ref.toucharea.members}
1344        /// </OnlyInSC>
1345        ///
1346        /// <NotInSC>
1347        /// ```slint playground
1348        /// export component Example inherits Window {
1349        ///     width: 200px;
1350        ///     height: 100px;
1351        ///     area := TouchArea {
1352        ///         width: parent.width;
1353        ///         height: parent.height;
1354        ///         clicked => {
1355        ///             rect2.background = #ff0;
1356        ///         }
1357        ///     }
1358        ///     Rectangle {
1359        ///         x:0;
1360        ///         width: parent.width / 2;
1361        ///         height: parent.height;
1362        ///         background: area.pressed ? blue: red;
1363        ///     }
1364        ///     rect2 := Rectangle {
1365        ///         x: parent.width / 2;
1366        ///         width: parent.width / 2;
1367        ///         height: parent.height;
1368        ///     }
1369        /// }
1370        /// ```
1371        /// </NotInSC>
1372        /// \group:gestures
1373        @sc @expands_to_parent_geometry
1374        TouchArea: TouchArea
1375    }
1376
1377    item! { KeyBinding {
1378        /// The <Link type="keys" label="keys" /> to match against incoming key events.
1379        in property <keys> keys;
1380        /// Whether this KeyBinding is currently enabled. Disabled KeyBinding elements don't consume key events and never invoke their `activated()` callback.
1381        in property <bool> enabled: true;
1382        /// Invoked when the parent `FocusScope` receives a key event that matches the `keys` of this `KeyBinding`.
1383        callback activated;
1384    } }
1385
1386    element! {
1387        /// Place `KeyBinding` elements inside a `FocusScope` to declare keyboard shortcuts.
1388        /// KeyBindings use **logical keys**, based on the character a key produces, not physical key positions.
1389        ///
1390        /// See <Link type="KeyBindingOverview" label="Key Bindings"/> for details.
1391        @is_non_item_type
1392        KeyBinding: KeyBinding
1393    }
1394
1395    item! { FocusScope {
1396        /// Is `true` when the element has keyboard focus.
1397        out property <bool> has-focus;
1398        /// When false, the FocusScope will not accept focus, neither via click nor via tab focus traversal, not even programmatically.
1399        ///
1400        /// A parent `FocusScope` will still receive key events from child `FocusScope`s that were rejected, even if `enabled` is set to false.
1401        in property <bool> enabled: true;
1402        /// When true, the `FocusScope` will make itself the focused element when clicked.
1403        ///
1404        /// This property has no effect if the `enabled` property is set to false.
1405        in property <bool> focus-on-click: true;
1406        /// When true, the `FocusScope` will accept focus as part of the tab focus traversal.
1407        ///
1408        /// This property has no effect if the `enabled` property is set to false.
1409        in property <bool> focus-on-tab-navigation: true;
1410        //! ## Functions
1411        //!
1412        //! ### focus()
1413        //! Call this function to transfer keyboard focus to this `FocusScope`, to receive future <Link type="KeyEvent" />s.
1414        //!
1415        //! ### clear-focus()
1416        //! Call this function to remove keyboard focus from this `FocusScope` if it currently has the focus. See also <Link type="FocusHandling" />.
1417        /// This function is called during key event handling, *before* `key-pressed` is called. Use this to intercept key press events. The returned <Link type="EventResult" />
1418        /// indicates whether to accept or reject the event. Rejected events are forwarded to the parent element.
1419        callback capture-key-pressed(event: KeyEvent) -> EventResult;
1420        /// This function is called during key event handling, *before* `key-released` is called. Use this to intercept key release events. The returned <Link type="EventResult" />
1421        /// indicates whether to accept or reject the event. Rejected events are forwarded to the parent element.
1422        callback capture-key-released(event: KeyEvent) -> EventResult;
1423        /// Invoked when a key is pressed, the argument is a <Link type="KeyEvent" /> struct. The returned <Link type="EventResult" />
1424        /// indicates whether to accept or reject the event. Rejected events are forwarded to the parent element.
1425        callback key-pressed(event: KeyEvent) -> EventResult;
1426        /// Invoked when a key is released, the argument is a <Link type="KeyEvent" /> struct. The returned <Link type="EventResult" />
1427        /// indicates whether to accept or reject the event. Rejected events are forwarded to the parent element.
1428        callback key-released(event: KeyEvent) -> EventResult;
1429        /// Invoked when the focus on the `FocusScope` has changed. The argument is a a <Link type="FocusReason" /> enum containing the reason for focus change.
1430        callback focus-changed-event(reason: FocusReason);
1431        /// Invoked when the `FocusScope` gains focus. The argument is a a <Link type="FocusReason" /> enum containing the reason for focus gain.
1432        callback focus-gained(reason: FocusReason);
1433        /// Invoked when the `FocusScope` loses focus. The argument is a a <Link type="FocusReason" /> enum containing the reason for focus loss.
1434        callback focus-lost(reason: FocusReason);
1435
1436
1437
1438    } }
1439
1440    element! {
1441        /// ```slint playground
1442        /// export component Example inherits Window {
1443        ///     width: 100px;
1444        ///     height: 100px;
1445        ///     forward-focus: my-key-handler;
1446        ///     my-key-handler := FocusScope {
1447        ///         key-pressed(event) => {
1448        ///             debug(event.text);
1449        ///             if (event.modifiers.control) {
1450        ///                 debug("control was pressed during this event");
1451        ///             }
1452        ///             if (event.text == Key.Escape) {
1453        ///                 debug("Esc key was pressed")
1454        ///             }
1455        ///             accept
1456        ///         }
1457        ///
1458        ///         KeyBinding {
1459        ///             keys: @keys(Control + X);
1460        ///             activated => {
1461        ///                 debug("Control + X pressed")
1462        ///             }
1463        ///         }
1464        ///     }
1465        /// }
1466        /// ```
1467        ///
1468        /// The `FocusScope` can react to <Link type="KeyBindingOverview" label="keyboard shortcuts"/> using the <Link type="KeyBinding" label="KeyBinding element"/>, and exposes callbacks to handle key events manually.
1469        /// Note that `FocusScope` will only handle key events when it either `has-focus`, or when it surrounds another FocusScope that `has-focus` (see [Key Event Delivery](#key-event-delivery))
1470        ///
1471        /// The <Link type="KeyEvent" /> has a text property, which is a character of the key entered.
1472        /// When a non-printable key is pressed, the character will be either a control character,
1473        /// or it will be mapped to a private unicode character. The mapping of these non-printable, special characters is available in the <Link type="KeyEvent"/> namespace
1474        ///
1475        /// ## Key Event Delivery
1476        ///
1477        /// Key events are delivered to the element that `has-focus`.
1478        ///
1479        /// Before attempting to deliver the `KeyEvent`, it is checked whether some other element wants to intercept the `KeyEvent`.
1480        /// Visiting all the elements starting at the Window, going down toward the focused element, `capture_key_pressed` or `capture_key_released` is called.
1481        /// If any of these returns `EventResult::accept`, then key event processing stops at this point. If `EventResult::reject` is returned,
1482        /// then event delivery continues.
1483        ///
1484        /// If no element captures the `KeyEvent`, then the `KeyEvent` is delivered to the focused element by calling `key-pressed` or `key-released`.
1485        /// If these callbacks return `EventResult::accept`, then event delivery is finished and the event has been handled. Otherwise, (recursively) try
1486        /// to deliver the key event to the parent element.
1487        /// \group:keyboard-input
1488        @accepts_focus @expands_to_parent_geometry
1489        FocusScope: FocusScope {
1490            children: KeyBinding;
1491        }
1492    }
1493
1494    item! { Flickable: Empty {
1495        /// ```slint imageAlt="flickable interactive" width="200" height="200"
1496        /// Flickable {
1497        ///     interactive: false;
1498        /// }
1499        /// ```
1500        /// When false, the content can't be panned by the user, neither by dragging with the mouse
1501        /// nor with touch.
1502        in property <bool> interactive: true;
1503        /// When true, the content can be scrolled by clicking on it and dragging it with the cursor.
1504        /// Panning with a touch screen is only affected by `interactive`.
1505        in property <bool> mouse-drag-pan-enabled: true;
1506        /// The total width of the scrollable content.
1507        @shadowable in property <length> content-width;
1508        /// The total height of the scrollable content.
1509        @shadowable in property <length> content-height;
1510        /// The position of the scrollable content relative to the `Flickable`. This is usually a negative value.
1511        @shadowable in-out property <length> content-x;
1512        /// The position of the scrollable content relative to the `Flickable`. This is usually a negative value.
1513        @shadowable in-out property <length> content-y;
1514        @deprecated in property <length> viewport-width <=> content-width;
1515        @deprecated in property <length> viewport-height <=> content-height;
1516        @deprecated in-out property <length> viewport-x <=> content-x;
1517        @deprecated in-out property <length> viewport-y <=> content-y;
1518        /// Invoked when `content-x` or `content-y` is changed by a user action (dragging, scrolling).
1519        callback flicked;
1520    } }
1521
1522    element! {
1523        /// ```slint playground
1524        /// export component Example inherits Window {
1525        ///     width: 270px;
1526        ///     height: 100px;
1527        ///
1528        ///     Flickable {
1529        ///         content-height: 300px;
1530        ///         Text {
1531        ///             x:0;
1532        ///             y: 150px;
1533        ///             text: "This is some text that you have to scroll to see";
1534        ///         }
1535        ///     }
1536        /// }
1537        /// ```
1538        ///
1539        /// The `Flickable` is a low-level element that is the base for scrollable
1540        /// widgets, such as the <Link type="ScrollView"/> or <Link type="ListView"/>.
1541        /// When the `content-width` or the `content-height` is greater than the parent's `width` or `height`
1542        /// respectively, the element becomes scrollable.
1543        ///
1544        /// When unset, the `content-width` and `content-height` are
1545        /// calculated automatically based on the `Flickable`'s children. This isn't the
1546        /// case when using a `for` loop to populate the elements. This is a bug tracked in
1547        /// issue [#407](https://github.com/slint-ui/slint/issues/407).
1548        /// The maximum and preferred size of the `Flickable` are based on the content size.
1549        ///
1550        /// Note that the `Flickable` doesn't create a scrollbar.
1551        /// You can use a <Link type="ScrollView"/> instead or add your own scroll bars.
1552        ///
1553        /// When not part of a layout, its width or height defaults to 100% of the parent
1554        /// element when not specified.
1555        ///
1556        /// ## Pointer Event Interaction
1557        ///
1558        /// If the `Flickable`'s area contains elements that use `TouchArea` to act on clicking, such as `Button`
1559        /// widgets, then the following algorithm is used to distinguish between the user's intent of scrolling or
1560        /// interacting with `TouchArea` elements:
1561        ///
1562        /// 1. If the `Flickable`'s `interactive` property is `false`, all events are forwarded to elements underneath.
1563        ///    If `mouse-drag-pan-enabled` is `false`, only mouse events are forwarded this way, while touch events keep panning.
1564        /// 2. If a press event is received where the event's coordinates interact with a `TouchArea`, the event is stored
1565        ///    and any subsequent move and release events are handled as follows:
1566        ///    1. If 100ms elapse without any events, the stored press event is delivered to the `TouchArea`.
1567        ///    2. If a release event is received before 100ms have elapsed, the stored press event as well as the
1568        ///       release event are immediately delivered to the `TouchArea` and the algorithm resets.
1569        ///    3. Any move events received will start a flicking operation on the `Flickable` if all of the following
1570        ///       conditions are met:
1571        ///         1. The event is received before 500ms have elapsed since receiving the press event.
1572        ///         2. The distance to the press event exceeds 8 logical pixels in an orientation in which we are allowed to move.
1573        ///       If `Flickable` decides to flick, any press event sent previously to a `TouchArea`, is followed up
1574        ///       by an exit event. During the phase of receiving move events, the flickable follows the coordinates.
1575        /// 3. If the interaction of press, move, and release events begins at coordinates that do not intersect with
1576        ///    a `TouchArea`, then `Flickable` will flick immediately on pointer move events when the euclidean distance
1577        ///    to the coordinates of the press event exceeds 8 logical pixels.
1578        ///
1579        /// If no element underneath claims a press, the `Flickable` itself only intercepts it when it can actually pan in some direction,
1580        /// i.e. when its `content-width`/`content-height` exceed its own size, or its content is currently scrolled away from the origin.
1581        /// Otherwise the event is forwarded to elements underneath it,
1582        /// the same way wheel/scroll events already are (see below).
1583        ///
1584        /// ## Wheel/Scroll Event Interaction
1585        ///
1586        /// The `Flickable` also supports scrolling with the mouse wheel and touchpad scroll gestures.
1587        /// It will scroll regardless of the `interactive` and `mouse-drag-pan-enabled` properties.
1588        /// If the `Flickable` can scroll in the event's direction, the event will be intercepted.
1589        /// If the Flickable can't scroll in the direction of the event, the event will be forwarded to the parent.
1590        /// \group:gestures
1591        @expands_to_parent_geometry
1592        Flickable: Flickable
1593    }
1594
1595    item! { SwipeGestureHandler {
1596        /// When disabled, the `SwipeGestureHandler` doesn't recognize any gestures.
1597        in property <bool> enabled: true;
1598        /// The position of the pointer when the swipe started.
1599        out property <Point> pressed-position;
1600        /// The current pointer position.
1601        out property <Point> current-position;
1602        /// `true` while the gesture is recognized, false otherwise.
1603        out property <bool> swiping;
1604        //! ### Handle swipe directions properties
1605        /// \default false
1606        in property <bool> handle-swipe-left;
1607        /// \default false
1608        in property <bool> handle-swipe-right;
1609        /// \default false
1610        in property <bool> handle-swipe-up;
1611        /// \default false
1612        in property <bool> handle-swipe-down;
1613
1614        // For the future
1615        //in property <length> swipe-distance-threshold: 8px;
1616        //in property <duration> swipe-duration-threshold: 500ms;
1617        // in property <bool> delays-propagation;
1618        //in property <duration> propagation-delay: 100ms;
1619        // in property <int> required-touch-points: 1;
1620        //callback swipe-recognized();
1621
1622        /// Invoked when the pointer is moved.
1623        callback moved;
1624        /// Invoked after the swipe gesture was recognized and the pointer was released.
1625        callback swiped;
1626        /// Invoked when the swipe is cancelled programmatically or if the window loses focus.
1627        callback cancelled;
1628
1629        /// Cancel any on-going swipe gesture recognition.
1630        function cancel() { }
1631    } }
1632
1633    element! {
1634        /// Use the `SwipeGestureHandler` to handle swipe gesture in some particular direction.
1635        /// Recognition is limited to the element's geometry.
1636        ///
1637        /// The `SwipeGestureHandler` recognizes touchscreen swipes and mouse drags.
1638        ///
1639        /// ```slint playground
1640        /// export component Example inherits Window {
1641        ///     width: 270px;
1642        ///     height: 100px;
1643        ///
1644        ///     property <int> current-page: 0;
1645        ///
1646        ///     sgr := SwipeGestureHandler {
1647        ///         handle-swipe-right: current-page > 0;
1648        ///         handle-swipe-left: current-page < 5;
1649        ///         swiped => {
1650        ///             if self.current-position.x > self.pressed-position.x + self.width / 4 {
1651        ///                 current-page -= 1;
1652        ///             } else if self.current-position.x < self.pressed-position.x - self.width / 4 {
1653        ///                 current-page += 1;
1654        ///             }
1655        ///         }
1656        ///
1657        ///         HorizontalLayout {
1658        ///             property <length> position: - current-page * root.width;
1659        ///             animate position { duration: 200ms; easing: ease-in-out; }
1660        ///             property <length> swipe-offset;
1661        ///             x: position + swipe-offset;
1662        ///             states [
1663        ///                 swiping when sgr.swiping : {
1664        ///                     swipe-offset: sgr.current-position.x - sgr.pressed-position.x;
1665        ///                     out { animate swipe-offset { duration: 200ms; easing: ease-in-out; }  }
1666        ///                 }
1667        ///             ]
1668        ///
1669        ///             Rectangle { width: root.width; background: green; }
1670        ///             Rectangle { width: root.width; background: limegreen; }
1671        ///             Rectangle { width: root.width; background: yellow; }
1672        ///             Rectangle { width: root.width; background: orange; }
1673        ///             Rectangle { width: root.width; background: red; }
1674        ///             Rectangle { width: root.width; background: violet; }
1675        ///         }
1676        ///     }
1677        /// }
1678        /// ```
1679        ///
1680        /// Specify the different swipe directions you'd like to handle by setting the `handle-swipe-left/right/up/down` properties and react to the gesture in the `swiped` callback.
1681        ///
1682        /// Pointer press events on the recognizer's area are forwarded to the children with a small delay.
1683        /// If the pointer moves by more than 8 logical pixels in one of the enabled swipe directions, the gesture is recognized, and events are no longer forwarded to the children.
1684        ///
1685        /// To keep the gesture-recognition area large enough to feel responsive, wrap the `SwipeGestureHandler` around the controls it should
1686        /// handle swipes for, rather than placing it as a sibling before them.
1687        ///
1688        /// :::note{Known issue}
1689        /// [#6781](https://github.com/slint-ui/slint/issues/6781): `SwipeGestureHandler` can interfere with other controls that also recognize swipe gestures, such as `Slider`.
1690        /// Work around it by disabling the relevant `handle-swipe-*` properties while the child is being interacted with, for example in a
1691        /// `Slider`'s `changed` and `released` callbacks.
1692        /// :::
1693        /// \group:gestures
1694        @expands_to_parent_geometry
1695        SwipeGestureHandler: SwipeGestureHandler
1696    }
1697
1698    item! { ScaleRotateGestureHandler {
1699        /// When disabled, the `ScaleRotateGestureHandler` doesn't recognize any gestures and any on-going gesture is cancelled.
1700        in property <bool> enabled: true;
1701
1702        /// `true` while a gesture is being recognized, `false` otherwise.
1703        out property <bool> active;
1704        /// The cumulative scale factor of the gesture. Always starts at `1.0` when the gesture begins.
1705        /// A value greater than `1.0` means zooming in, less than `1.0` means zooming out.
1706        /// When the gesture is not active, the value is `1.0`.
1707        out property <float> scale;
1708        /// The cumulative rotation angle of the gesture. Always starts at `0deg` when the gesture begins.
1709        /// Positive values indicate clockwise rotation, negative values indicate counter-clockwise rotation.
1710        /// When the gesture is not active, the value is `0deg`.
1711        out property <angle> rotation;
1712        /// The center point of the gesture, in the coordinate system of the `ScaleRotateGestureHandler`.
1713        /// For two-finger touch input, this is the midpoint between the two fingers.
1714        /// For trackpad gestures, this is the mouse cursor position.
1715        out property <Point> center;
1716
1717        /// Invoked when a gesture begins. Use this to capture the initial state you want to transform.
1718        callback started;
1719        /// Invoked whenever the `scale`, `rotation`, or `center` changes during the gesture.
1720        callback updated;
1721        /// Invoked when the gesture completes normally (fingers lifted).
1722        callback ended;
1723        /// Invoked when the gesture is cancelled, for example when the handler is disabled during an active gesture or the window loses focus.
1724        callback cancelled;
1725    } }
1726
1727    element! {
1728        /// Use the `ScaleRotateGestureHandler` to handle pinch and rotation gestures.
1729        /// Recognition is limited to the element's geometry.
1730        ///
1731        /// The `ScaleRoteGestureHandler` supports touchscreens on all platforms, and additionally supports trackpad gestures on macOS and iOS.
1732        ///
1733        /// ```slint playground
1734        /// export component Example inherits Window {
1735        ///     width: 400px;
1736        ///     height: 400px;
1737        ///
1738        ///     property <float> start-scale;
1739        ///     property <angle> start-rotation;
1740        ///
1741        ///     gesture := ScaleRotateGestureHandler {
1742        ///         started => {
1743        ///             start-scale = rect.current-scale;
1744        ///             start-rotation = rect.current-rotation;
1745        ///         }
1746        ///         updated => {
1747        ///             rect.current-scale = start-scale * self.scale;
1748        ///             rect.current-rotation = start-rotation + self.rotation;
1749        ///         }
1750        ///
1751        ///         rect := Rectangle {
1752        ///             background: @radial-gradient(circle, #4488ff, #224488);
1753        ///             border-radius: 8px;
1754        ///
1755        ///             property <float> current-scale: 1.0;
1756        ///             property <angle> current-rotation: 0deg;
1757        ///             width: 200px * self.current-scale;
1758        ///             height: 200px * self.current-scale;
1759        ///             x: (parent.width - self.width) / 2;
1760        ///             y: (parent.height - self.height) / 2;
1761        ///
1762        ///             Text {
1763        ///                 text: "Pinch & rotate";
1764        ///                 color: white;
1765        ///             }
1766        ///         }
1767        ///     }
1768        /// }
1769        /// ```
1770        ///
1771        /// The `scale` property provides a cumulative scale factor relative to the start of the gesture (starting at `1.0`).
1772        /// The `rotation` property provides a cumulative rotation angle (starting at `0deg`).
1773        /// Use the `started` callback to capture your initial state, then multiply by `scale` and add `rotation` in the `updated` callback to apply the gesture.
1774        /// \group:gestures
1775        @expands_to_parent_geometry
1776        ScaleRotateGestureHandler: ScaleRotateGestureHandler
1777    }
1778
1779    item! { DragArea {
1780        /// Set to `false` to stop the `DragArea` from starting drags.
1781        /// Events still reach the child elements.
1782        in property <bool> enabled: true;
1783        /// The payload that's transferred to a <Link type="DropArea" /> when a drop happens.
1784        in property <data-transfer> data;
1785        /// Bitmap drawn under the cursor while a drag is in flight.
1786        /// When unset (the default empty image), no overlay is drawn.
1787        in property <image> drag-image;
1788        /// Horizontal hot spot within `drag-image` that aligns with the cursor, in image pixel coordinates.
1789        /// `0` puts the image's left edge at the cursor; following HTML5's `setDragImage(image, x, y)` convention.
1790        in property <int> drag-image-offset-x;
1791        /// Vertical hot spot within `drag-image` that aligns with the cursor, in image pixel coordinates.
1792        /// `0` puts the image's top edge at the cursor.
1793        in property <int> drag-image-offset-y;
1794        /// Whether the source allows the drop to copy the data. The source retains the data.
1795        in property <bool> allow-copy;
1796        /// Whether the source allows the drop to move the data. The source should remove the
1797        /// original from its model in the `drag-finished` callback when the action is `move`.
1798        in property <bool> allow-move;
1799        /// Whether the source allows the drop to link to the data. Neither side gives up ownership.
1800        in property <bool> allow-link;
1801        /// `true` once the press has crossed the drag threshold and a drag is in flight,
1802        /// `false` once the drop completes or the drag is cancelled.
1803        out property <bool> dragging;
1804        /// Fires when the drag ends: with the chosen action on a successful drop, or with
1805        /// `DragAction.none` if the drag was cancelled.
1806        callback drag-finished(action: DragAction);
1807    } }
1808
1809    element! {
1810        /// Use `DragArea` to make any part of the UI draggable.
1811        /// A drag starts when the user presses the mouse inside the area and moves past a small threshold,
1812        /// and the value bound to `data` becomes the drag payload delivered to a <Link type="DropArea" />.
1813        /// A click doesn't start a drag, so child elements like <Link type="TouchArea" /> stay interactive.
1814        ///
1815        /// The payload is a `data-transfer` value, which abstracts over the file-type transfer mechanisms supported by each platform.
1816        /// `data-transfer` values are opaque in Slint code:
1817        /// construct and read them via callbacks implemented in the host language.
1818        ///
1819        /// The source declares which actions it permits via `allow-copy`, `allow-move`, and `allow-link`.
1820        /// At least one must be set to true; a `DragArea` that permits no action never starts a drag.
1821        /// When no modifier key is pressed, the proposed action is the first allowed of move, copy, link;
1822        /// modifier keys request a specific action (Ctrl -> copy, Shift -> move, Ctrl+Shift -> link).
1823        /// The target picks the final action from this set in its `can-drop` callback. Once a drop completes
1824        /// (or the drag is cancelled), `drag-finished(action)` fires so a "move" source can remove the original data.
1825        ///
1826        /// See <Link type="DragAndDrop" /> for a usage guide and a complete example.
1827        /// \group:drag-and-drop
1828        @expands_to_parent_geometry
1829        DragArea: DragArea
1830    }
1831
1832    item! { DropArea {
1833        /// Set to `false` to stop the `DropArea` from accepting any drops.
1834        in property <bool> enabled: true;
1835        /// Return the action this target wants to perform with the drag, or `DragAction.none` to reject.
1836        /// The runtime clamps the returned value to the source's allowed set: anything the source did not
1837        /// allow is treated as `none`.
1838        /// The argument is a <Link type="DropEvent" /> describing the drag.
1839        callback can-drop(event: DropEvent) -> DragAction;
1840        /// Invoked when the user releases the mouse over the area after `can-drop` returned a non-`none`
1841        /// action. Use this callback to read `event.data` and apply the drop. The returned
1842        /// `DragAction` is reported to the source via `drag-finished`; return `event.proposed-action`
1843        /// to mirror what was negotiated during hover, or a different action to refine the choice at
1844        /// drop time. The runtime clamps the return value against the source's allowed set.
1845        callback dropped(event: DropEvent) -> DragAction;
1846        /// `true` while an accepted drag hovers over the area, `false` otherwise.
1847        /// Bind it to a visual property to give the user feedback, for example a background color.
1848        out property <bool> has-drag;
1849        /// The action the runtime is currently negotiating with the source: `none` when no drag is hovering,
1850        /// or `copy`/`move`/`link` once a concrete action is settled.
1851        out property <DragAction> current-action;
1852    } }
1853
1854    element! {
1855        /// Use `DropArea` to accept drops coming from a <Link type="DragArea" />, or from another application on platforms that support it.
1856        /// The `can-drop` callback runs while the cursor moves over the area to decide whether to accept the drag,
1857        /// and which action (copy/move/link) to perform.
1858        /// The `dropped` callback runs when the user releases the mouse inside the area after `can-drop` returned
1859        /// a non-`none` action.
1860        ///
1861        /// See <Link type="DragAndDrop" /> for a usage guide and a complete example.
1862        /// \group:drag-and-drop
1863        @expands_to_parent_geometry
1864        DropArea: DropArea
1865    }
1866
1867    item! { MenuItem {
1868        /// The title shown for this menu item.
1869        /// \default ""
1870        in property <string> title;
1871        /// Invoked when the menu entry is activated.
1872        callback activated;
1873        /// When disabled, the `MenuItem` can be selected but not activated.
1874        in property <bool> enabled: true;
1875        /// When true, the `MenuItem` can be checked. The value of the `checked` property is toggled when the user activates the menu item.
1876        /// \default false
1877        in property <bool> checkable: false;
1878        /// The keyboard shortcut for this `MenuItem`.
1879        ///
1880        /// This property can only be set in a `MenuItem` that is part of a <Link type="MenuBar"/>.
1881        in property <keys> shortcut;
1882        /// When true, a checkmark will be shown next to the title of the `MenuItem`.
1883        /// \default false
1884        in-out property <bool> checked: false;
1885        /// The icon shown next to the title.
1886        in property <image> icon;
1887    } }
1888
1889    element! {
1890        /// A `MenuItem` represents a single menu entry. It must be a child of a `Menu` element.
1891        @is_non_item_type @disallow_global_types_as_child_elements
1892        MenuItem: MenuItem
1893    }
1894
1895    element! {
1896        /// A `MenuSeparator` represents a separator in a menu.
1897        /// It cannot have children, and doesn't have properties or callbacks.
1898        /// MenuSeparator at the beginning or end of a menu will not be visible.
1899        /// Consecutive `MenuSeparator`s will be merged into one.
1900        @is_non_item_type @disallow_global_types_as_child_elements
1901        MenuSeparator
1902    }
1903
1904    element! {
1905        /// Place the `Menu` element in a <Link type="MenuBar" />, a `ContextMenuArea`, or within another `Menu`.
1906        /// Use `MenuItem` children of individual menu items, `Menu` children to create sub-menus, and `MenuSeparator` to create separators.
1907        @is_non_item_type @disallow_global_types_as_child_elements
1908        Menu {
1909            /// This is the label of the menu as written in the menu bar or in the parent menu.
1910            /// \default ""
1911            in property <string> title;
1912            /// When disabled, the `Menu` can be selected but not activated.
1913            in property <bool> enabled: true;
1914            /// The icon shown next to the title when in a parent menu.
1915            in property <image> icon;
1916
1917
1918            children: MenuItem, MenuSeparator, Menu;
1919        }
1920    }
1921
1922    element! {
1923        /// Use the `MenuBar` element in a <Link type="Window" /> to declare the structure of a menu bar, including the actual
1924        /// menus and sub-menus.
1925        ///
1926        /// :::note{Note}
1927        /// There can only be one `MenuBar` element in a `Window` and it must not be in a `for` or a `if`.
1928        /// :::
1929        ///
1930        /// The `MenuBar` doesn't have properties, but it must contain <Link type="Menu" /> as children that represent top level entries in the menu bar.
1931        ///
1932        /// Depending on the platform, the menu bar might be native or rendered by Slint.
1933        /// This means that for example, on macOS, the menu bar will be at the top of the screen.
1934        /// The `width` and `height` property of the <Link type="Window" /> define the client area, excluding the menu bar.
1935        /// The `x` and `y` properties of `Window` children are also relative to the client area.
1936        ///
1937        /// ### Example
1938        ///
1939        /// ```slint
1940        /// export component Example inherits Window {
1941        ///     MenuBar {
1942        ///         Menu {
1943        ///             title: @tr("File");
1944        ///             MenuItem {
1945        ///                 title: @tr("New");
1946        ///                 activated => { file-new(); }
1947        ///                 shortcut: @keys(Control + N);
1948        ///             }
1949        ///             MenuItem {
1950        ///                 title: @tr("Open");
1951        ///                 activated => { file-open(); }
1952        ///                 shortcut: @keys(Control + O);
1953        ///             }
1954        ///         }
1955        ///         Menu {
1956        ///             title: @tr("Edit");
1957        ///             MenuItem {
1958        ///                 title: @tr("Copy");
1959        ///             }
1960        ///             MenuItem {
1961        ///                 title: @tr("Paste");
1962        ///             }
1963        ///             MenuSeparator {}
1964        ///             Menu {
1965        ///                 title: @tr("Find");
1966        ///                 MenuItem {
1967        ///                     title: @tr("Find in document...");
1968        ///                 }
1969        ///                 MenuItem {
1970        ///                     title: @tr("Find Next");
1971        ///                 }
1972        ///                 MenuItem {
1973        ///                     title: @tr("Find Previous");
1974        ///                 }
1975        ///             }
1976        ///         }
1977        ///     }
1978        ///
1979        ///     callback file-new();
1980        ///     callback file-open();
1981        ///
1982        ///     // ... actual window content goes here
1983        /// }
1984        /// ```
1985        /// \skip_children
1986        @is_non_item_type @disallow_global_types_as_child_elements
1987        MenuBar {
1988            /// Whether this menu bar should be visible.  If the menu bar is not visible, the menu bar will not take up any space but shortcuts will still function.
1989            /// \default true
1990            in property <bool> visible: true;
1991
1992
1993            children: Menu;
1994        }
1995    }
1996
1997    item! { ContextMenu: Empty {
1998        callback activated(entry: MenuEntry);
1999        callback sub-menu(entry: MenuEntry) -> [MenuEntry];
2000        callback show(position: Point);
2001        function close() { }
2002        @pure function is-open() -> bool { }
2003        in property <bool> enabled: true;
2004    } }
2005
2006    element! {
2007        // The NativeItem, exported as ContextMenuInternal for the style
2008        @is_internal @expands_to_parent_geometry
2009        ContextMenuInternal: ContextMenu {
2010            in property <[MenuEntry]> entries;
2011        }
2012    }
2013
2014    element! {
2015        // Lowered in lower_menus pass.
2016        /// Use the non-visual `ContextMenuArea` element to declare an area where the user can show a context menu.
2017        ///
2018        /// The context menu is shown if the user right-clicks on the area covered by the `ContextMenuArea` element,
2019        /// or if the user presses the "Menu" key on their keyboard while a `FocusScope` within the `ContextMenuArea` has focus.
2020        /// On Android, the menu is shown with a long press.
2021        /// Call the `show()` function on the `ContextMenuArea` element to programmatically show the context menu.
2022        ///
2023        /// One of the children of the `ContextMenuArea` must be a `Menu` element, which defines the menu to be shown.
2024        /// There can be at most one `Menu` child, all other children must be of a different type and will be shown as regular visual children.
2025        /// Define the structure of the menu by placing `MenuItem` or `Menu` elements inside that `Menu`.
2026        ///
2027        /// \footer
2028        /// ## Example
2029        ///
2030        /// ```slint
2031        /// export component Example {
2032        ///     ContextMenuArea {
2033        ///         Menu {
2034        ///             MenuItem {
2035        ///                 title: @tr("Cut");
2036        ///                 activated => { debug("Cut"); }
2037        ///             }
2038        ///             MenuItem {
2039        ///                 title: @tr("Copy");
2040        ///                 activated => { debug("Copy"); }
2041        ///             }
2042        ///             MenuItem {
2043        ///                 title: @tr("Paste");
2044        ///                 activated => { debug("Paste"); }
2045        ///             }
2046        ///             MenuSeparator {}
2047        ///             Menu {
2048        ///                 title: @tr("Find");
2049        ///                 MenuItem {
2050        ///                     title: @tr("Find Next");
2051        ///                 }
2052        ///                 MenuItem {
2053        ///                     title: @tr("Find Previous");
2054        ///                 }
2055        ///             }
2056        ///         }
2057        ///     }
2058        /// }
2059        /// ```
2060        /// \group:window
2061        @expands_to_parent_geometry
2062        ContextMenuArea: Empty {
2063            //! ## Function
2064            //!
2065            //! ### show(Point)
2066            //!
2067            //! Call this function to programmatically show the context menu at the given position relative to the `ContextMenuArea` element.
2068            //!
2069            //! ## close()
2070            //!
2071            //! Close the context menu if it's currently open.
2072            // This is actually function as part of out interface, but a callback as much is the runtime concerned
2073            callback show(position: Point);
2074            function close() { }
2075
2076
2077            //! ### enabled
2078            //!
2079            //! <SlintProperty propName="enabled" typeName="bool" defaultValue="true">
2080            //! When disabled, the `Menu` is not showing.
2081            //! </SlintProperty>
2082            in property <bool> enabled: true;
2083            children: Menu;
2084        }
2085    }
2086
2087    item! { WindowItem {
2088        /// The width of the window. \{#sls.ref.window.width}
2089        ///
2090        /// <OnlyInSC>
2091        /// The application gives the window its size when it creates the component, so this is a value the file reads,
2092        /// and binding it is an error. \{#sls.ref.window.width-out}
2093        /// </OnlyInSC>
2094        @sc in-out property <length> width;
2095        /// The height of the window. \{#sls.ref.window.height}
2096        ///
2097        /// <OnlyInSC>
2098        /// The application gives the window its size when it creates the component, so this is a value the file reads,
2099        /// and binding it is an error. \{#sls.ref.window.height-out}
2100        /// </OnlyInSC>
2101        @sc in-out property <length> height;
2102        /// Whether the window should be placed above all other windows on window managers supporting it.
2103        /// \default false
2104        in property <bool> always-on-top;
2105        /// Whether to display the Window in full-screen mode. In full-screen mode the Window will occupy the entire screen, it will not be resizable, and it will not display the title bar.
2106        /// \default true if 'SLINT_FULLSCREEN' environment variable is set, otherwise false
2107        in-out property <bool> full-screen;
2108        /// Whether the window is minimized. Setting this to true minimizes the window.
2109        @shadowable in-out property <bool> minimized;
2110        /// Whether the window is maximized. Setting this to true maximizes the window.
2111        @shadowable in-out property <bool> maximized;
2112        /// The background brush of the `Window`. It is painted first, covering the whole window. \{#sls.ref.window.background}
2113        ///
2114        /// <OnlyInSC>
2115        /// This background must be an opaque color literal.
2116        /// Rendering writes every pixel of the frame buffer, and there's nothing
2117        /// underneath the window for a translucent background to blend with. \{#sls.ref.window.opaque}
2118        /// </OnlyInSC>
2119        /// \default depends on the style
2120        @sc in property <brush> background; // StyleMetrics.background  set in apply_default_properties_from_style
2121        @deprecated in property <brush> color <=> background;
2122        /// The font family to use as default in text elements inside this window, that don't have their `font-family` property set.
2123        in property <string> default-font-family;
2124        /// The font size to use as default in text elements inside this window, that don't have their `font-size` property set. The value of this property also forms the basis for relative font sizes.
2125        /// \default 0
2126        in property <length> default-font-size;
2127        /// The font weight to use as default in text elements inside this window, that don't have their `font-weight` property set. The values range from 100 (lightest) to 900 (thickest). 400 is the normal weight. Use the <Link type="FontWeight" /> namespace for predefined constants.
2128        in property <int> default-font-weight;
2129        /// The window icon shown in the title bar or the task bar on window managers supporting it.
2130        in property <image> icon;
2131        /// Whether the window should be borderless/frameless or not.
2132        /// \default false
2133        in property <bool> no-frame;
2134        ///     :::caution[Caution]
2135        ///     This property is `winit` only for now.
2136        ///     :::
2137        ///     Size of the resize border in borderless/frameless windows.
2138        /// \default 0
2139        in property <length> resize-border-width;
2140        /// The window title that is shown in the title bar.
2141        /// \default the name of the running program
2142        in property <string> title { BuiltinFunction.DefaultWindowTitle }
2143        /// Some devices, such as mobile phones, allow programs to overlap the system UI. A few examples for this are the notch on iPhones, the window buttons on macOS on windows that extend their content over the titlebar and the system bar on Android. This property exposes the amount of space at the edges of the window that can be drawn to but where no interactive elements should be placed. On most devices, this is 0 for all sides.
2144        out property <Edges> safe-area-insets;
2145        /// On mobile devices, virtual keyboards (aka software keyboards or onscreen keyboards) are displayed on top of the application. When such a keyboard is shown, this property denotes the position of the top left boundary of the rectangle covered by it in window coordinates.
2146        out property <Point> virtual-keyboard-position;
2147        /// On mobile devices, virtual keyboards (aka software keyboards or onscreen keyboards) are displayed on top of the application. When such a keyboard is shown, this property denotes the width and height of the rectangle covered by it in window coordinates.
2148        out property <Size> virtual-keyboard-size;
2149        /// Request that the window be closed.
2150        /// This triggers the `close-requested` callback, giving the application a chance to cancel the close.
2151        /// Returns `true` if the application accepted the close request; false otherwise.
2152        /// Returns `false` if called on a child `Window` element, which can't be closed independently.
2153        @shadowable function close() -> bool { }
2154        /// Hide this window. This also drops the strong reference on the window, so if this was
2155        /// the last reference, the event loop will quit.
2156        @shadowable function hide() { }
2157    } }
2158
2159    element! {
2160        /// `Window` is the root of the tree of elements that are visible on the screen. \{#sls.meta.window.purpose}
2161        ///
2162        /// <NotInSC>
2163        /// The `Window` geometry will be restricted by its layout constraints: Setting the `width` will result in a fixed width,
2164        /// and the window manager will respect the `min-width` and `max-width` so the window can't be resized bigger
2165        /// or smaller. The initial width can be controlled with the `preferred-width` property. The same applies to the `Window`s height.
2166        /// </NotInSC>
2167        ///
2168        /// <NotInSC>
2169        /// Use the <Link type="MenuBar" /> element to declare a menu bar for the window.
2170        /// </NotInSC>
2171        /// \group:window
2172        @sc
2173        Window: WindowItem {
2174            children: MenuBar;
2175        }
2176    }
2177
2178    item! { WindowMoveArea {
2179        /// Set to `false` to stop the `WindowMoveArea` from initiating window moves.
2180        /// Events still reach the child elements.
2181        in property <bool> enabled: true;
2182    } }
2183
2184    element! {
2185        /// Use `WindowMoveArea` to let the user move the window by dragging a region of your UI,
2186        /// such as a custom title bar in a window without native decorations (`no-frame: true`).
2187        ///
2188        /// The move starts when the user presses the left mouse button inside the area and drags past a small threshold.
2189        /// A plain click doesn't move the window, so child elements like <Link type="TouchArea" /> stay interactive.
2190        ///
2191        /// The windowing system performs the move.
2192        /// It requires a backend and platform with support for it (winit on Windows, macOS, X11, and Wayland; Qt).
2193        /// On platforms without support, the element does nothing.
2194        ///
2195        /// When not part of a layout, its width and height default to 100% of the parent element.
2196        ///
2197        /// ```slint playground
2198        /// export component Example inherits Window {
2199        ///     no-frame: true;
2200        ///     preferred-width: 400px;
2201        ///     preferred-height: 300px;
2202        ///     VerticalLayout {
2203        ///         Rectangle {
2204        ///             height: 32px;
2205        ///             background: #444444;
2206        ///             WindowMoveArea {
2207        ///                 HorizontalLayout {
2208        ///                     Text {
2209        ///                         text: "My Application";
2210        ///                         color: white;
2211        ///                         vertical-alignment: center;
2212        ///                         horizontal-alignment: center;
2213        ///                     }
2214        ///                 }
2215        ///             }
2216        ///         }
2217        ///         Rectangle {
2218        ///             background: white;
2219        ///         }
2220        ///     }
2221        /// }
2222        /// ```
2223        /// \group:window
2224        @expands_to_parent_geometry
2225        WindowMoveArea: WindowMoveArea
2226    }
2227
2228    item! { BoxShadow: Empty {
2229        in property <length> border-top-left-radius;
2230        in property <length> border-top-right-radius;
2231        in property <length> border-bottom-left-radius;
2232        in property <length> border-bottom-right-radius;
2233        in property <length> offset-x;
2234        in property <length> offset-y;
2235        in property <color> color;
2236        in property <length> blur;
2237        in property <length> spread;
2238        in property <bool> inset;
2239    } }
2240
2241    element! {
2242        @is_internal @expands_to_parent_geometry
2243        BoxShadow: BoxShadow
2244    }
2245
2246    item! { TextInput {
2247        /// The text rendered and editable by the user.
2248        /// \default ""
2249        in-out property <string> text;
2250        /// The name of the font family selected for rendering the text.
2251        in property <string> font-family;
2252        /// The font size of the text.
2253        in property <length> font-size;
2254        /// Whether or not the font face should be drawn italicized or not.
2255        /// \default false
2256        in property <bool> font-italic;
2257        /// The weight of the font. The values range from 100 (lightest) to 900 (thickest). 400 is the normal weight.
2258        in property <int> font-weight;
2259        /// The color of the text.
2260        /// \default depends on the style
2261        in property <brush> color; // StyleMetrics.default-text-color  set in apply_default_properties_from_style
2262        /// The foreground color of the selection.
2263        in property <color> selection-foreground-color; // StyleMetrics.selection-foreground set in apply_default_properties_from_style
2264        /// The background color of the selection.
2265        in property <color> selection-background-color; // StyleMetrics.selection-background set in apply_default_properties_from_style
2266        /// The horizontal alignment of the text.
2267        in property <TextHorizontalAlignment> horizontal-alignment;
2268        /// The vertical alignment of the text.
2269        in property <TextVerticalAlignment> vertical-alignment;
2270        /// The way the text input wraps. Only makes sense when `single-line` is false.
2271        /// \default no-wrap
2272        in property <TextWrap> wrap;
2273        /// The letter spacing allows changing the spacing between the glyphs. A positive value increases the spacing and a negative value decreases the distance.
2274        /// \default 0
2275        in property <length> letter-spacing;
2276        /// The line height as a unitless factor (or a percentage: `150%` equals `1.5`) applied to
2277        /// the font's natural line height (ascent + descent + line gap). The default of `1` keeps
2278        /// the natural line height; larger values spread the lines apart, smaller values pull them
2279        /// together, and `0` collapses them onto each other. Negative or non-numeric values behave
2280        /// like `1`. Unlike CSS `line-height`, the factor is relative to the natural line height,
2281        /// not the font size, and keyword or length values aren't supported.
2282        /// \default 1
2283        in property <float> line-height-factor: 1;
2284        in property <length> width;
2285        in property <length> height;
2286        /// The height of the page used to compute how much to scroll when the user presses page up or page down.
2287        in property <length> page-height;
2288        /// The width of the text cursor.
2289        /// \default provided at run-time by the selected widget style
2290        in property <length> text-cursor-width; // StyleMetrics.text-cursor-width  set in apply_default_properties_from_style
2291        ///  Use this to configure `TextInput` for editing special input, such as password fields.
2292        /// \default text
2293        in property <InputType> input-type;
2294        /// Hints for the platform's input method (such as a soft keyboard), for example to configure auto-capitalization.
2295        /// The input method may take these hints into account, but might also ignore them.
2296        in property <InputMethodHints> input-method-hints;
2297        // Internal, undocumented property, only exposed for tests.
2298        out property <int> cursor-position-byte-offset;
2299        // Internal, undocumented property, only exposed for tests.
2300        out property <int> anchor-position-byte-offset;
2301        /// `TextInput` sets this to `true` when it's focused. Only then it receives <Link type="KeyEvent"/>s.
2302        out property <bool> has-focus;
2303        /// Invoked when the enter key is pressed.
2304        callback accepted;
2305        /// Invoked when the text has changed because the user modified it.
2306        callback edited;
2307        /// The cursor was moved to the new (x, y) position described by the `Point` argument.
2308        callback cursor-position-changed(position: Point);
2309        /// Invoked when a key is pressed, the argument is a <Link type="KeyEvent" /> struct. Use this callback to
2310        /// handle keys before `TextInput` does. Return `accept` to indicate that you've handled the event, or return
2311        /// `reject` to let `TextInput` handle it.
2312        callback key-pressed(event: KeyEvent) -> EventResult;
2313        /// Invoked when a key is released, the argument is a <Link type="KeyEvent" /> struct. Use this callback to
2314        /// handle keys before `TextInput` does. Return `accept` to indicate that you've handled the event, or return
2315        /// `reject` to let `TextInput` handle it.
2316        callback key-released(event: KeyEvent) -> EventResult;
2317        in property <bool> enabled: true;
2318        /// When set to `true`, the text is always rendered as a single line, regardless of new line separators in the text.
2319        in property <bool> single-line: true;
2320        /// When set to `true`, text editing via keyboard and mouse is disabled but selecting text is still enabled as well as editing text programmatically.
2321        in property <bool> read-only: false;
2322        // Internal, undocumented property, only exposed for IME.
2323        out property <string> preedit-text;
2324        /// The design metrics of the font scaled to the font pixel size used by the element.
2325        out property <FontMetrics> font-metrics { BuiltinFunction.ItemFontMetrics }
2326
2327
2328        /// Selects the text between two UTF-8 offsets.
2329        /// `anchor` is the end of the selection that stays put and `focus` the end the cursor moves to,
2330        /// so `focus` may precede `anchor` to select backwards.
2331        /// Pass the same value for both to place the text cursor at that offset without selecting anything.
2332        function set-selection-offsets(anchor: int, focus: int) { BuiltinFunction.SetSelectionOffsets }
2333        /// Selects all text.
2334        function select-all() { }
2335        /// Clears the selection.
2336        function clear-selection() { }
2337        /// Copies the selected text to the clipboard and removes it from the editable area.
2338        function cut() { }
2339        /// Copies the selected text to the clipboard.
2340        function copy() { }
2341        /// Pastes the text content of the clipboard at the cursor position.
2342        function paste() { }
2343        /// Undoes the last text operation.
2344        function undo() { }
2345        /// Redoes the last undone text operation.
2346        function redo() { }
2347        //! ### focus()
2348        //! Call this function to focus the text input and make it receive future keyboard events.
2349        //!
2350        //! ### clear-focus()
2351        //! Call this function to remove keyboard focus from this `TextInput` if it currently has the focus. See also <Link type="FocusHandling" />.
2352    } }
2353
2354    element! {
2355        /// The `TextInput` is a lower-level item that shows text and allows entering text.
2356        /// You should probably not use this directly, but instead use the <Link type="LineEdit" /> or <Link type="TextEdit" /> component.
2357        ///
2358        /// When not part of a layout, its width and height defaults to 100% of the parent element.
2359        ///
2360        /// The `TextInput` does not scroll automatically when the cursor is outside of the visible area.
2361        /// This is the responsibility of the enclosing widget to ensure using the `cursor-position-changed` callback.
2362        ///
2363        /// ## Example
2364        ///
2365        /// ```slint playground
2366        /// export component Example inherits Window {
2367        ///     width: 270px;
2368        ///     height: 40px;
2369        ///     Rectangle {
2370        ///         clip: true;
2371        ///
2372        ///         TextInput {
2373        ///             text: "Edit me";
2374        ///             width: max(parent.width, self.preferred-width);
2375        ///             vertical-alignment: center;
2376        ///
2377        ///             private property <length> margin: 1rem;
2378        ///             cursor-position-changed(cursor-position) => {
2379        ///                 if cursor-position.x + self.x < margin {
2380        ///                     self.x = - cursor-position.x + margin;
2381        ///                 } else if cursor-position.x + self.x > parent.width - margin - self.text-cursor-width {
2382        ///                     self.x = parent.width - cursor-position.x - margin - self.text-cursor-width;
2383        ///                 }
2384        ///             }
2385        ///         }
2386        ///     }
2387        /// }
2388        /// ```
2389        ///
2390        /// \footer
2391        /// ## Accessibility
2392        ///
2393        /// By default, `TextInput` elements have the following accessibility properties set:
2394        ///
2395        ///  - `accessible-role: text-input;`
2396        ///  - `accessible-value: text;`
2397        ///  - `accessible-enabled: enabled;`
2398        ///  - `accessible-read-only: read-only; `
2399        /// \group:keyboard-input
2400        @accepts_focus @expands_to_parent_geometry
2401        TextInput: TextInput
2402    }
2403
2404    item! { Clip {
2405        in property <length> border-top-left-radius;
2406        in property <length> border-top-right-radius;
2407        in property <length> border-bottom-left-radius;
2408        in property <length> border-bottom-right-radius;
2409        in property <length> border-width;
2410        in property <bool> clip;
2411        in property <bool> is-visibility-clip;
2412    } }
2413
2414    element! {
2415        @is_internal @expands_to_parent_geometry
2416        Clip: Clip
2417    }
2418
2419    item! { Opacity {
2420        in property <float> opacity: 1;
2421    } }
2422
2423    element! {
2424        @is_internal @expands_to_parent_geometry
2425        Opacity: Opacity
2426    }
2427
2428    item! { Layer: Empty {
2429        in property <bool> cache-rendering-hint;
2430    } }
2431
2432    element! {
2433        @is_internal @expands_to_parent_geometry
2434        Layer: Layer
2435    }
2436
2437    element! {
2438        @is_non_item_type
2439        Row
2440    }
2441
2442    element! {
2443        /// `GridLayout` places elements on a grid.
2444        ///
2445        /// `GridLayout` covers its entire surface with cells. Cells are not aligned.
2446        /// The elements constituting the cells will be stretched inside their allocated
2447        /// space, unless their size constraints&mdash;like, e.g., `min-height` or
2448        /// `max-width`&mdash;work against this.
2449        ///
2450        ///
2451        /// ```slint playground imageAlt="gridlayout example" width="200" height="100"
2452        /// // This example uses the `Row` element
2453        /// export component Foo inherits Window {
2454        ///     width: 200px;
2455        ///     height: 200px;
2456        ///     GridLayout {
2457        ///         spacing: 5px;
2458        ///         Row {
2459        ///             Rectangle { background: red; }
2460        ///             Rectangle { background: blue; }
2461        ///         }
2462        ///         Row {
2463        ///             Rectangle { background: yellow; }
2464        ///             Rectangle { background: green; }
2465        ///         }
2466        ///     }
2467        /// }
2468        /// ```
2469        ///
2470        ///
2471        /// ```slint playground imageAlt="gridlayout example2" width="200" height="100"
2472        /// // This example uses the `col` and `row` properties
2473        /// export component Foo inherits Window {
2474        ///     width: 200px;
2475        ///     height: 150px;
2476        ///     GridLayout {
2477        ///         Rectangle { background: red; }
2478        ///         Rectangle { background: blue; }
2479        ///         Rectangle { background: yellow; row: 1; }
2480        ///         Rectangle { background: green; }
2481        ///         Rectangle { background: black; col: 2; row: 0; }
2482        ///     }
2483        /// }
2484        /// ```
2485        ///
2486        /// \footer
2487        /// ## Cell elements
2488        /// Cell elements inside a `GridLayout` obtain the following new properties. Any bindings to these properties must be compile-time constants:
2489        ///
2490        /// ### row
2491        /// <SlintProperty propName="row" typeName="int" defaultValue="auto">
2492        /// The index of the element's row within the grid. Setting this property resets the element's column to zero, unless explicitly set.
2493        /// </SlintProperty>
2494        ///
2495        /// ### col
2496        /// <SlintProperty propName="col" typeName="int" defaultValue="auto">
2497        /// The index of the element's column within the grid. Set this property to override the sequential column assignment (e.g., to skip a column).
2498        /// </SlintProperty>
2499        ///
2500        /// ### rowspan
2501        /// <SlintProperty propName="rowspan" typeName="int" defaultValue="1">
2502        /// The number of rows this element should span.
2503        /// </SlintProperty>
2504        ///
2505        /// ### colspan
2506        /// <SlintProperty propName="colspan" typeName="int" defaultValue="1">
2507        /// The number of columns this element should span.
2508        /// </SlintProperty>
2509        ///
2510        /// To implicitly sequentially assign row indices&mdash;just like with `col`&mdash;wrap cell elements in `Row` elements.
2511        ///
2512        /// The following example creates a 2-by-2 grid with `Row` elements, omitting one cell:
2513        ///
2514        /// ```slint
2515        /// import { Button } from "std-widgets.slint";
2516        /// export component Foo inherits Window {
2517        ///     width: 200px;
2518        ///     height: 100px;
2519        ///     GridLayout {
2520        ///         Row { // children implicitly on row 0
2521        ///             Button { col: 1; text: "Top Right"; } // implicit column after this would be 2
2522        ///         }
2523        ///         Row { // children implicitly on row 1
2524        ///             Button { text: "Bottom Left"; }  // implicitly in column 0...
2525        ///             Button { text: "Bottom Right"; } // ...and 1
2526        ///         }
2527        ///     }
2528        /// }
2529        /// ```
2530        ///
2531        /// The following example creates the same grid using the `row` property. Row indices must be taken care of manually:
2532        ///
2533        /// ```slint
2534        /// import { Button } from "std-widgets.slint";
2535        /// export component Foo inherits Window {
2536        ///     width: 200px;
2537        ///     height: 100px;
2538        ///     GridLayout {
2539        ///         Button { row: 0; col: 1; text: "Top Right"; } // `row: 0;` could even be left out at the start
2540        ///         Button { row: 1; text: "Bottom Left"; } // new row, implicitly resets column to 0
2541        ///         Button { text: "Bottom Right"; } // same row, sequentially assigned column 1
2542        ///     }
2543        /// }
2544        /// ```
2545        /// \group:layouts
2546        GridLayout {
2547            //! ## Spacing Properties
2548            /// The distance between the elements in the layout. This single value is applied to both horizontal and vertical spacing.
2549            in property <length> spacing;
2550            //! To target specific axis with different values use the following properties:
2551            ///
2552            in property <length> spacing-horizontal;
2553            ///
2554            in property <length> spacing-vertical;
2555            //! ## Padding Properties
2556            //!
2557            //! ### padding
2558            //! <SlintProperty propName="padding" typeName="length">
2559            //! The padding around the grid structure as a whole. This single value is applied to all sides.
2560            //! </SlintProperty>
2561            //!
2562            //! To target specific sides with different values use the following properties:
2563            //!
2564            //! ### padding-left
2565            //! <SlintProperty propName="padding-left" typeName="length"/>
2566            //!
2567            //! ### padding-right
2568            //! <SlintProperty propName="padding-right" typeName="length"/>
2569            //!
2570            //! ### padding-top
2571            //! <SlintProperty propName="padding-top" typeName="length"/>
2572            //!
2573            //! ### padding-bottom
2574            //! <SlintProperty propName="padding-bottom" typeName="length"/>
2575
2576            // Additional accepted child
2577            children: Row;
2578        }
2579    }
2580
2581    element! {
2582        /// ```slint
2583        /// export component Foo inherits Window {
2584        ///     width: 200px;
2585        ///     height: 100px;
2586        ///     VerticalLayout {
2587        ///         spacing: 5px;
2588        ///         Rectangle { background: red; width: 10px; }
2589        ///         Rectangle { background: blue; min-width: 10px; }
2590        ///         Rectangle { background: yellow; vertical-stretch: 1; }
2591        ///         Rectangle { background: green; vertical-stretch: 2; }
2592        ///     }
2593        /// }
2594        /// ```
2595        ///
2596        /// Places its children next to each other vertically.
2597        /// The size of elements can either be fixed with the `width` or `height` property, or if they aren't set
2598        /// they will be computed by the layout respecting the minimum and maximum sizes and the stretch factor.
2599        /// \footer
2600        /// ## Cell elements
2601        /// Cell elements inside a `VerticalLayout` obtain the following new properties:
2602        ///
2603        /// ### cross-axis-self-alignment
2604        /// <SlintProperty propName="cross-axis-self-alignment" typeName="enum" enumName="CrossAxisAlignment" defaultValue="auto">
2605        /// Overrides the container's `cross-axis-alignment` for this element.
2606        /// The default value `auto` uses the container's `cross-axis-alignment`.
2607        /// </SlintProperty>
2608        ///
2609        /// ### layout-order
2610        /// <SlintProperty propName="layout-order" typeName="int" defaultValue="0">
2611        /// Controls the visual order of the elements: they are laid out in ascending
2612        /// order value, and elements with the same value keep their declaration order.
2613        /// ```slint no-test
2614        /// VerticalLayout {
2615        ///     Rectangle { layout-order: 2; }
2616        ///     Rectangle { layout-order: 1; }  // appears first
2617        /// }
2618        /// ```
2619        /// Only the visual order changes: keyboard focus still moves in declaration order.
2620        /// </SlintProperty>
2621        /// \group:layouts
2622        VerticalLayout {
2623            //! ## Spacing Properties
2624            /// The distance between the elements in the layout.
2625            in property <length> spacing;
2626            //! ## Padding Properties
2627            //! ### padding
2628            //! <SlintProperty propName="padding" typeName="length">
2629            //! The padding within the layout as a whole. This single value is applied to all sides.
2630            //! </SlintProperty>
2631            //!
2632            //! To target specific sides with different values use the following properties:
2633            //! ### padding-left
2634            //! <SlintProperty propName="padding-left" typeName="length"/>
2635            //!
2636            //! ### padding-right
2637            //! <SlintProperty propName="padding-right" typeName="length"/>
2638            //!
2639            //! ### padding-top
2640            //! <SlintProperty propName="padding-top" typeName="length"/>
2641            //!
2642            //! ### padding-bottom
2643            //! <SlintProperty propName="padding-bottom" typeName="length"/>
2644            //!
2645            //! ## Alignment Properties
2646            /// Set the alignment along the main (vertical) axis. Matches the CSS flex box.
2647            in property <LayoutAlignment> alignment;
2648            /// Set the alignment of items along the cross (horizontal) axis.
2649            /// The default is `stretch`, meaning each item fills the full width of the layout.
2650            /// The other values (`start`, `end`, `center`) size each
2651            /// item to its preferred width, clamped to its min/max, and position it at the
2652            /// left, right, or center of the layout's content box.
2653            ///
2654            /// ```slint
2655            /// export component Example inherits Window {
2656            ///     width: 200px;
2657            ///     height: 100px;
2658            ///     VerticalLayout {
2659            ///         cross-axis-alignment: end;
2660            ///         Rectangle { background: red; preferred-width: 30px; preferred-height: 20px; }
2661            ///         Rectangle { background: blue; preferred-width: 60px; preferred-height: 20px; }
2662            ///         Rectangle { background: green; preferred-width: 90px; preferred-height: 20px; }
2663            ///     }
2664            /// }
2665            /// ```
2666            in property <CrossAxisAlignment> cross-axis-alignment;
2667        }
2668    }
2669
2670    element! {
2671        /// ```slint
2672        /// export component Foo inherits Window {
2673        ///     width: 200px;
2674        ///     height: 100px;
2675        ///     HorizontalLayout {
2676        ///         spacing: 5px;
2677        ///         Rectangle { background: red; width: 10px; }
2678        ///         Rectangle { background: blue; min-width: 10px; }
2679        ///         Rectangle { background: yellow; horizontal-stretch: 1; }
2680        ///         Rectangle { background: green; horizontal-stretch: 2; }
2681        ///     }
2682        /// }
2683        /// ```
2684        ///
2685        /// Places its children next to each other horizontally.
2686        /// The size of elements can either be fixed with the `width` or `height` property, or if they aren't set
2687        /// they will be computed by the layout respecting the minimum and maximum sizes and the stretch factor.
2688        /// \footer
2689        /// ## Cell elements
2690        /// Cell elements inside a `HorizontalLayout` obtain the following new properties:
2691        ///
2692        /// ### cross-axis-self-alignment
2693        /// <SlintProperty propName="cross-axis-self-alignment" typeName="enum" enumName="CrossAxisAlignment" defaultValue="auto">
2694        /// Overrides the container's `cross-axis-alignment` for this element.
2695        /// The default value `auto` uses the container's `cross-axis-alignment`.
2696        /// </SlintProperty>
2697        ///
2698        /// ### layout-order
2699        /// <SlintProperty propName="layout-order" typeName="int" defaultValue="0">
2700        /// Controls the visual order of the elements: they are laid out in ascending
2701        /// order value, and elements with the same value keep their declaration order.
2702        /// ```slint no-test
2703        /// HorizontalLayout {
2704        ///     Rectangle { layout-order: 2; }
2705        ///     Rectangle { layout-order: 1; }  // appears first
2706        /// }
2707        /// ```
2708        /// Only the visual order changes: keyboard focus still moves in declaration order.
2709        /// </SlintProperty>
2710        /// \group:layouts
2711        HorizontalLayout {
2712            //! ## Spacing Properties
2713            /// The distance between the elements in the layout.
2714            in property <length> spacing;
2715            //! ## Padding Properties
2716            //!
2717            //! ### padding
2718            //! <SlintProperty propName="padding" typeName="length">
2719            //! The padding within the layout as a whole. This single value is applied to all sides.
2720            //! </SlintProperty>
2721            //!
2722            //! To target specific sides with different values use the following properties:
2723            //!
2724            //! ### padding-left
2725            //! <SlintProperty propName="padding-left" typeName="length"/>
2726            //!
2727            //! ### padding-right
2728            //! <SlintProperty propName="padding-right" typeName="length"/>
2729            //!
2730            //! ### padding-top
2731            //! <SlintProperty propName="padding-top" typeName="length"/>
2732            //!
2733            //! ### padding-bottom
2734            //! <SlintProperty propName="padding-bottom" typeName="length"/>
2735            //!
2736            //! ## Alignment Properties
2737            /// Set the alignment along the main (horizontal) axis. Matches the CSS flex box.
2738            in property <LayoutAlignment> alignment;
2739            /// Set the alignment of items along the cross (vertical) axis.
2740            /// The default is `stretch`, meaning each item fills the full height of the layout.
2741            /// The other values (`start`, `end`, `center`) size each
2742            /// item to its preferred height, clamped to its min/max, and position it at the
2743            /// top, bottom, or center of the layout's content box.
2744            ///
2745            /// ```slint
2746            /// export component Example inherits Window {
2747            ///     width: 200px;
2748            ///     height: 100px;
2749            ///     HorizontalLayout {
2750            ///         cross-axis-alignment: center;
2751            ///         Rectangle { background: red; preferred-width: 30px; preferred-height: 20px; }
2752            ///         Rectangle { background: blue; preferred-width: 30px; preferred-height: 40px; }
2753            ///         Rectangle { background: green; preferred-width: 30px; preferred-height: 60px; }
2754            ///     }
2755            /// }
2756            /// ```
2757            in property <CrossAxisAlignment> cross-axis-alignment;
2758        }
2759    }
2760
2761    element! {
2762        /// `FlexboxLayout` is a flexible box layout that arranges its children in rows or columns with automatic wrapping.
2763        /// It implements a CSS Flexbox-like layout model suitable for creating flexible, responsive UIs.
2764        ///
2765        /// Use `FlexboxLayout` when the items should wrap: items that don't fit continue on the next line.
2766        /// That's why `flex-wrap` defaults to `wrap`, unlike CSS.
2767        /// For a single row or column, use the simpler and faster
2768        /// <Link type="HorizontalLayout" /> or <Link type="VerticalLayout" /> instead,
2769        /// unless you need a `flex-direction` that changes at runtime,
2770        /// or the reversed directions (`row-reverse` / `column-reverse`).
2771        ///
2772        ///
2773        /// ```slint playground imageAlt="flexboxlayout example with row direction" width="300" height="150"
2774        /// // This example demonstrates FlexboxLayout with row direction (default)
2775        /// export component Foo inherits Window {
2776        ///     width: 300px;
2777        ///     height: 150px;
2778        ///     FlexboxLayout {
2779        ///         spacing: 8px;
2780        ///         padding: 8px;
2781        ///         flex-direction: row;
2782        ///         Rectangle { background: red; width: 60px; height: 50px; }
2783        ///         Rectangle { background: blue; width: 60px; height: 50px; }
2784        ///         Rectangle { background: yellow; width: 60px; height: 50px; }
2785        ///         Rectangle { background: green; width: 60px; height: 50px; }
2786        ///         Rectangle { background: purple; width: 60px; height: 50px; }
2787        ///     }
2788        /// }
2789        /// ```
2790        ///
2791        ///
2792        /// ```slint playground imageAlt="flexboxlayout example with column direction" width="200" height="300"
2793        /// // This example demonstrates FlexboxLayout with column direction
2794        /// export component Foo inherits Window {
2795        ///     width: 200px;
2796        ///     height: 300px;
2797        ///     FlexboxLayout {
2798        ///         spacing: 8px;
2799        ///         padding: 8px;
2800        ///         flex-direction: column;
2801        ///         Rectangle { background: red; width: 50px; height: 60px; }
2802        ///         Rectangle { background: blue; width: 50px; height: 60px; }
2803        ///         Rectangle { background: yellow; width: 50px; height: 60px; }
2804        ///         Rectangle { background: green; width: 50px; height: 60px; }
2805        ///         Rectangle { background: purple; width: 50px; height: 60px; }
2806        ///     }
2807        /// }
2808        /// ```
2809        ///
2810        /// ## Overview
2811        ///
2812        /// In row direction, items are placed from left to right. When the available width is exceeded, items automatically wrap to the next row. In column direction, items are placed from top to bottom and wrap to the next column when the available height is exceeded.
2813        ///
2814        /// A wrapping column direction container reports the width of all its columns
2815        /// only when its `height` is set to a plain length, such as `height: 200px`.
2816        /// `phx` and `rem` do not count, since they depend on the window's scale factor
2817        /// and the default font size, which are only known while running.
2818        /// Set it on the container, on a component it inherits from, or where the container is used.
2819        /// A height a parent layout assigns, a percentage, and an expression all report
2820        /// the width of a single column instead,
2821        /// as for a CSS column flex container with an automatic height.
2822        /// A height on the root of a component used elsewhere does not count for the elements inside it,
2823        /// since each use may override it: set the height on the container instead.
2824        /// A `wrap` column container never wraps into columns wider than its width:
2825        /// the content overflows downward instead, like a wrapping `Text` given too little height.
2826        /// A `wrap-reverse` one still wraps, since its lines are anchored at the opposite edge.
2827        /// To wrap without setting a height, give the container more width,
2828        /// with `horizontal-stretch` or a `min-width`: it wraps into whatever width it gets.
2829        ///
2830        /// \footer
2831        /// ## Cell elements
2832        /// Cell elements inside a `FlexboxLayout` obtain the following new properties:
2833        ///
2834        /// ### cross-axis-self-alignment
2835        /// <SlintProperty propName="cross-axis-self-alignment" typeName="enum" enumName="CrossAxisAlignment" defaultValue="auto">
2836        /// Overrides the container's `cross-axis-alignment` for this element. CSS Flexbox calls this "align-self".
2837        /// The default value `auto` uses the container's `cross-axis-alignment`.
2838        /// </SlintProperty>
2839        ///
2840        /// ### layout-order
2841        /// <SlintProperty propName="layout-order" typeName="int" defaultValue="0">
2842        /// Controls the visual order of the items, like the CSS `order` property:
2843        /// items are laid out in ascending order value, and items with the same value keep
2844        /// their declaration order.
2845        /// ```slint no-test
2846        /// FlexboxLayout {
2847        ///     Rectangle { layout-order: 2; }
2848        ///     Rectangle { layout-order: 1; }  // appears first
2849        /// }
2850        /// ```
2851        /// Only the visual order changes: keyboard focus still moves in declaration order.
2852        /// </SlintProperty>
2853        ///
2854        /// ## CSS Mapping
2855        ///
2856        /// The container properties map to CSS Flexbox as follows:
2857        ///
2858        /// | CSS               | Slint                                                     |
2859        /// | ----------------- | --------------------------------------------------------- |
2860        /// | `flex-direction`  | `flex-direction`                                          |
2861        /// | `flex-wrap`       | `flex-wrap`, but the default is `wrap` (CSS: `nowrap`)    |
2862        /// | `justify-content` | `alignment`                                               |
2863        /// | `align-items`     | `cross-axis-alignment`                                    |
2864        /// | `align-content`   | `cross-axis-line-alignment`                               |
2865        /// | `gap`             | `spacing`                                                 |
2866        /// | `column-gap`      | `spacing-horizontal`                                      |
2867        /// | `row-gap`         | `spacing-vertical`                                        |
2868        /// | `padding`         | `padding`, `padding-left` / `-right` / `-top` / `-bottom` |
2869        ///
2870        /// The CSS per-item flexbox properties are expressed with the properties the
2871        /// other layouts already use:
2872        ///
2873        /// | CSS           | Slint                                                          |
2874        /// | ------------- | -------------------------------------------------------------- |
2875        /// | `flex-grow`   | `alignment: stretch` on the container, weighted per item by `horizontal-stretch` / `vertical-stretch`; `max-width` / `max-height` caps growing (space a capped item cannot take stays free) |
2876        /// | `flex-shrink` | nothing to opt into: every item shrinks, in proportion to its preferred size; `min-width` / `min-height` refuses shrinking |
2877        /// | `flex-basis`  | `preferred-width` (row) / `preferred-height` (column)          |
2878        /// | `align-self`  | `cross-axis-self-alignment`                                    |
2879        ///
2880        /// ## Layout Behavior
2881        ///
2882        /// The layouting algorithm for FlexboxLayout is entirely implemented by <a href="https://github.com/DioxusLabs/taffy">taffy</a>
2883        ///
2884        /// You can learn more about the CSS Flexbox specification from
2885        /// - <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Flexible_box_layout/Basic_concepts">the Mozilla developer website</a>
2886        /// - <a href="https://css-tricks.com/snippets/css/a-guide-to-flexbox/">A Complete Guide To Flexbox by CSS Tricks</a>. This is detailed guide with illustrations and comprehensive written explanation of the different Flexbox properties and how they work.
2887        ///
2888        /// \group:layouts
2889        FlexboxLayout {
2890            //! ## Spacing Properties
2891            /// The distance between the elements in the layout. CSS Flexbox usually calls this "gap", but "spacing" is used in Slint for consistency with other layout types.
2892            /// This single value is applied as both horizontal and vertical spacing between items.
2893            in property <length> spacing;
2894            //! To target specific directions with different values use the following properties:
2895            /// The horizontal distance between items in the layout. CSS Flexbox calls this "column-gap".
2896            in property <length> spacing-horizontal;
2897            /// The vertical distance between items in the layout. CSS Flexbox calls this "row-gap".
2898            in property <length> spacing-vertical;
2899            //! ## Padding Properties
2900            //!
2901            //! ### padding
2902            //! <SlintProperty propName="padding" typeName="length">
2903            //! The padding around the layout as a whole. This single value is applied to all sides.
2904            //! </SlintProperty>
2905            //!
2906            //! To target specific sides with different values use the following properties:
2907            //! ### padding-left
2908            //! <SlintProperty propName="padding-left" typeName="length"/>
2909            //!
2910            //! ### padding-right
2911            //! <SlintProperty propName="padding-right" typeName="length"/>
2912            //!
2913            //! ### padding-top
2914            //! <SlintProperty propName="padding-top" typeName="length"/>
2915            //!
2916            //! ### padding-bottom
2917            //! <SlintProperty propName="padding-bottom" typeName="length"/>
2918            //!
2919            //! ## Alignment Properties
2920            /// Set the alignment of items along the main axis. CSS Flexbox calls this "justify-content".
2921            /// With `stretch`, items grow along the main axis to fill each line,
2922            /// weighted by their `horizontal-stretch` (row) or `vertical-stretch` (column) factor.
2923            /// When every factor is 0, the free space is split evenly.
2924            /// Use `max-width`/`max-height` to cap an item's growth;
2925            /// space a capped item cannot take stays free at the end of the line.
2926            /// CSS Flexbox expresses this per item with `flex-grow` instead.
2927            in property <LayoutAlignment> alignment: LayoutAlignment.start;  // CSS default is flex-start
2928            //! ## Direction Properties
2929            /// The primary direction in which items are placed. Set to `row` to place items horizontally left-to-right (default), or `column` to place items vertically top-to-bottom.
2930            /// It also supports `row-reverse` and `column-reverse` which invert the flow: `row-reverse` places items right-to-left (starting at the right edge), and `column-reverse` places items bottom-to-top (starting at the bottom edge).
2931            in property <FlexboxLayoutDirection> flex-direction;
2932            /// Set the distribution of flex lines along the cross axis. CSS Flexbox calls this "align-content";
2933            /// the name here pairs with `cross-axis-alignment`, which aligns the items within one line.
2934            /// The default value is `stretch`.
2935            in property <LayoutAlignment> cross-axis-line-alignment;
2936            /// Set the alignment of individual items along the cross axis within each flex line.
2937            /// CSS Flexbox calls this "align-items". The default value is `stretch`.
2938            in property <CrossAxisAlignment> cross-axis-alignment;
2939            /// Controls whether flex items wrap onto multiple lines when they don't fit in the container.
2940            /// The default value is `wrap`, unlike CSS where it is `nowrap`.
2941            in property <FlexboxLayoutWrap> flex-wrap;
2942        }
2943    }
2944
2945    element! {
2946        /// The `MoveTo` sub-element closes the current sub-path, if present, and moves the current point
2947        /// to the location specified by the `x` and `y` properties. Subsequent elements such as `LineTo`
2948        /// will use this new position as their starting point, therefore this starts a new sub-path.
2949        @is_non_item_type @builtin_struct(PathMoveTo)
2950        MoveTo {
2951            /// The x position of the new current point.
2952            in property <float> x;
2953            /// The y position of the new current point.
2954            in property <float> y;
2955        }
2956    }
2957
2958    element! {
2959        /// The `LineTo` sub-element describes a line from the path's current position to the
2960        /// location specified by the `x` and `y` properties.
2961        @is_non_item_type @builtin_struct(PathLineTo)
2962        LineTo {
2963            /// The target x position of the line.
2964            in property <float> x;
2965            /// The target y position of the line.
2966            in property <float> y;
2967        }
2968    }
2969
2970    element! {
2971        /// The `ArcTo` sub-element describes the portion of an ellipse. The arc is drawn from the path's
2972        /// current position to the location specified by the `x` and `y` properties. The remaining properties
2973        /// are modelled after the SVG specification and allow tuning visual features such as the direction
2974        /// or angle.
2975        @is_non_item_type @builtin_struct(PathArcTo)
2976        ArcTo {
2977            /// Out of the two arcs of a closed ellipse, this flag selects that the larger arc is to be rendered. If the property is `false`, the shorter arc is rendered instead.
2978            in property <bool> large-arc;
2979            /// The x-radius of the ellipse.
2980            in property <float> radius-x;
2981            /// The y-radius of the ellipse.
2982            in property <float> radius-y;
2983            /// If the property is `true`, the arc will be drawn as a clockwise turning arc; anti-clockwise otherwise.
2984            in property <bool> sweep;
2985            /// The x-axis of the ellipse will be rotated by the value of this properties, specified in as angle in degrees from 0 to 360.
2986            in property <float> x-rotation;
2987            /// The target x position of the line.
2988            in property <float> x;
2989            /// The target y position of the line.
2990            in property <float> y;
2991        }
2992    }
2993
2994    element! {
2995        /// The `CubicTo` sub-element describes a smooth Bézier from the path's current position to the
2996        /// location specified by the `x` and `y` properties, using two control points specified by their
2997        /// respective properties.
2998        @is_non_item_type @builtin_struct(PathCubicTo)
2999        CubicTo {
3000            /// The x coordinate of the curve's first control point.
3001            in property <float> control-1-x;
3002            /// The y coordinate of the curve's first control point.
3003            in property <float> control-1-y;
3004            /// The x coordinate of the curve's second control point.
3005            in property <float> control-2-x;
3006            /// The y coordinate of the curve's second control point.
3007            in property <float> control-2-y;
3008            /// The target x position of the curve.
3009            in property <float> x;
3010            /// The target y position of the curve.
3011            in property <float> y;
3012        }
3013    }
3014
3015    element! {
3016        /// The QuadraticTo sub-element describes a smooth Bézier from the path's current position to the
3017        /// location specified by the `x` and `y` properties, using the control points specified by the
3018        /// `control-x` and `control-y` properties.
3019        @is_non_item_type @builtin_struct(PathQuadraticTo)
3020        QuadraticTo {
3021            /// The x coordinate of the curve's control point.
3022            in property <float> control-x;
3023            /// The y coordinate of the curve's control point.
3024            in property <float> control-y;
3025            /// The target x position of the curve.
3026            in property <float> x;
3027            /// The target y position of the curve.
3028            in property <float> y;
3029        }
3030    }
3031
3032    element! {
3033        /// The `Close` element closes the current sub-path and draws a straight line from the current
3034        /// position to the beginning of the path.
3035        @is_non_item_type @builtin_struct(PathClose)
3036        Close
3037    }
3038
3039    item! { Path {
3040        /// The color for filling the shape of the path.
3041        in property <brush> fill;
3042        /// The fill rule to use for the path.
3043        /// \default nonzero
3044        in property <FillRule> fill-rule;
3045        /// The color for drawing the outline of the path.
3046        in property <brush> stroke;
3047        /// The width of the outline.
3048        in property <length> stroke-width;
3049        /// The appearance of the ends of the path's outline.
3050        /// \default butt
3051        in property <LineCap> stroke-line-cap;
3052        /// The appearance of the joins between segments of stroked paths.
3053        /// \default miter
3054        in property <LineJoin> stroke-line-join;
3055        /// The limit on the ratio of the miter length to the stroke width when `stroke-line-join` is set to `miter`.
3056        /// When the limit is exceeded, the join is rendered as a bevel instead.
3057        in property <float> stroke-miter-limit: 4; // SVG default is 4
3058        //! ### width
3059        //! <SlintProperty propName="width" typeName="length">
3060        //! If non-zero, the path will be scaled to fit into the specified width.
3061        //! </SlintProperty>
3062        //!
3063        //! ### height
3064        //! <SlintProperty propName="height" typeName="length">
3065        //! If non-zero, the path will be scaled to fit into the specified height.
3066        //! </SlintProperty>
3067        //!
3068
3069        @fake in property <string> commands;
3070        /// Defines how the path's view box is scaled to fit the element's width and height.
3071        /// If no view box is defined, the implicit bounding rectangle is used.
3072        /// \default contain
3073        in property <ImageFit> fit: ImageFit.contain;
3074        /// By default, when a path has a view box defined and the elements render
3075        /// outside of it, they are still rendered. When this property is set to `true`, then rendering will be
3076        /// clipped at the boundaries of the view box.
3077        /// \default false
3078        in property <bool> clip;
3079        ///  By default, the fill and stroke of a path is rendered with anti-aliasing, for best quality. Some GPUs
3080        ///  have performance issues when rendering with anti-aliasing and animation. Setting the value to `false`
3081        ///  might improve the frame-rate at the expense of a smoother looking path.
3082        /// \default true
3083        in property <bool> anti-alias: true;
3084        //! ## Viewbox Properties
3085        //!
3086        //! These four properties allow defining the position and size of the viewport of the path in path coordinates.
3087        //!
3088        //! If the `viewbox-width` or `viewbox-height` is less or equal than zero, the viewbox properties are
3089        //! ignored and instead the bounding rectangle of all path elements is used to define the view port.
3090        ///
3091        in property <float> viewbox-x;
3092        ///
3093        in property <float> viewbox-y;
3094        ///
3095        in property <float> viewbox-width;
3096        ///
3097        in property <float> viewbox-height;
3098        /// Returns a point at the given percent along the path in the Path element's coordinate space.
3099        /// Returns (0, 0) if the path is empty.
3100        ///
3101        /// If a `t` outside the bounds of 0 and 1 is passed, it will be converted to its decimal fraction.
3102        /// Ex: 1.5 -> 0.5 and 2.0 -> 1.0. This allows for N iterations of a loop
3103        /// by animating t from 0 to N. If `t` is animated from N to 0, it will loop N times backwards.
3104        @pure function point-at(t: float) -> Point { BuiltinFunction.PathPointAt }
3105        /// Returns the angle (in degrees) between the x-axis and the path's tangent vector at the given `t`.
3106        /// The tangent points in the direction the path was defined, so this reflects the path's shape and not
3107        /// the object's current direction of travel. Returns 0 if the path is empty.
3108        /// If a `t` outside the bounds of 0 and 1 is passed, the decimal fraction will be passed.
3109        @pure function angle-at(t: float) -> angle { BuiltinFunction.PathAngleAt }
3110        //!
3111        //! ## Path Using SVG Commands
3112        //!
3113        //! SVG is a popular file format for defining scalable graphics, which are often composed of paths. In SVG
3114        //! paths are composed using [commands](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#path_commands),
3115        //! which in turn are written in a string. In `.slint` the path commands are provided to the `commands`
3116        //! property. The following example renders a shape consists of an arc and a rectangle, composed of `line-to`,
3117        //! `move-to` and `arc` commands:
3118        //!
3119        //! ```slint
3120        //! export component Example inherits Path {
3121        //!     width: 100px;
3122        //!     height: 100px;
3123        //!     commands: "M 0 0 L 0 100 A 1 1 0 0 0 100 100 L 100 0 Z";
3124        //!     stroke: red;
3125        //!     stroke-width: 1px;
3126        //! }
3127        //! ```
3128        //!
3129        //! The commands are provided in a property:
3130        //!
3131        //! ### Commands
3132        //! <SlintProperty propName="commands" typeName="string">
3133        //! A string providing the commands according to the SVG path specification.
3134        //! This property can only be set in a binding and cannot be accessed in an expression.
3135        //! </SlintProperty>
3136        //!
3137        //! ## Path Using SVG Path Elements
3138        //!
3139        //! The shape of the path can also be described using elements that resemble the SVG path commands but use the
3140        //! `.slint` markup syntax. The earlier example using SVG commands can also be written like that:
3141        //!
3142        //! ```slint
3143        //! export component Example inherits Path {
3144        //!     width: 100px;
3145        //!     height: 100px;
3146        //!     stroke: blue;
3147        //!     stroke-width: 1px;
3148        //!
3149        //!     MoveTo {
3150        //!         x: 0;
3151        //!         y: 0;
3152        //!     }
3153        //!     LineTo {
3154        //!         x: 0;
3155        //!         y: 100;
3156        //!     }
3157        //!     ArcTo {
3158        //!         radius-x: 1;
3159        //!         radius-y: 1;
3160        //!         x: 100;
3161        //!         y: 100;
3162        //!     }
3163        //!     LineTo {
3164        //!         x: 100;
3165        //!         y: 0;
3166        //!     }
3167        //!     Close {
3168        //!     }
3169        //! }
3170        //! ```
3171        //!
3172        //! Note how the coordinates of the path elements don't use units - they operate within the imaginary
3173        //! coordinate system of the scalable path.
3174
3175
3176
3177
3178
3179
3180
3181    } }
3182
3183    element! {
3184        /// The `Path` element allows rendering a generic shape, composed of different geometric commands. A path
3185        /// shape can be filled and outlined.
3186        ///
3187        /// When not part of a layout, its width or height defaults to 100% of the parent element when not specified.
3188        ///
3189        /// A path can be defined in two different ways:
3190        ///
3191        /// -   Using SVG path commands as a string
3192        /// -   Using path command elements in `.slint` markup.
3193        ///
3194        /// The coordinates used in the geometric commands are within the imaginary coordinate system of the path.
3195        /// When rendering on the screen, the shape is drawn relative to the `x` and `y` properties. If the `width`
3196        /// and `height` properties are non-zero, then the entire shape is fit into these bounds - by scaling
3197        /// accordingly.
3198        /// \group:elements
3199        @disallow_global_types_as_child_elements @expands_to_parent_geometry
3200        Path: Path {
3201            children: MoveTo, LineTo, ArcTo, CubicTo, QuadraticTo, Close;
3202        }
3203    }
3204
3205    element! {
3206        Tab {
3207            in property <string> title;
3208        }
3209    }
3210
3211    element! {
3212        // Note: not a native class, handled in the lower_tabs pass
3213        @is_internal @disallow_global_types_as_child_elements @expands_to_parent_geometry
3214        TabWidget {
3215            in-out property <int> current-index;
3216
3217            @constexpr in property <Orientation> orientation;
3218
3219
3220            children: Tab;
3221        }
3222    }
3223
3224    element! {
3225        RadioButton {
3226            in property <string> text;
3227            in property <bool> enabled: true;
3228            in-out property <bool> checked;
3229            callback toggled;
3230        }
3231    }
3232
3233    element! {
3234        // Note: not a native class, handled in the lower_radiogroup pass
3235        @is_internal @disallow_global_types_as_child_elements
3236        RadioGroup {
3237            in property <string> title;
3238            in property <bool> enabled: true;
3239            in property <Orientation> orientation;
3240            out property <string> current-value;
3241            out property <bool> has-focus;
3242            callback selected(value: string);
3243
3244
3245            children: RadioButton;
3246        }
3247    }
3248
3249    element! {
3250        /// ```slint playground
3251        /// export component Example inherits Window {
3252        ///     width: 100px;
3253        ///     height: 100px;
3254        ///
3255        ///     popup := PopupWindow {
3256        ///         Rectangle { height:100%; width: 100%; background: yellow; }
3257        ///         x: 20px; y: 20px; height: 50px; width: 50px;
3258        ///     }
3259        ///
3260        ///     TouchArea {
3261        ///         height:100%; width: 100%;
3262        ///         clicked => { popup.show(); }
3263        ///     }
3264        /// }
3265        /// ```
3266        ///
3267        /// Use this element to show a popup window like a tooltip or a popup menu.
3268        ///
3269        /// :::note{Note}
3270        /// It isn't allowed to access properties of elements within the popup from outside of the `PopupWindow`. See [#4438](https://github.com/slint-ui/slint/issues/4438).
3271        /// :::
3272        /// \group:window
3273        PopupWindow {
3274            //property <length> x;
3275            //property <length> y;
3276            in property <length> width;
3277            in property <length> height;
3278            /*property <length> anchor_x;
3279            in property <length> anchor-y;
3280            in property <length> anchor-height;
3281            in property <length> anchor-width;*/
3282
3283            @constexpr in property <bool> close-on-click;
3284            /// By default, a PopupWindow closes when the user clicks. Set this to false to prevent that behavior and close it manually using the `close()` function.
3285            /// \default close-on-click
3286
3287            @constexpr in property <PopupClosePolicy> close-policy;
3288            /// Use this read-only property to style the element that opened the popup, for example
3289            /// to rotate a ComboBox's arrow while the dropdown is open.
3290            /// `true` while the popup is shown on the screen, and `false` once it is closed, for example
3291            /// when dismissed by a click, by a selection, or by a programmatic `close()`.
3292            out property <bool> is-open;
3293            /// Show the popup on the screen.
3294            function show() { BuiltinFunction.ShowPopupWindow }
3295            /// Closes the popup. Use this if you set the `close-policy` property to `no-auto-close`.
3296            function close() { BuiltinFunction.ClosePopupWindow }
3297        }
3298    }
3299
3300    item! { TooltipArea: Empty {
3301        // Set when the mouse is over the parent's region while this area is expanded to fill it during lowering.
3302        out property <bool> has-hover;
3303        // Pointer x within this area during hover.
3304        out property <length> mouse-x;
3305        // Pointer y within this area during hover.
3306        out property <length> mouse-y;
3307        // Tooltip configuration folded from the user-facing Tooltip element during lowering.
3308        in property <styled-text> text;
3309        // Delay and offset are not user-facing in 1.17; the values used here are the
3310        // built-in defaults applied to the synthesized element on instantiation.
3311        in property <duration> delay: 500ms;
3312        in property <length> offset: 8px;
3313        callback show;
3314        callback hide;
3315    } }
3316
3317    element! {
3318        // Internal hover tracker used with `Tooltip` lowering (the compiler inserts `TooltipArea` so `Tooltip` can react to hover and pointer position).
3319        @is_internal @expands_to_parent_geometry
3320        TooltipArea: TooltipArea
3321    }
3322
3323    element! {
3324        /// ```slint playground
3325        /// import { Button } from "std-widgets.slint";
3326        ///
3327        /// export component Example inherits Window {
3328        ///     width: 280px;
3329        ///     height: 160px;
3330        ///
3331        ///     VerticalLayout {
3332        ///         alignment: center;
3333        ///
3334        ///         Button {
3335        ///             text: "Hover me";
3336        ///
3337        ///             Tooltip {
3338        ///                 text: @markdown("This is a tooltip");
3339        ///             }
3340        ///         }
3341        ///     }
3342        /// }
3343        /// ```
3344        ///
3345        /// Place a `Tooltip` inside any element to show helpful information when hovering over it.
3346        /// The tooltip appears after a short delay near the pointer and hides when the pointer leaves.
3347        ///
3348        /// Set the `text` property for a simple text tooltip,
3349        /// or add a child element instead for custom content.
3350        ///
3351        /// Each element can contain at most one `Tooltip`.
3352        ///
3353        /// \footer
3354        /// ## Custom Content
3355        ///
3356        /// For richer tooltips, omit `text` and provide your own layout inside a single child element.
3357        ///
3358        ///
3359        /// ```slint playground
3360        /// import { Button, VerticalBox, HorizontalBox } from "std-widgets.slint";
3361        ///
3362        /// export component Example inherits Window {
3363        ///     width: 320px;
3364        ///     height: 200px;
3365        ///
3366        ///     VerticalLayout {
3367        ///         alignment: center;
3368        ///
3369        ///         Button {
3370        ///             text: "Custom tooltip";
3371        ///
3372        ///             Tooltip {
3373        ///                 VerticalBox {
3374        ///                     padding: 10px;
3375        ///                     spacing: 6px;
3376        ///
3377        ///                     Text {
3378        ///                         text: "Quick Actions";
3379        ///                         font-weight: 700;
3380        ///                         color: #fff;
3381        ///                     }
3382        ///
3383        ///                     Text {
3384        ///                         text: "Open command palette and search settings.";
3385        ///                         color: #d1d5db;
3386        ///                         wrap: word-wrap;
3387        ///                     }
3388        ///
3389        ///                     HorizontalBox {
3390        ///                         spacing: 6px;
3391        ///
3392        ///                         Rectangle {
3393        ///                             border-radius: 4px;
3394        ///                             background: #374151;
3395        ///                             HorizontalBox {
3396        ///                                 padding: 4px;
3397        ///                                 Text { text: "Ctrl"; color: #fff; }
3398        ///                             }
3399        ///                         }
3400        ///
3401        ///                         Rectangle {
3402        ///                             border-radius: 4px;
3403        ///                             background: #374151;
3404        ///                             HorizontalBox {
3405        ///                                 padding: 4px;
3406        ///                                 Text { text: "K"; color: #fff; }
3407        ///                             }
3408        ///                         }
3409        ///                     }
3410        ///                 }
3411        ///             }
3412        ///         }
3413        ///     }
3414        /// }
3415        /// ```
3416        /// \group:window
3417        @is_non_item_type @can_be_declared_without_children_slot
3418        Tooltip: Empty {
3419            /// The text to display in the tooltip.
3420            /// Don't set this property when using custom content.
3421            in property <styled-text> text;
3422        }
3423    }
3424
3425    element! {
3426        /// :::note[Note]
3427        /// Timer is not an actual element visible in the tree, therefore it doesn't have the common properties such as `x`, `y`, `width`, `height`, etc. It also doesn't take room in a layout and cannot have any children or be inherited from.
3428        /// :::
3429        ///
3430        /// This example shows a timer that counts down from 10 to 0 every second:
3431        ///
3432        /// ```slint playground
3433        /// import { Button } from "std-widgets.slint";
3434        /// export component Example inherits Window {
3435        ///     property <int> value: 10;
3436        ///     timer := Timer {
3437        ///         interval: 1s;
3438        ///         running: true;
3439        ///         triggered() => {
3440        ///             value -= 1;
3441        ///             if (value == 0) {
3442        ///                 self.running = false;
3443        ///             }
3444        ///         }
3445        ///     }
3446        ///     HorizontalLayout {
3447        ///         Text { text: value; }
3448        ///         Button {
3449        ///             text: "Reset";
3450        ///             clicked() => { value = 10; timer.running = true; }
3451        ///         }
3452        ///     }
3453        /// }
3454        /// ```
3455        ///
3456        ///
3457        ///
3458        /// Use the Timer pseudo-element to schedule a callback at a given interval.
3459        /// The timer is only running when the `running` property is set to `true`. To stop or start the timer, set that property to `true` or `false`.
3460        /// It can be also set to a binding expression.
3461        /// When already running, the timer will be restarted if the `interval` property is changed.
3462        ///
3463        /// :::caution[Caution]
3464        /// By default the `Timer` is always running `running: true`. This can result in constant CPU usage and
3465        /// power usage so ensure that you set `running` to `false` when you don't want the timer to run.
3466        /// :::
3467        ///
3468        /// ```slint
3469        /// property <int> count: 0;
3470        /// Timer {
3471        ///     interval: 8s; // every 8 seconds the timer will activate (tick)
3472        ///     triggered() => { // The triggered callback activates every time the timer ticks
3473        ///         if count >= 5 {
3474        ///             self.running = false; // stop the timer after 5 ticks
3475        ///         }
3476        ///         count += 1;
3477        ///     }
3478        /// }
3479        /// ```
3480        @is_non_item_type @disallow_global_types_as_child_elements
3481        Timer {
3482            /// The interval between timer ticks. This property is mandatory.
3483            /// ```slint "interval: 250ms;"
3484            /// Timer {
3485            ///     property <int> count: 0;
3486            ///     interval: 250ms;
3487            ///     triggered() => {
3488            ///         debug("count is:", count);
3489            ///         count += 1;
3490            ///     }
3491            /// }
3492            /// ```
3493            in property <duration> interval;
3494            /// `true` if the timer is running.
3495            /// ```slint "running: false; // timer is not running"
3496            /// Timer {
3497            ///     property <int> count: 0;
3498            ///     interval: 250ms;
3499            ///     running: false; // timer is not running
3500            ///     triggered() => {
3501            ///         debug("count is:", count);
3502            ///     }
3503            /// }
3504            /// ```
3505            in property <bool> running: true;
3506            /// Invoked every time the timer ticks (every `interval`).
3507            /// ```slint {4-6}
3508            /// Timer {
3509            ///     property <int> count: 0;
3510            ///     interval: 250ms;
3511            ///     triggered() => {
3512            ///         debug("count is:", count);
3513            ///     }
3514            /// }
3515            /// ```
3516            callback triggered;
3517            /// Start the timer (equivalent to setting `running` to true).
3518            function start() { BuiltinFunction.StartTimer }
3519            /// Stop the timer (equivalent to setting `running` to false).
3520            function stop() { BuiltinFunction.StopTimer }
3521            /// Restarts the timer if it was previously started.
3522            function restart() { BuiltinFunction.RestartTimer }
3523        }
3524    }
3525
3526    element! {
3527        /// ```slint playground imageAlt="dialog example" width="200" height="100"
3528        /// import { StandardButton, Button } from "std-widgets.slint";
3529        /// export component Example inherits Dialog {
3530        ///     Text {
3531        ///       text: "This is a dialog box";
3532        ///     }
3533        ///     StandardButton { kind: ok; }
3534        ///     StandardButton { kind: cancel; }
3535        ///     Button {
3536        ///       text: "More Info";
3537        ///       dialog-button-role: action;
3538        ///     }
3539        /// }
3540        /// ```
3541        ///
3542        /// Dialog can be used in place of <Link type="Window"/>, but it has buttons that are automatically laid out.
3543        ///
3544        /// A Dialog should have one main element as child, that isn't a button.
3545        /// The dialog can have any number of `StandardButton` widgets or other buttons
3546        /// with the `dialog-button-role` property.
3547        /// The buttons will be placed in an order that depends on the target platform at run-time.
3548        ///
3549        /// The `kind` property of the `StandardButton`s and the `dialog-button-role` properties need to be set to a constant value, it can't be an arbitrary variable expression.
3550        /// There can't be several `StandardButton`s of the same kind.
3551        ///
3552        /// A callback `<kind>_clicked` is automatically added for each `StandardButton` which doesn't have an explicit
3553        /// callback handler, so it can be handled from the native code: For example if there is a button of kind `cancel`,
3554        /// a `cancel_clicked` callback will be added.
3555        /// Each of these automatically-generated callbacks is an alias for the `clicked` callback of the associated `StandardButton`.
3556        ///
3557        /// ## Properties
3558        ///
3559        /// Same as <Link type="Window"/>.
3560        ///
3561        /// ## Functions
3562        ///
3563        /// Same as <Link type="Window"/>.
3564        /// \group:window
3565        @skip_inherited
3566        Dialog: WindowItem
3567    }
3568
3569    element! {
3570        @is_non_item_type
3571        PropertyAnimation {
3572            in property <duration> delay;
3573            in property <duration> duration;
3574            in property <AnimationDirection> direction;
3575            in property <easing> easing;
3576            in property <float> iteration-count: 1.0;
3577            in property <bool> enabled: true;
3578        }
3579    }
3580
3581    element! {
3582        /// ```slint
3583        /// import { LineEdit } from "std-widgets.slint";
3584        ///
3585        /// component VKB {
3586        ///     Rectangle { background: yellow; }
3587        /// }
3588        ///
3589        /// export component Example inherits Window {
3590        ///     width: 200px;
3591        ///     height: 100px;
3592        ///     VerticalLayout {
3593        ///         LineEdit {}
3594        ///         FocusScope {}
3595        ///         if TextInputInterface.text-input-focused: VKB {}
3596        ///     }
3597        /// }
3598        /// ```
3599        ///
3600        /// \group:keyboard-input
3601        @is_global
3602        TextInputInterface {
3603            //! ## Properties
3604            //!
3605            //! The `TextInputInterface.text-input-focused` property can be used to find out if a `TextInput` element has the focus.
3606            //! If you're implementing your own virtual keyboard, this property is an indicator whether the virtual keyboard should be shown or hidden.
3607            /// True if an `TextInput` element has the focus; false otherwise.
3608            in property <bool> text-input-focused;
3609        }
3610    }
3611
3612    element! {
3613        /// The **Platform** namespace contains properties that help deal with platform specific differences.
3614        @is_global
3615        Platform {
3616            /// This property holds the type of the operating system detected at run-time.
3617            ///
3618            /// :::note{Note}
3619            /// When running in a web browser, the value of this property is computed at run-time by querying the web browser's navigator properties.
3620            /// :::
3621            ///
3622            /// :::note{Note}
3623            /// When Slint is ported to new operating systems in the future, new enum values will be added.
3624            /// :::
3625            out property <OperatingSystemType> os;
3626            /// `true` when the `.slint` file is being interpreted on its own, with nothing behind it, such as
3627            /// when previewed with `slint-viewer` or the editor's preview, and `false` when the user interface
3628            /// is driven by a host application: your business logic written in Rust, C++, JavaScript or Python.
3629            ///
3630            /// Use it to provide placeholder data and preview-only decorations that are removed from your
3631            /// compiled application. This property is a compile-time constant, so branches that depend on it
3632            /// are optimized away when the value is known to be `false` or `true`.
3633            //
3634            // ```slint playground
3635            // import { ListView, VerticalBox } from "std-widgets.slint";
3636            //
3637            // export struct Data {
3638            //     text: string,
3639            //     color: color,
3640            //     bg: color,
3641            // }
3642            // export component Example inherits Window {
3643            //     width: 150px;
3644            //     height: 150px;
3645            //     in property<[Data]> data: Platform.uses-mock-data ? [
3646            //                 { text: "Blue", color: #0000ff, bg: #eeeeee},
3647            //                 { text: "Red", color: #ff0000, bg: #eeeeee},
3648            //                 { text: "Green", color: #00ff00, bg: #eeeeee},
3649            //                 { text: "Yellow", color: #ffff00, bg: #222222 },
3650            //                 { text: "Black", color: #000000, bg: #eeeeee },
3651            //                 { text: "White", color: #ffffff, bg: #222222 },
3652            //                 { text: "Magenta", color: #ff00ff, bg: #eeeeee },
3653            //                 { text: "Cyan", color: #00ffff, bg: #222222 },
3654            //             ] : [];
3655            //
3656            //     VerticalBox {
3657            //         ListView {
3658            //             for data in root.data : Rectangle {
3659            //                 height: 30px;
3660            //                 background: data.bg;
3661            //                 width: parent.width;
3662            //                 Text {
3663            //                     x: 0;
3664            //                     text: data.text;
3665            //                     color: data.color;
3666            //                 }
3667            //             }
3668            //         }
3669            //     }
3670            // }
3671            // ```
3672            out property <bool> uses-mock-data;
3673            /// The name of the currently selected <Link type="StyleWidgets" label="widget style"/>. Some widget
3674            /// styles have dark and light variant suffixes, such as `fluent-light`. This property contains the
3675            /// style name without the suffix. Use <Link type="Palette" label="Palette"/>'s `color-scheme` to
3676            /// determine the currently used scheme.
3677            out property <string> style-name;
3678            /// The decimal separator used when converting between `float` and `string`.
3679            /// It defaults to the dot (`.`) and is determined by the locale.
3680            /// See the <Link type="translations" label="translations guide"/> for details.
3681            out property <string> decimal-separator;
3682            /// Opens the specified URL in an external browser. This function invokes the platform's URL opening mechanism.
3683            /// Returns `true` on success, or `false` if the platform doesn't support opening URLs or the operation failed.
3684            ///
3685            /// ```slint playground
3686            /// import { Button } from "std-widgets.slint";
3687            ///
3688            /// export component Example inherits Window {
3689            ///     Button {
3690            ///         text: "Open Slint Website";
3691            ///         clicked => {
3692            ///             Platform.open-url("https://slint.dev");
3693            ///         }
3694            ///     }
3695            /// }
3696            /// ```
3697            function open-url(url: string) -> bool { }
3698            /// Brings all application windows to the front of the screen.
3699            ///
3700            /// On macOS this invokes `[NSApp arrangeInFront:]`, which raises every application window
3701            /// to the top of the window stack. On other platforms this function is a no-op.
3702            ///
3703            /// This corresponds to the standard macOS **Window › Bring All to Front** menu item.
3704            function macos-bring-all-windows-to-front() { }
3705        }
3706    }
3707
3708    item! { NativeButton {
3709        in property <string> text;
3710        in property <image> icon;
3711        out property <bool> pressed;
3712        in property <bool> checkable;
3713        in-out property <bool> checked;
3714        out property <bool> has-focus;
3715        in property <bool> primary;
3716        in property <bool> colorize-icon;
3717        in property <length> icon-size;
3718        callback clicked;
3719        in property <bool> enabled: true;
3720        in property <StandardButtonKind> standard-button-kind;
3721        in property <bool> is-standard-button;
3722    } }
3723
3724    element! {
3725        @is_internal @accepts_focus
3726        NativeButton: NativeButton
3727    }
3728
3729    item! { NativeCheckBox {
3730        in property <bool> enabled: true;
3731        in property <string> text;
3732        in-out property <bool> checked;
3733        out property <bool> has-focus;
3734        callback toggled;
3735    } }
3736
3737    element! {
3738        @is_internal @accepts_focus
3739        NativeCheckBox: NativeCheckBox
3740    }
3741
3742    item! { NativeSpinBox {
3743        in property <bool> enabled: true;
3744        out property <bool> has-focus;
3745        in-out property <int> value;
3746        in property <int> minimum;
3747        in property <int> maximum: 100;
3748        in property <int> step-size: 1;
3749        in property <TextHorizontalAlignment> horizontal-alignment;
3750        in property <bool> read-only;
3751        callback edited(value: int);
3752    } }
3753
3754    element! {
3755        @is_internal @accepts_focus
3756        NativeSpinBox: NativeSpinBox
3757    }
3758
3759    item! { NativeSlider {
3760        in property <bool> enabled: true;
3761        out property <bool> has-focus;
3762        in-out property <float> value;
3763        in property <float> minimum;
3764        in property <float> maximum: 100;
3765        in property <float> step: 1;
3766        in property <Orientation> orientation: Orientation.horizontal;
3767        callback changed(value: float);
3768        callback released(value: float);
3769    } }
3770
3771    element! {
3772        @is_internal @accepts_focus
3773        NativeSlider: NativeSlider
3774    }
3775
3776    item! { NativeProgressIndicator {
3777        in property <bool> indeterminate;
3778        in property <float> progress;
3779    } }
3780
3781    element! {
3782        @is_internal
3783        NativeProgressIndicator: NativeProgressIndicator
3784    }
3785
3786    item! { NativeGroupBox {
3787        in property <bool> enabled: true;
3788        in property <string> title;
3789        out property <length> native-padding-left;
3790        out property <length> native-padding-right;
3791        out property <length> native-padding-top;
3792        out property <length> native-padding-bottom;
3793    } }
3794
3795    element! {
3796        @is_internal @expands_to_parent_geometry
3797        NativeGroupBox: NativeGroupBox
3798    }
3799
3800    item! { NativeLineEdit {
3801        out property <length> native-padding-left;
3802        out property <length> native-padding-right;
3803        out property <length> native-padding-top;
3804        out property <length> native-padding-bottom;
3805        out property <image> clear-icon;
3806        in property <bool> has-focus;
3807        in property <bool> enabled: true;
3808    } }
3809
3810    element! {
3811        @is_internal
3812        NativeLineEdit: NativeLineEdit
3813    }
3814
3815    item! { NativeScrollView {
3816        in property <length> horizontal-max;
3817        in property <length> horizontal-page-size;
3818        in property <length> horizontal-value;
3819        in property <length> vertical-max;
3820        in property <length> vertical-page-size;
3821        in-out property <length> vertical-value;
3822        out property <length> native-padding-left;
3823        out property <length> native-padding-right;
3824        out property <length> native-padding-top;
3825        out property <length> native-padding-bottom;
3826        in property <bool> has-focus;
3827        in property <ScrollBarPolicy> vertical-scrollbar-policy;
3828        in property <ScrollBarPolicy> horizontal-scrollbar-policy;
3829        in property <bool> enabled: true;
3830        callback scrolled;
3831    } }
3832
3833    element! {
3834        @is_internal @expands_to_parent_geometry
3835        NativeScrollView: NativeScrollView
3836    }
3837
3838    item! { NativeStandardListViewItem {
3839        in property <int> index;
3840        in property <StandardListViewItem> item;
3841        in-out property <bool> is-selected;
3842        in property <bool> has-hover;
3843        in property <bool> has-focus;
3844        in property <bool> pressed;
3845        in property <bool> combobox;
3846        in property <length> pressed-x;
3847        in property <length> pressed-y;
3848    } }
3849
3850    element! {
3851        @is_internal
3852        NativeStandardListViewItem: NativeStandardListViewItem
3853    }
3854
3855    item! { NativeTableHeaderSection {
3856        in property <int> index;
3857        in property <TableColumn> item;
3858        in property <bool> has-hover;
3859    } }
3860
3861    element! {
3862        @is_internal
3863        NativeTableHeaderSection: NativeTableHeaderSection
3864    }
3865
3866    item! { NativeComboBox {
3867        in-out property <string> current-value;
3868        in property <bool> enabled: true;
3869        in property <bool> has-focus;
3870    } }
3871
3872    element! {
3873        @is_internal
3874        NativeComboBox: NativeComboBox
3875    }
3876
3877    item! { NativeComboBoxPopup { } }
3878
3879    element! {
3880        @is_internal
3881        NativeComboBoxPopup: NativeComboBoxPopup
3882    }
3883
3884    item! { NativeTabWidget {
3885        in property <length> width;
3886        in property <length> height;
3887
3888        out property <length> content-x;
3889        out property <length> content-y;
3890        out property <length> content-height;
3891        out property <length> content-width;
3892        out property <length> tabbar-x;
3893        out property <length> tabbar-y;
3894        out property <length> tabbar-height;
3895        out property <length> tabbar-width;
3896        in property <length> tabbar-preferred-height;
3897        in property <length> tabbar-preferred-width;
3898        in property <length> content-min-height;
3899        in property <length> content-min-width;
3900
3901        in property <int> current-index;
3902        in property <int> current-focused;
3903        in property <Orientation> orientation: Orientation.horizontal;
3904    } }
3905
3906    element! {
3907        @is_internal @expands_to_parent_geometry
3908        NativeTabWidget: NativeTabWidget
3909    }
3910
3911    item! { NativeTab {
3912        in property <string> title;
3913        in property <image> icon;
3914        in property <bool> enabled: true;
3915        in-out property <int> current; // supposed to be a binding to the tab
3916        in property <int> tab-index;
3917        in property <int> current-focused;
3918        in property <int> num-tabs;
3919    } }
3920
3921    element! {
3922        @is_internal
3923        NativeTab: NativeTab
3924    }
3925
3926    item! { NativeStyleMetrics {
3927        out property <length> layout-spacing;
3928        out property <length> layout-padding;
3929        out property <length> text-cursor-width;
3930        out property <color> window-background;
3931        out property <color> default-text-color;
3932        out property <color> textedit-background;
3933        out property <color> textedit-text-color;
3934        out property <color> textedit-background-disabled;
3935        out property <color> textedit-text-color-disabled;
3936
3937        out property <bool> dark-color-scheme;
3938
3939        // specific to the Native one
3940        out property <color> placeholder-color;
3941        out property <color> placeholder-color-disabled;
3942
3943        // Tab Bar metrics:
3944        out property <LayoutAlignment> tab-bar-alignment;
3945    } }
3946
3947    element! {
3948        @is_internal @is_non_item_type @is_global
3949        NativeStyleMetrics: NativeStyleMetrics
3950    }
3951
3952    item! { NativePalette {
3953        out property <brush> background;
3954        out property <brush> foreground;
3955        out property <brush> alternate-background;
3956        out property <brush> alternate-foreground;
3957        out property <brush> control-background;
3958        out property <brush> control-foreground;
3959        out property <brush> accent-background;
3960        out property <brush> accent-foreground;
3961        out property <brush> selection-background;
3962        out property <brush> selection-foreground;
3963        out property <brush> border;
3964        in-out property <ColorScheme> color-scheme;
3965    } }
3966
3967    element! {
3968        @is_internal @is_non_item_type @is_global
3969        NativePalette: NativePalette
3970    }
3971
3972    item! { SystemTrayIcon {
3973        /// The icon shown in the system tray. The image is scaled by the platform to the size expected
3974        /// for tray icons. Use `@image-url(...)` to embed an icon asset, or bind to an `image` property
3975        /// fed from your code. The tray icon is only created once a non-empty image has been assigned.
3976        in property <image> icon;
3977        /// The hover text shown over the tray icon.
3978        /// Typically the application name or a short status message.
3979        in property <string> tooltip;
3980        /// Whether the tray icon is registered with the OS.
3981        /// Set it to `false` to hide the icon without dropping the component instance, and back to `true` to show it again.
3982        /// The `show()` and `hide()` methods on the language-binding side are convenience aliases that set this property.
3983        in property <bool> visible: true;
3984        /// A descriptive name for the tray entry, separate from the hover tooltip.
3985        /// Where it actually shows up depends on the platform:
3986        ///
3987        /// | Platform      | Where `title` appears                                                                            |
3988        /// | ------------- | ------------------------------------------------------------------------------------------------ |
3989        /// | Linux, \*BSD  | Used by accessibility tools and shown by some desktops when listing tray icons (e.g. an overflow menu). Set as the [StatusNotifierItem `Title`](https://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/StatusNotifierItem/) property. |
3990        /// | macOS         | The visible text label rendered next to the icon in the menu bar (think battery percent, clock). |
3991        /// | Windows       | Has no visible effect; the notification area renders only the icon.                              |
3992        in property <string> title;
3993        /// Invoked when the user left-clicks the tray icon itself, as opposed to picking an entry from its menu.
3994        /// Whether it's invoked at all depends on the platform:
3995        ///
3996        /// | Platform      | Click behavior                                                                        |
3997        /// | ------------- | ------------------------------------------------------------------------------------- |
3998        /// | Linux, \*BSD  | Invoked on a left-click of the icon. The exact gesture is decided by the desktop environment or shell extension hosting the tray. |
3999        /// | macOS         | Invoked on a left-click when no `Menu` is attached (or when an `if cond : Menu { ... }`'s condition is currently false). When a populated menu is attached, AppKit pops it open instead and `clicked` doesn't fire. |
4000        /// | Windows       | Invoked on a left-click of the icon. Right-click opens the menu.                      |
4001        callback clicked;
4002    } }
4003
4004    element! {
4005        // Lowered in lower_menus pass. See that pass documentation for more info.
4006        // The optional Menu child is lifted into a separate item tree and wired via
4007        // the `SetupSystemTrayIcon` builtin.
4008        /// Use the `SystemTrayIcon` element to add an icon and menu to the desktop's system tray,
4009        /// also known as the notification area, status area, or menu bar extras, depending on the platform.
4010        ///
4011        /// `SystemTrayIcon` is a top-level component: derive your own component
4012        /// from it with `inherits SystemTrayIcon` instead of placing it inside a <Link type="Window" />.
4013        /// A `SystemTrayIcon` component has no window of its own — the icon lives in the tray, and the only UI
4014        /// it presents is the menu.
4015        ///
4016        /// ```slint
4017        /// export component ExampleTray inherits SystemTrayIcon {
4018        ///     icon: @image-url("tray-icon.png");
4019        ///     tooltip: "My App";
4020        ///
4021        ///     Menu {
4022        ///         MenuItem {
4023        ///             title: "Quit";
4024        ///             activated => { quit(); }
4025        ///         }
4026        ///     }
4027        ///
4028        ///     callback quit();
4029        /// }
4030        /// ```
4031        ///
4032        /// Create the component from your language binding as you would any other Slint component;
4033        /// the tray icon appears as soon as the instance is created and an event loop is running,
4034        /// and disappears when the instance is dropped.
4035        ///
4036        /// :::note{Note}
4037        /// A `SystemTrayIcon` exported alongside a `Window` doesn't share <Link type="Globals" label="globals" /> with that window — each instance gets its own copy.
4038        /// You may need to initialize the relevant globals on each instance, the same way you would across multiple windows.
4039        /// :::
4040        ///
4041        /// :::note{Note}
4042        /// A `SystemTrayIcon` must contain exactly one <Link type="Menu" /> child, and that `Menu` must not
4043        /// be inside an `if` or a `for`. No other child element types are permitted. The menu itself may
4044        /// use `if` / `for` to build its entries dynamically.
4045        /// :::
4046        ///
4047        /// \skip_children
4048        /// \footer
4049        /// ## Menu
4050        ///
4051        /// The child `Menu` defines the menu that is shown when the user clicks or right-clicks the tray
4052        /// icon. Its structure is the same as for <Link type="MenuBar" /> and `ContextMenuArea`: use
4053        /// `MenuItem` for entries, nested `Menu` elements for sub-menus, and `MenuSeparator` for
4054        /// separators. See <Link type="Menu" /> for the properties and callbacks available on those
4055        /// elements.
4056        ///
4057        /// The menu tree is reactive: when any property the menu reads changes (for example the `title`,
4058        /// `enabled`, or `checked` binding of a `MenuItem`), Slint rebuilds the platform menu so the tray
4059        /// reflects the new state on its next open.
4060        ///
4061        /// Keyboard `shortcut` bindings on `MenuItem`s within a `SystemTrayIcon` are ignored — tray menus are
4062        /// not attached to a focused window, so there is nothing for the shortcut to fire against.
4063        ///
4064        /// ## Language Bindings
4065        ///
4066        /// The generated public API for a `SystemTrayIcon`-rooted component is smaller than the one
4067        /// for a `Window`-rooted component. Construction, property and callback accessors, and global
4068        /// access work the same way. Two things are missing:
4069        ///
4070        /// | Operation              | Window-rooted | SystemTrayIcon-rooted |
4071        /// | ---------------------- | :-----------: | :---------------: |
4072        /// | access the window      | yes           | **no**            |
4073        /// | run the event loop     | yes           | **no**            |
4074        ///
4075        /// `show` and `hide` exist on both, but on a `SystemTrayIcon` they set the `visible` property,
4076        /// and the platform backend translates that into the native tray API.
4077        /// A visible `SystemTrayIcon` keeps the event loop alive the same way a visible window does.
4078        ///
4079        /// A typical app instantiates both a main window and a tray, shows them, and runs the event loop.
4080        /// The snippets below also wire the built-in `clicked` callback so a left-click on the tray icon
4081        /// brings the window back if the user has hidden it.
4082        ///
4083        /// <Tabs syncKey="dev-language">
4084        /// <TabItem label="Rust">
4085        /// ```rust
4086        /// fn main() -> Result<(), slint::PlatformError> {
4087        ///     let window = MainWindow::new()?;
4088        ///     let tray = ExampleTray::new()?;
4089        ///
4090        ///     let window_weak = window.as_weak();
4091        ///     tray.on_clicked(move || {
4092        ///         if let Some(w) = window_weak.upgrade() {
4093        ///             let _ = w.show();
4094        ///         }
4095        ///     });
4096        ///
4097        ///     window.show()?;
4098        ///     tray.show()?;
4099        ///     slint::run_event_loop()
4100        /// }
4101        /// ```
4102        /// </TabItem>
4103        /// <TabItem label="C++">
4104        /// ```cpp
4105        /// int main() {
4106        ///     auto window = MainWindow::create();
4107        ///     auto tray = ExampleTray::create();
4108        ///
4109        ///     auto window_weak = slint::ComponentWeakHandle(window);
4110        ///     tray->on_clicked([window_weak] {
4111        ///         if (auto w = window_weak.lock()) {
4112        ///             (*w)->show();
4113        ///         }
4114        ///     });
4115        ///
4116        ///     window->show();
4117        ///     tray->show();
4118        ///     slint::run_event_loop();
4119        /// }
4120        /// ```
4121        /// </TabItem>
4122        /// <TabItem label="NodeJS">
4123        /// ```js
4124        /// const window = new ui.MainWindow();
4125        /// const tray = new ui.ExampleTray();
4126        /// tray.clicked = () => window.show();
4127        /// window.show();
4128        /// tray.show();
4129        /// await slint.runEventLoop();
4130        /// ```
4131        /// </TabItem>
4132        /// <TabItem label="Python">
4133        /// ```python
4134        /// window = module.MainWindow()
4135        /// tray = module.ExampleTray()
4136        /// tray.clicked = lambda: window.show()
4137        /// window.show()
4138        /// tray.show()
4139        /// slint.run_event_loop()
4140        /// ```
4141        /// </TabItem>
4142        /// </Tabs>
4143        ///
4144        /// A program that exposes only a `SystemTrayIcon` and no window is also valid: skip the
4145        /// `MainWindow` instance, and the loop quits once the tray is hidden (or `slint::quit_event_loop`
4146        /// is called). No `WindowAdapter` is created in that case — the platform backend is still
4147        /// selected the usual way, but no window opens.
4148        ///
4149        /// ## Platform Support
4150        ///
4151        /// | Platform      | Mechanism                                             |
4152        /// | ------------- | ----------------------------------------------------- |
4153        /// | Linux, \*BSD  | `StatusNotifierItem` / `AppIndicator` on D-Bus        |
4154        /// | macOS         | `NSStatusItem` in the menu bar                        |
4155        /// | Windows       | Shell notification area icon (`Shell_NotifyIcon`)     |
4156        ///
4157        /// On Linux, a desktop environment or shell extension that implements the `StatusNotifierItem`
4158        /// specification is required; plain X11 system trays are not supported. GNOME, for example,
4159        /// needs an extension such as *AppIndicator and KStatusNotifierItem Support*.
4160        ///
4161        /// \group:window
4162        @is_non_item_type @disallow_global_types_as_child_elements
4163        SystemTrayIcon: SystemTrayIcon {
4164            children: Menu;
4165        }
4166    }
4167}
4168
4169/// Fill `register` with the builtin elements. It must already contain the basic types
4170/// (string, int, ...), the builtin structs and enums.
4171pub(crate) fn load(register: &mut TypeRegister) {
4172    let mut loader = Loader { register, items: HashMap::new(), elements: HashMap::new() };
4173    build(&mut loader);
4174    let Loader { register, elements, .. } = loader;
4175    // Elements that are accepted children of another one are only reachable through it.
4176    let is_child = |name: &SmolStr| {
4177        elements.values().any(|e| e.additional_accepted_child_types.contains_key(name))
4178    };
4179    for (name, element) in &elements {
4180        match name.as_str() {
4181            "Empty" => register.empty_type = ElementType::Builtin(element.clone()),
4182            "PropertyAnimation" => {
4183                register.property_animation_type = ElementType::Builtin(element.clone())
4184            }
4185            _ if !element.is_global && !is_child(name) => register.add_builtin(element.clone()),
4186            _ => {}
4187        }
4188    }
4189}