From 73d94e9755e1e6fed4d9af255df32b62a3997276 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 20 Jun 2023 11:49:41 +0200 Subject: [PATCH 1/8] Merge `absolute-x` and `absolute-y` "virtual" properties into `absolute-coordinates` The type of thep property is `Point`, which existed before. It was mapped to `slint::private_unstable_api::re_exports::Point` (euclid) and is now mapped to slint::LogicalPosition (also in C++). --- CHANGELOG.md | 2 +- api/cpp/cbindgen.rs | 2 +- docs/language/src/builtins/elements.md | 2 +- internal/compiler/builtins.slint | 8 --- internal/compiler/generator/cpp.rs | 2 +- internal/compiler/generator/rust.rs | 2 +- .../passes/lower_absolute_coordinates.rs | 52 ++++++++++++------- internal/compiler/typeregister.rs | 9 ++-- internal/core/api.rs | 3 +- internal/core/items.rs | 4 +- tests/cases/absolute_coords.slint | 10 +++- 11 files changed, 53 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71e2f79bb16..d62901d4c3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,7 +28,7 @@ All notable changes to this project are documented in this file. - Added functions on color: `transparentize`, `mix`, and `with-alpha`. - Added a `close()` function and a `close-on-click` boolean property to `PopupWindow`. - Added basic translation infrastructure with `@tr("...")` - - Added `absolute-x` and `absolute-y` properties to every element, for computing window-absolute positions. + - Added `absolute-coordinates` property to every element, for computing window-absolute positions. - Added `primary` boolean property to `Button` to configure its visual appearance. - Added `current-row` to `StandardTableView`. diff --git a/api/cpp/cbindgen.rs b/api/cpp/cbindgen.rs index 0850a6e87b3..579404e5598 100644 --- a/api/cpp/cbindgen.rs +++ b/api/cpp/cbindgen.rs @@ -63,7 +63,7 @@ fn default_config() -> cbindgen::Config { ("VoidArg".into(), "void".into()), ("KeyEventArg".into(), "KeyEvent".into()), ("PointerEventArg".into(), "PointerEvent".into()), - ("PointArg".into(), "Point".into()), + ("PointArg".into(), "slint::LogicalPosition".into()), ("FloatArg".into(), "float".into()), ("Coord".into(), "float".into()), ] diff --git a/docs/language/src/builtins/elements.md b/docs/language/src/builtins/elements.md index a38c29c1dd8..60ceac6035f 100644 --- a/docs/language/src/builtins/elements.md +++ b/docs/language/src/builtins/elements.md @@ -9,7 +9,7 @@ These properties are valid on all visible items: - **`width`** and **`height`** (_in_ _length_): The size of the element. When set, this overrides the default size. - **`x`** and **`y`** (_in_ _length_): The position of the element relative to its parent. - **`z`** (_in_ _float_): Allows to specify a different order to stack the items with its siblings. (default value: 0) -- **`absolute-x`** and **`absolute-y`** (_in_ _length_): The position of the element within the contained window. +- **`absolute-coordinates`** (_in_ _Point_): The position of the element within the contained window. ### Layout diff --git a/internal/compiler/builtins.slint b/internal/compiler/builtins.slint index b8798866ceb..8b234f1e915 100644 --- a/internal/compiler/builtins.slint +++ b/internal/compiler/builtins.slint @@ -172,13 +172,6 @@ export component BoxShadow inherits Empty { //-is_internal } -// Keep an eye on typeregister::logical_point_type() that creates the same type. -export struct Point { - //-name:slint::private_api::Point - x: length, - y: length, -} - export component TextInput { in-out property text; in property font-family; @@ -408,7 +401,6 @@ export struct StandardListViewItem { } export struct TableColumn { - //-name:slint::private_api::TableColumn title: string, min-width: length, horizontal-stretch: float, diff --git a/internal/compiler/generator/cpp.rs b/internal/compiler/generator/cpp.rs index eeab47f4f00..4a3648bd6be 100644 --- a/internal/compiler/generator/cpp.rs +++ b/internal/compiler/generator/cpp.rs @@ -2841,7 +2841,7 @@ fn compile_builtin_function_call( BuiltinFunction::ItemAbsolutePosition => { if let [llr::Expression::PropertyReference(pr)] = arguments { let item_rc = access_item_rc(pr, ctx); - format!("slint_item_absolute_position(&{item_rc})") + format!("slint::LogicalPosition(slint_item_absolute_position(&{item_rc}))") } else { panic!("internal error: invalid args to ItemAbsolutePosition {:?}", arguments) } diff --git a/internal/compiler/generator/rust.rs b/internal/compiler/generator/rust.rs index a5bc7b34938..405f99c6fc8 100644 --- a/internal/compiler/generator/rust.rs +++ b/internal/compiler/generator/rust.rs @@ -2536,7 +2536,7 @@ fn compile_builtin_function_call( if let [Expression::PropertyReference(pr)] = arguments { let item_rc = access_item_rc(pr, ctx); quote!( - (*#item_rc).map_to_window(Default::default()).to_untyped() + slint::LogicalPosition::from_euclid((*#item_rc).map_to_window(Default::default())) ) } else { panic!("internal error: invalid args to MapPointToWindow {:?}", arguments) diff --git a/internal/compiler/passes/lower_absolute_coordinates.rs b/internal/compiler/passes/lower_absolute_coordinates.rs index ee4973dc884..cbbcd993fea 100644 --- a/internal/compiler/passes/lower_absolute_coordinates.rs +++ b/internal/compiler/passes/lower_absolute_coordinates.rs @@ -19,13 +19,14 @@ pub fn lower_absolute_coordinates(component: &Rc) { recurse_elem_including_sub_components_no_borrow(component, &(), &mut |elem, _| { visit_all_named_references_in_element(elem, |nr| { - if nr.name() == "absolute-x" || nr.name() == "absolute-y" { + if nr.name() == "absolute-coordinates" { to_materialize.insert(nr.clone()); } }); }); - let absolute_point_prop_name = "cached-absolute-xy".to_string(); + // Absolute item coordinates without the item local x/y. + let cached_absolute_item_prop_name = "cached-absolute-xy".to_string(); let point_type = match BuiltinFunction::ItemAbsolutePosition.ty() { crate::langtype::Type::Function { return_type, .. } => return_type.as_ref().clone(), _ => unreachable!(), @@ -36,13 +37,13 @@ pub fn lower_absolute_coordinates(component: &Rc) { elem.borrow_mut() .property_declarations - .entry(absolute_point_prop_name.clone()) + .entry(cached_absolute_item_prop_name.clone()) .or_insert_with(|| PropertyDeclaration { property_type: point_type.clone(), ..PropertyDeclaration::default() }); - if !elem.borrow().bindings.contains_key(&absolute_point_prop_name) { + if !elem.borrow().bindings.contains_key(&cached_absolute_item_prop_name) { let point_binding = Expression::FunctionCall { function: Box::new(Expression::BuiltinFunctionReference( BuiltinFunction::ItemAbsolutePosition, @@ -53,24 +54,35 @@ pub fn lower_absolute_coordinates(component: &Rc) { }; elem.borrow_mut() .bindings - .insert(absolute_point_prop_name.clone(), RefCell::new(point_binding.into())); + .insert(cached_absolute_item_prop_name.clone(), RefCell::new(point_binding.into())); } - // Create a binding to the hidden point property. The materialize properties pass is going to create the actual property - // for absolute-x/y. - let x_or_y = nr.name().strip_prefix("absolute-").unwrap().to_string(); - let binding = Expression::BinaryExpression { - lhs: Expression::StructFieldAccess { - base: Expression::PropertyReference(NamedReference::new( - &elem, - &absolute_point_prop_name, - )) - .into(), - name: x_or_y.clone(), - } - .into(), - rhs: Expression::PropertyReference(NamedReference::new(&elem, &x_or_y)).into(), - op: '+', + // Create a binding to the hidden point property and add item local x/y. The + // materialize properties pass is going to create the actual property for + // absolute-coordinates. + let binding = Expression::Struct { + ty: point_type.clone(), + values: IntoIterator::into_iter(["x", "y"]) + .map(|coord| { + ( + coord.to_string(), + Expression::BinaryExpression { + lhs: Expression::StructFieldAccess { + base: Expression::PropertyReference(NamedReference::new( + &elem, + &cached_absolute_item_prop_name, + )) + .into(), + name: coord.to_string(), + } + .into(), + rhs: Expression::PropertyReference(NamedReference::new(&elem, &coord)) + .into(), + op: '+', + }, + ) + }) + .collect(), }; elem.borrow_mut().bindings.insert(nr.name().to_string(), RefCell::new(binding.into())); } diff --git a/internal/compiler/typeregister.rs b/internal/compiler/typeregister.rs index 3c4aceedda9..a59b9b8d036 100644 --- a/internal/compiler/typeregister.rs +++ b/internal/compiler/typeregister.rs @@ -21,9 +21,6 @@ pub const RESERVED_GEOMETRY_PROPERTIES: &[(&str, Type)] = &[ ("z", Type::Float32), ]; -pub(crate) const RESERVED_ABSOLUTE_GEOMETRY_PROPERTIES: &[(&str, Type)] = - &[("absolute-x", Type::LogicalLength), ("absolute-y", Type::LogicalLength)]; - pub const RESERVED_LAYOUT_PROPERTIES: &[(&str, Type)] = &[ ("min-width", Type::LogicalLength), ("min-height", Type::LogicalLength), @@ -115,13 +112,13 @@ pub const RESERVED_ACCESSIBILITY_PROPERTIES: &[(&str, Type)] = &[ pub fn reserved_properties() -> impl Iterator { RESERVED_GEOMETRY_PROPERTIES .iter() - .chain(RESERVED_ABSOLUTE_GEOMETRY_PROPERTIES.iter()) .chain(RESERVED_LAYOUT_PROPERTIES.iter()) .chain(RESERVED_OTHER_PROPERTIES.iter()) .chain(RESERVED_DROP_SHADOW_PROPERTIES.iter()) .chain(RESERVED_ROTATION_PROPERTIES.iter()) .chain(RESERVED_ACCESSIBILITY_PROPERTIES.iter()) .map(|(k, v)| (*k, v.clone())) + .chain(IntoIterator::into_iter([("absolute-coordinates", logical_point_type())])) .chain(IntoIterator::into_iter([ ("forward-focus", Type::ElementReference), ("focus", BuiltinFunction::SetFocusItem.ty()), @@ -234,6 +231,7 @@ impl TypeRegister { register.insert_type(Type::Angle); register.insert_type(Type::Brush); register.insert_type(Type::Rem); + register.types.insert("Point".into(), logical_point_type()); BUILTIN_ENUMS.with(|e| e.fill_register(&mut register)); @@ -402,7 +400,6 @@ impl TypeRegister { } } -/// This is identical with builtins.slint's Point type (TODO: use that in the future) pub fn logical_point_type() -> Type { Type::Struct { fields: IntoIterator::into_iter([ @@ -410,7 +407,7 @@ pub fn logical_point_type() -> Type { ("y".to_owned(), Type::LogicalLength), ]) .collect(), - name: Some("Point".into()), + name: Some("slint::LogicalPosition".into()), node: None, rust_attributes: None, } diff --git a/internal/core/api.rs b/internal/core/api.rs index 61724fe474d..7036179c483 100644 --- a/internal/core/api.rs +++ b/internal/core/api.rs @@ -47,7 +47,8 @@ impl LogicalPosition { pub(crate) fn to_euclid(&self) -> crate::lengths::LogicalPoint { [self.x as _, self.y as _].into() } - pub(crate) fn from_euclid(p: crate::lengths::LogicalPoint) -> Self { + #[doc(hidden)] + pub fn from_euclid(p: crate::lengths::LogicalPoint) -> Self { Self::new(p.x as _, p.y as _) } } diff --git a/internal/core/items.rs b/internal/core/items.rs index 664934f51fc..59b436c2af2 100644 --- a/internal/core/items.rs +++ b/internal/core/items.rs @@ -1448,7 +1448,7 @@ pub struct PointerEvent { pub unsafe extern "C" fn slint_item_absolute_position( self_component: &vtable::VRc, self_index: usize, -) -> Point { +) -> LogicalPoint { let self_rc = ItemRc::new(self_component.clone(), self_index); - self_rc.map_to_window(Default::default()).to_untyped() + self_rc.map_to_window(Default::default()) } diff --git a/tests/cases/absolute_coords.slint b/tests/cases/absolute_coords.slint index 092f4f0cd5e..ab41434ad31 100644 --- a/tests/cases/absolute_coords.slint +++ b/tests/cases/absolute_coords.slint @@ -5,7 +5,7 @@ export component TestCase { width: 500phx; height: 500phx; - property simple-inner-ok: simple-inner.absolute-x == 40phx && simple-inner.absolute-y == 60phx; + property simple-inner-ok: simple-inner.absolute-coordinates.x == 40phx && simple-inner.absolute-coordinates.y == 60phx; Rectangle { x: 10phx; y: 20phx; @@ -16,23 +16,31 @@ export component TestCase { } } out property test: simple-inner-ok; + out property coords <=> simple-inner.absolute-coordinates; } /* ```rust let instance = TestCase::new().unwrap(); assert!(instance.get_test()); +let pos: slint::LogicalPosition = instance.get_coords(); +assert_eq!(pos.x, 40.); +assert_eq!(pos.y, 60.); ``` ```cpp auto handle = TestCase::create(); const TestCase &instance = *handle; assert(instance.get_test()); +slint::LogicalPosition pos = instance.get_coords(); +assert_eq(pos.x, 40); +assert_eq(pos.y, 60); ``` ```js let instance = new slint.TestCase({}); assert(instance.test, 1); +assert.deepEqual(instance.coords, { x: 40, y: 60}); ``` */ From e82f03b174d2efce831330f2d72d58e90ebb49ae Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 20 Jun 2023 15:46:11 +0200 Subject: [PATCH 2/8] fixup! Merge `absolute-x` and `absolute-y` "virtual" properties into `absolute-coordinates` --- internal/compiler/load_builtins.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/compiler/load_builtins.rs b/internal/compiler/load_builtins.rs index dadbdd143f2..54d874fd643 100644 --- a/internal/compiler/load_builtins.rs +++ b/internal/compiler/load_builtins.rs @@ -37,12 +37,13 @@ pub fn load_builtins(register: &mut TypeRegister) { for s in doc.StructDeclaration().chain(doc.ExportsList().flat_map(|e| e.StructDeclaration())) { let external_name = identifier_text(&s.DeclaredIdentifier()).unwrap(); let mut ty = object_tree::type_struct_from_node(s.ObjectType(), &mut diag, register, None); - if let Type::Struct { name, .. } = &mut ty { + if let Type::Struct { name, node, .. } = &mut ty { *name = Some( parse_annotation("name", &s.ObjectType()) .map_or_else(|| external_name.clone(), |s| s.unwrap()) .to_owned(), ); + *node = None; } else { unreachable!() } From e9c2eb73887afbf909e99abc3eec08f029a8073c Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 20 Jun 2023 16:44:05 +0200 Subject: [PATCH 3/8] fixup! Merge `absolute-x` and `absolute-y` "virtual" properties into `absolute-coordinates` --- .../tests/syntax/analysis/binding_loop_mappointtowindow.slint | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/compiler/tests/syntax/analysis/binding_loop_mappointtowindow.slint b/internal/compiler/tests/syntax/analysis/binding_loop_mappointtowindow.slint index 0121c1dcb7f..b809df336f2 100644 --- a/internal/compiler/tests/syntax/analysis/binding_loop_mappointtowindow.slint +++ b/internal/compiler/tests/syntax/analysis/binding_loop_mappointtowindow.slint @@ -4,11 +4,11 @@ export App := Rectangle { Rectangle { - x: inner.absolute-x > 10px ? 10px : 0px; + x: inner.absolute-coordinates.x > 10px ? 10px : 0px; // ^error{The binding for the property 'x' is part of a binding loop} inner := Rectangle { // ^error{The binding for the property 'cached-absolute-xy' is part of a binding loop} -// ^^error{The binding for the property 'absolute-x' is part of a binding loop} +// ^^error{The binding for the property 'absolute-coordinates' is part of a binding loop} } } From 94ddd4b58902cda9337a2a8a3431df079637d43e Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 20 Jun 2023 21:09:16 +0200 Subject: [PATCH 4/8] absolute-coordinates -> absolute-position --- CHANGELOG.md | 2 +- docs/language/src/builtins/elements.md | 2 +- internal/compiler/passes/lower_absolute_coordinates.rs | 4 ++-- .../tests/syntax/analysis/binding_loop_mappointtowindow.slint | 2 +- internal/compiler/typeregister.rs | 2 +- tests/cases/absolute_coords.slint | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d62901d4c3e..bcb20f0a5e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,7 +28,7 @@ All notable changes to this project are documented in this file. - Added functions on color: `transparentize`, `mix`, and `with-alpha`. - Added a `close()` function and a `close-on-click` boolean property to `PopupWindow`. - Added basic translation infrastructure with `@tr("...")` - - Added `absolute-coordinates` property to every element, for computing window-absolute positions. + - Added `absolute-position` property to every element, for computing window-absolute positions. - Added `primary` boolean property to `Button` to configure its visual appearance. - Added `current-row` to `StandardTableView`. diff --git a/docs/language/src/builtins/elements.md b/docs/language/src/builtins/elements.md index 60ceac6035f..b50a20f888b 100644 --- a/docs/language/src/builtins/elements.md +++ b/docs/language/src/builtins/elements.md @@ -9,7 +9,7 @@ These properties are valid on all visible items: - **`width`** and **`height`** (_in_ _length_): The size of the element. When set, this overrides the default size. - **`x`** and **`y`** (_in_ _length_): The position of the element relative to its parent. - **`z`** (_in_ _float_): Allows to specify a different order to stack the items with its siblings. (default value: 0) -- **`absolute-coordinates`** (_in_ _Point_): The position of the element within the contained window. +- **`absolute-position`** (_in_ _Point_): The position of the element within the contained window. ### Layout diff --git a/internal/compiler/passes/lower_absolute_coordinates.rs b/internal/compiler/passes/lower_absolute_coordinates.rs index cbbcd993fea..240b5b9727d 100644 --- a/internal/compiler/passes/lower_absolute_coordinates.rs +++ b/internal/compiler/passes/lower_absolute_coordinates.rs @@ -19,7 +19,7 @@ pub fn lower_absolute_coordinates(component: &Rc) { recurse_elem_including_sub_components_no_borrow(component, &(), &mut |elem, _| { visit_all_named_references_in_element(elem, |nr| { - if nr.name() == "absolute-coordinates" { + if nr.name() == "absolute-position" { to_materialize.insert(nr.clone()); } }); @@ -59,7 +59,7 @@ pub fn lower_absolute_coordinates(component: &Rc) { // Create a binding to the hidden point property and add item local x/y. The // materialize properties pass is going to create the actual property for - // absolute-coordinates. + // absolute-position. let binding = Expression::Struct { ty: point_type.clone(), values: IntoIterator::into_iter(["x", "y"]) diff --git a/internal/compiler/tests/syntax/analysis/binding_loop_mappointtowindow.slint b/internal/compiler/tests/syntax/analysis/binding_loop_mappointtowindow.slint index b809df336f2..31a48ac052e 100644 --- a/internal/compiler/tests/syntax/analysis/binding_loop_mappointtowindow.slint +++ b/internal/compiler/tests/syntax/analysis/binding_loop_mappointtowindow.slint @@ -4,7 +4,7 @@ export App := Rectangle { Rectangle { - x: inner.absolute-coordinates.x > 10px ? 10px : 0px; + x: inner.absolute-position.x > 10px ? 10px : 0px; // ^error{The binding for the property 'x' is part of a binding loop} inner := Rectangle { // ^error{The binding for the property 'cached-absolute-xy' is part of a binding loop} diff --git a/internal/compiler/typeregister.rs b/internal/compiler/typeregister.rs index a59b9b8d036..4f641100d4a 100644 --- a/internal/compiler/typeregister.rs +++ b/internal/compiler/typeregister.rs @@ -118,7 +118,7 @@ pub fn reserved_properties() -> impl Iterator { .chain(RESERVED_ROTATION_PROPERTIES.iter()) .chain(RESERVED_ACCESSIBILITY_PROPERTIES.iter()) .map(|(k, v)| (*k, v.clone())) - .chain(IntoIterator::into_iter([("absolute-coordinates", logical_point_type())])) + .chain(IntoIterator::into_iter([("absolute-position", logical_point_type())])) .chain(IntoIterator::into_iter([ ("forward-focus", Type::ElementReference), ("focus", BuiltinFunction::SetFocusItem.ty()), diff --git a/tests/cases/absolute_coords.slint b/tests/cases/absolute_coords.slint index ab41434ad31..9662fcfaf77 100644 --- a/tests/cases/absolute_coords.slint +++ b/tests/cases/absolute_coords.slint @@ -5,7 +5,7 @@ export component TestCase { width: 500phx; height: 500phx; - property simple-inner-ok: simple-inner.absolute-coordinates.x == 40phx && simple-inner.absolute-coordinates.y == 60phx; + property simple-inner-ok: simple-inner.absolute-position.x == 40phx && simple-inner.absolute-position.y == 60phx; Rectangle { x: 10phx; y: 20phx; @@ -16,7 +16,7 @@ export component TestCase { } } out property test: simple-inner-ok; - out property coords <=> simple-inner.absolute-coordinates; + out property coords <=> simple-inner.absolute-position; } /* From 8d041a94f8b06f70f5324f97867718b8db1a6059 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 20 Jun 2023 21:15:02 +0200 Subject: [PATCH 5/8] fixup! absolute-coordinates -> absolute-position --- .../tests/syntax/analysis/binding_loop_mappointtowindow.slint | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/compiler/tests/syntax/analysis/binding_loop_mappointtowindow.slint b/internal/compiler/tests/syntax/analysis/binding_loop_mappointtowindow.slint index 31a48ac052e..3f1a3d39f3a 100644 --- a/internal/compiler/tests/syntax/analysis/binding_loop_mappointtowindow.slint +++ b/internal/compiler/tests/syntax/analysis/binding_loop_mappointtowindow.slint @@ -8,7 +8,7 @@ export App := Rectangle { // ^error{The binding for the property 'x' is part of a binding loop} inner := Rectangle { // ^error{The binding for the property 'cached-absolute-xy' is part of a binding loop} -// ^^error{The binding for the property 'absolute-coordinates' is part of a binding loop} +// ^^error{The binding for the property 'absolute-position' is part of a binding loop} } } From 83e5946fae16e058351fa59f4e734bf446362354 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 20 Jun 2023 21:18:21 +0200 Subject: [PATCH 6/8] Rename internal property that caches the parent's absolute coordinates --- .../passes/lower_absolute_coordinates.rs | 17 +++++++++-------- .../binding_loop_mappointtowindow.slint | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/internal/compiler/passes/lower_absolute_coordinates.rs b/internal/compiler/passes/lower_absolute_coordinates.rs index 240b5b9727d..d2736d0e978 100644 --- a/internal/compiler/passes/lower_absolute_coordinates.rs +++ b/internal/compiler/passes/lower_absolute_coordinates.rs @@ -25,8 +25,8 @@ pub fn lower_absolute_coordinates(component: &Rc) { }); }); - // Absolute item coordinates without the item local x/y. - let cached_absolute_item_prop_name = "cached-absolute-xy".to_string(); + // Absolute item coordinates of the parent item. + let cached_parent_position_prop_name = "absolute-parent-position".to_string(); let point_type = match BuiltinFunction::ItemAbsolutePosition.ty() { crate::langtype::Type::Function { return_type, .. } => return_type.as_ref().clone(), _ => unreachable!(), @@ -37,13 +37,13 @@ pub fn lower_absolute_coordinates(component: &Rc) { elem.borrow_mut() .property_declarations - .entry(cached_absolute_item_prop_name.clone()) + .entry(cached_parent_position_prop_name.clone()) .or_insert_with(|| PropertyDeclaration { property_type: point_type.clone(), ..PropertyDeclaration::default() }); - if !elem.borrow().bindings.contains_key(&cached_absolute_item_prop_name) { + if !elem.borrow().bindings.contains_key(&cached_parent_position_prop_name) { let point_binding = Expression::FunctionCall { function: Box::new(Expression::BuiltinFunctionReference( BuiltinFunction::ItemAbsolutePosition, @@ -52,9 +52,10 @@ pub fn lower_absolute_coordinates(component: &Rc) { arguments: vec![Expression::ElementReference(Rc::downgrade(&elem))], source_location: None, }; - elem.borrow_mut() - .bindings - .insert(cached_absolute_item_prop_name.clone(), RefCell::new(point_binding.into())); + elem.borrow_mut().bindings.insert( + cached_parent_position_prop_name.clone(), + RefCell::new(point_binding.into()), + ); } // Create a binding to the hidden point property and add item local x/y. The @@ -70,7 +71,7 @@ pub fn lower_absolute_coordinates(component: &Rc) { lhs: Expression::StructFieldAccess { base: Expression::PropertyReference(NamedReference::new( &elem, - &cached_absolute_item_prop_name, + &cached_parent_position_prop_name, )) .into(), name: coord.to_string(), diff --git a/internal/compiler/tests/syntax/analysis/binding_loop_mappointtowindow.slint b/internal/compiler/tests/syntax/analysis/binding_loop_mappointtowindow.slint index 3f1a3d39f3a..5b0dd52ab8b 100644 --- a/internal/compiler/tests/syntax/analysis/binding_loop_mappointtowindow.slint +++ b/internal/compiler/tests/syntax/analysis/binding_loop_mappointtowindow.slint @@ -7,7 +7,7 @@ export App := Rectangle { x: inner.absolute-position.x > 10px ? 10px : 0px; // ^error{The binding for the property 'x' is part of a binding loop} inner := Rectangle { -// ^error{The binding for the property 'cached-absolute-xy' is part of a binding loop} +// ^error{The binding for the property 'absolute-parent-position' is part of a binding loop} // ^^error{The binding for the property 'absolute-position' is part of a binding loop} } } From acd16395d445a9823895a5e65fdaf5edfef6adb1 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 20 Jun 2023 21:28:00 +0200 Subject: [PATCH 7/8] Use a free-standing function from private_unstable_api instead of exposing the euclid conversion from from LogicalPosition --- api/rs/slint/private_unstable_api.rs | 2 +- internal/compiler/generator/rust.rs | 2 +- internal/core/api.rs | 3 +-- internal/core/lengths.rs | 4 ++++ 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/api/rs/slint/private_unstable_api.rs b/api/rs/slint/private_unstable_api.rs index ca380df5fa0..15b1222d080 100644 --- a/api/rs/slint/private_unstable_api.rs +++ b/api/rs/slint/private_unstable_api.rs @@ -196,7 +196,7 @@ pub mod re_exports { }; pub use i_slint_core::items::*; pub use i_slint_core::layout::*; - pub use i_slint_core::lengths::{LogicalLength, LogicalPoint}; + pub use i_slint_core::lengths::{logical_position_to_api, LogicalLength, LogicalPoint}; pub use i_slint_core::model::*; pub use i_slint_core::properties::{set_state_binding, Property, PropertyTracker, StateInfo}; pub use i_slint_core::slice::Slice; diff --git a/internal/compiler/generator/rust.rs b/internal/compiler/generator/rust.rs index 405f99c6fc8..3fde41a2520 100644 --- a/internal/compiler/generator/rust.rs +++ b/internal/compiler/generator/rust.rs @@ -2536,7 +2536,7 @@ fn compile_builtin_function_call( if let [Expression::PropertyReference(pr)] = arguments { let item_rc = access_item_rc(pr, ctx); quote!( - slint::LogicalPosition::from_euclid((*#item_rc).map_to_window(Default::default())) + slint::private_unstable_api::re_exports::logical_position_to_api((*#item_rc).map_to_window(Default::default())) ) } else { panic!("internal error: invalid args to MapPointToWindow {:?}", arguments) diff --git a/internal/core/api.rs b/internal/core/api.rs index 7036179c483..61724fe474d 100644 --- a/internal/core/api.rs +++ b/internal/core/api.rs @@ -47,8 +47,7 @@ impl LogicalPosition { pub(crate) fn to_euclid(&self) -> crate::lengths::LogicalPoint { [self.x as _, self.y as _].into() } - #[doc(hidden)] - pub fn from_euclid(p: crate::lengths::LogicalPoint) -> Self { + pub(crate) fn from_euclid(p: crate::lengths::LogicalPoint) -> Self { Self::new(p.x as _, p.y as _) } } diff --git a/internal/core/lengths.rs b/internal/core/lengths.rs index 87673c24ac4..6bef10b5c88 100644 --- a/internal/core/lengths.rs +++ b/internal/core/lengths.rs @@ -86,3 +86,7 @@ impl RectLengths for euclid::Rect { pub fn logical_size_from_api(size: crate::api::LogicalSize) -> LogicalSize { size.to_euclid() } + +pub fn logical_position_to_api(pos: LogicalPoint) -> crate::api::LogicalPosition { + crate::api::LogicalPosition::from_euclid(pos) +} From 3ef81fa45df20010cf213aaf070425cf4cfa3b52 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 20 Jun 2023 21:42:39 +0200 Subject: [PATCH 8/8] Document the `Point` mapping for Rust and C++ --- api/cpp/docs/types.md | 29 +++++++++++++++-------------- api/rs/slint/lib.rs | 1 + 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/api/cpp/docs/types.md b/api/cpp/docs/types.md index f43f3204125..afcfacbc413 100644 --- a/api/cpp/docs/types.md +++ b/api/cpp/docs/types.md @@ -4,25 +4,26 @@ The types used for properties in `.slint` design markup each translate to specif The follow table summarizes the entire mapping: ```{eval-rst} -=========================== ================================== ======================================================================================================================================= - :code:`.slint` Type C++ Type Note -=========================== ================================== ======================================================================================================================================= +=========================== =================================== ======================================================================================================================================= + :code:`.slint` Type C++ Type Note +=========================== =================================== ======================================================================================================================================= :code:`int` :code:`int` :code:`float` :code:`float` :code:`bool` :code:`bool` - :code:`string` :cpp:class:`slint::SharedString` A reference-counted string type that uses UTF-8 encoding and can be easily converted to a std::string_view or a :code:`const char *`. + :code:`string` :cpp:class:`slint::SharedString` A reference-counted string type that uses UTF-8 encoding and can be easily converted to a std::string_view or a :code:`const char *`. :code:`color` :cpp:class:`slint::Color` :code:`brush` :cpp:class:`slint::Brush` :code:`image` :cpp:class:`slint::Image` - :code:`physical_length` :code:`float` The unit are physical pixels. - :code:`length` :code:`float` At run-time, logical lengths are automatically translated to physical pixels using the device pixel ratio. - :code:`duration` :code:`std::int64_t` At run-time, durations are always represented as signed 64-bit integers with millisecond precision. - :code:`angle` :code:`float` The value in degrees. - :code:`relative-font-size` :code:`float` Relative font size factor that is multiplied with the :code:`Window.default-font-size` and can be converted to a :code:`length`. - structure A :code:`class` of the same name The order of the data member are in the same as in the slint declaration - anonymous object A :code:`std::tuple` The fields are in alphabetical order. - enum An :code:`enum class` The values are always converted to CamelCase. The order of the values is the same as in the declaration. -=========================== ================================== ======================================================================================================================================= + :code:`physical_length` :code:`float` The unit are physical pixels. + :code:`length` :code:`float` At run-time, logical lengths are automatically translated to physical pixels using the device pixel ratio. + :code:`duration` :code:`std::int64_t` At run-time, durations are always represented as signed 64-bit integers with millisecond precision. + :code:`angle` :code:`float` The value in degrees. + :code:`relative-font-size` :code:`float` Relative font size factor that is multiplied with the :code:`Window.default-font-size` and can be converted to a :code:`length`. + structure A :code:`class` of the same name The order of the data member are in the same as in the slint declaration + anonymous object A :code:`std::tuple` The fields are in alphabetical order. + enum An :code:`enum class` The values are always converted to CamelCase. The order of the values is the same as in the declaration. + :code:`Point` :cpp:class:`slint::LogicalPosition` A struct with :code:`x` and :code:`y` fields, representing logical coordinates. +=========================== =================================== ======================================================================================================================================= ``` ## Structures @@ -64,4 +65,4 @@ will generate the following type in C++: ```cpp enum class MyEnum { Alpha, BetaGamma, Omicron }; -``` \ No newline at end of file +``` diff --git a/api/rs/slint/lib.rs b/api/rs/slint/lib.rs index c8e97f7f813..f64a8deace8 100644 --- a/api/rs/slint/lib.rs +++ b/api/rs/slint/lib.rs @@ -187,6 +187,7 @@ The follow table summarizes the entire mapping: | anonymous object | anonymous tuple | The fields are in alphabetical order. | | enumeration | `enum` of the same name | The values are converted to CamelCase | | array | [`ModelRc`] | Arrays are represented as models, so that their contents can change dynamically. | +| `Point` | [`LogicalPosition`] | A struct with `x` and `y` fields, representing logical coordinates. | For user defined structures in the .slint, an extra struct is generated. For example, if the `.slint` contains