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