i_slint_compiler/passes/
lower_absolute_coordinates.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//! This pass creates bindings to "absolute-y" and "absolute-y" properties
5//! that can be used to compute the window-absolute coordinates of elements.
6
7use smol_str::SmolStr;
8use std::cell::RefCell;
9use std::rc::Rc;
10
11use crate::expression_tree::{BuiltinFunction, Expression};
12use crate::langtype::Type;
13use crate::namedreference::NamedReference;
14use crate::object_tree::Component;
15
16pub fn lower_absolute_coordinates(component: &Rc<Component>) {
17    let mut to_materialize = std::collections::HashSet::new();
18
19    crate::object_tree::visit_all_named_references(component, &mut |nr| {
20        if nr.name() == "absolute-position" {
21            to_materialize.insert(nr.clone());
22        }
23    });
24
25    let Type::Struct(point_type) = BuiltinFunction::ItemAbsolutePosition.ty().return_type.clone()
26    else {
27        unreachable!()
28    };
29
30    for nr in to_materialize {
31        let elem = nr.element();
32
33        // Create a binding for the `absolute-position` property. The
34        // materialize properties pass is going to create the actual property later.
35
36        let parent_position_var = Box::new(Expression::ReadLocalVariable {
37            name: "parent_position".into(),
38            ty: point_type.clone().into(),
39        });
40
41        let binding = Expression::CodeBlock(vec![
42            Expression::StoreLocalVariable {
43                name: "parent_position".into(),
44                value: Expression::FunctionCall {
45                    function: BuiltinFunction::ItemAbsolutePosition.into(),
46                    arguments: vec![Expression::ElementReference(Rc::downgrade(&elem))],
47                    source_location: None,
48                }
49                .into(),
50            },
51            Expression::Struct {
52                ty: point_type.clone(),
53                values: IntoIterator::into_iter(["x", "y"])
54                    .map(|coord| {
55                        (
56                            coord.into(),
57                            Expression::BinaryExpression {
58                                lhs: Expression::StructFieldAccess {
59                                    base: parent_position_var.clone(),
60                                    name: coord.into(),
61                                }
62                                .into(),
63                                rhs: Expression::PropertyReference(NamedReference::new(
64                                    &elem,
65                                    SmolStr::new_static(coord),
66                                ))
67                                .into(),
68                                op: '+',
69                            },
70                        )
71                    })
72                    .collect(),
73            },
74        ]);
75
76        elem.borrow_mut().bindings.insert(nr.name().clone(), RefCell::new(binding.into()));
77    }
78}