Skip to content

Commit 90b9872

Browse files
committed
Add a scale property to all elements
`scale-x` and `scale-y` defaults to that
1 parent 3acc16d commit 90b9872

File tree

5 files changed

+131
-29
lines changed

5 files changed

+131
-29
lines changed

docs/astro/src/content/docs/reference/common.mdx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,21 @@ The y component of the origin to rotate and scale around.
7272

7373
In the future this will be deprecated in favour of a transform-origin property.
7474
</SlintProperty>
75+
76+
#### scale
77+
<SlintProperty propName="scale" typeName="float" defaultValue='100%'>
78+
The scale factor to apply to the element and all its children.
79+
80+
This doesn't affect the geometry (width, height) of the element, but affects the rendering.
81+
The scale is done around the `rotation-origin` point.
82+
83+
It is also possible to use the `scale-x` and `scale-y` properties to specify the scale factors for the x and y axis.
84+
</SlintProperty>
85+
7586
#### scale-x
76-
<SlintProperty propName="scale-x" typeName="percent" defaultValue='100%'/>
87+
<SlintProperty propName="scale-x" typeName="float" defaultValue='self.scale'/>
7788
#### scale-y
78-
<SlintProperty propName="scale-y" typeName="percent" defaultValue='100%'/>
89+
<SlintProperty propName="scale-y" typeName="float" defaultValue='self.scale'/>
7990

8091
### opacity
8192
<CodeSnippetMD imagePath="/src/assets/generated/rectangle-opacity.png" scale="3" imageWidth="100" imageHeight="310" imageAlt='rectangle opacity'>

internal/compiler/passes.rs

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ mod visible;
5555
mod z_order;
5656

5757
use crate::expression_tree::Expression;
58-
use crate::namedreference::NamedReference;
5958
use smol_str::SmolStr;
6059

6160
pub fn ignore_debug_hooks(expr: &Expression) -> &Expression {
@@ -166,30 +165,8 @@ pub async fn run_passes(
166165
);
167166
visible::handle_visible(component, &global_type_registry.borrow(), diag);
168167
lower_shadows::lower_shadow_properties(component, &doc.local_registry, diag);
169-
lower_property_to_element::lower_property_to_element(
168+
lower_property_to_element::lower_transform_properties(
170169
component,
171-
crate::typeregister::RESERVED_TRANSFORM_PROPERTIES[..3]
172-
.iter()
173-
.map(|(prop_name, _)| *prop_name),
174-
crate::typeregister::RESERVED_TRANSFORM_PROPERTIES[3..]
175-
.iter()
176-
.map(|(prop_name, _)| *prop_name),
177-
Some(&|e, prop| {
178-
let prop_div_2 = |prop: &str| Expression::BinaryExpression {
179-
lhs: Expression::PropertyReference(NamedReference::new(e, prop.into())).into(),
180-
op: '/',
181-
rhs: Expression::NumberLiteral(2., Default::default()).into(),
182-
};
183-
184-
match prop {
185-
"rotation-origin-x" => prop_div_2("width"),
186-
"rotation-origin-y" => prop_div_2("height"),
187-
"scale-x" | "scale-y" => Expression::NumberLiteral(1., Default::default()),
188-
"rotation-angle" => Expression::NumberLiteral(0., Default::default()),
189-
_ => unreachable!(),
190-
}
191-
}),
192-
&SmolStr::new_static("Transform"),
193170
&global_type_registry.borrow(),
194171
diag,
195172
);

internal/compiler/passes/lower_property_to_element.rs

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub(crate) fn lower_property_to_element(
2020
component: &Rc<Component>,
2121
property_names: impl Iterator<Item = &'static str> + Clone,
2222
extra_properties: impl Iterator<Item = &'static str> + Clone,
23-
default_value_for_extra_properties: Option<&dyn Fn(&ElementRc, &str) -> Expression>,
23+
default_value_for_extra_properties: Option<&dyn Fn(&ElementRc, &str) -> Option<Expression>>,
2424
element_name: &SmolStr,
2525
type_register: &TypeRegister,
2626
diag: &mut BuildDiagnostics,
@@ -95,7 +95,7 @@ pub(crate) fn lower_property_to_element(
9595
fn create_property_element(
9696
child: &ElementRc,
9797
properties: impl Iterator<Item = &'static str>,
98-
default_value_for_extra_properties: Option<&dyn Fn(&ElementRc, &str) -> Expression>,
98+
default_value_for_extra_properties: Option<&dyn Fn(&ElementRc, &str) -> Option<Expression>>,
9999
element_name: &SmolStr,
100100
type_register: &TypeRegister,
101101
) -> ElementRc {
@@ -105,7 +105,9 @@ fn create_property_element(
105105
BindingExpression::new_two_way(NamedReference::new(child, property_name.into()));
106106
if let Some(default_value_for_extra_properties) = default_value_for_extra_properties {
107107
if !child.borrow().bindings.contains_key(property_name) {
108-
bind.expression = default_value_for_extra_properties(child, property_name)
108+
if let Some(e) = default_value_for_extra_properties(child, property_name) {
109+
bind.expression = e;
110+
}
109111
}
110112
}
111113
(property_name.into(), bind.into())
@@ -121,3 +123,50 @@ fn create_property_element(
121123
};
122124
element.make_rc()
123125
}
126+
127+
/// Wrapper around lower_property_to_element for the Transform element
128+
pub fn lower_transform_properties(
129+
component: &Rc<Component>,
130+
tr: &TypeRegister,
131+
diag: &mut BuildDiagnostics,
132+
) {
133+
lower_property_to_element(
134+
component,
135+
crate::typeregister::RESERVED_TRANSFORM_PROPERTIES[..4]
136+
.iter()
137+
.map(|(prop_name, _)| *prop_name),
138+
crate::typeregister::RESERVED_TRANSFORM_PROPERTIES[4..]
139+
.iter()
140+
.map(|(prop_name, _)| *prop_name),
141+
Some(&|e, prop| {
142+
let prop_div_2 = |prop: &str| {
143+
Some(Expression::BinaryExpression {
144+
lhs: Expression::PropertyReference(NamedReference::new(e, prop.into())).into(),
145+
op: '/',
146+
rhs: Expression::NumberLiteral(2., Default::default()).into(),
147+
})
148+
};
149+
150+
match prop {
151+
"rotation-origin-x" => prop_div_2("width"),
152+
"rotation-origin-y" => prop_div_2("height"),
153+
"scale-x" | "scale-y" => {
154+
if e.borrow().is_binding_set("scale", true) {
155+
Some(Expression::PropertyReference(NamedReference::new(
156+
e,
157+
SmolStr::new_static("scale"),
158+
)))
159+
} else {
160+
Some(Expression::NumberLiteral(1., Default::default()))
161+
}
162+
}
163+
"scale" => None,
164+
"rotation-angle" => Some(Expression::NumberLiteral(0., Default::default())),
165+
_ => unreachable!(),
166+
}
167+
}),
168+
&SmolStr::new_static("Transform"),
169+
tr,
170+
diag,
171+
);
172+
}

internal/compiler/typeregister.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ pub const RESERVED_TRANSFORM_PROPERTIES: &[(&str, Type)] = &[
179179
("rotation-angle", Type::Angle),
180180
("scale-x", Type::Float32),
181181
("scale-y", Type::Float32),
182+
("scale", Type::Float32),
182183
("rotation-origin-x", Type::LogicalLength),
183184
("rotation-origin-y", Type::LogicalLength),
184185
];
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright © SixtyFPS GmbH <[email protected]>
2+
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
3+
4+
export component TestCase {
5+
width: 800px;
6+
height: 600px;
7+
8+
in-out property <string> result;
9+
10+
r-a := Rectangle {
11+
x: 10px;
12+
y: 10px;
13+
width: 20px;
14+
height: 20px;
15+
rotation-origin-x: 0;
16+
rotation-origin-y: 0;
17+
scale: 2;
18+
TouchArea {
19+
clicked => { result += "A"}
20+
}
21+
}
22+
23+
24+
r-b := Rectangle {
25+
x: 100px;
26+
y: 100px;
27+
width: 20px;
28+
height: 20px;
29+
scale: 3;
30+
scale-x: 0.5;
31+
TouchArea {
32+
clicked => { result += "B"}
33+
}
34+
}
35+
36+
out property <bool> test:
37+
r-a.scale == 2 && r-a.scale-x == 2 && r-a.scale-y == 2 &&
38+
r-b.scale-x == 0.5 && r-b.scale-y == 3;
39+
40+
41+
}
42+
43+
/*
44+
```rust
45+
let instance = TestCase::new().unwrap();
46+
47+
assert_eq!(instance.get_test(), true);
48+
49+
slint_testing::send_mouse_click(&instance, 10.0 + 39.0 , 10.0 + 39.0);
50+
assert_eq!(instance.get_result(), "A", "was just clicked inside");
51+
slint_testing::send_mouse_click(&instance, 10.0 + 19.0 , 10.0 + 41.0);
52+
assert_eq!(instance.get_result(), "A", "was just clicked outside");
53+
slint_testing::send_mouse_click(&instance, 10.0 + 41.0 , 10.0 + 19.0);
54+
assert_eq!(instance.get_result(), "A", "was just clicked outside again");
55+
56+
57+
slint_testing::send_mouse_click(&instance, 100.0 + 6. , 100.0 - 19.0);
58+
assert_eq!(instance.get_result(), "AB", "was just clicked inside");
59+
slint_testing::send_mouse_click(&instance, 100.0 + 4., 100.0);
60+
assert_eq!(instance.get_result(), "AB", "was just clicked outside");
61+
slint_testing::send_mouse_click(&instance, 100.0 + 10., 100. - 21.);
62+
assert_eq!(instance.get_result(), "AB", "was just clicked outside again");
63+
```
64+
*/

0 commit comments

Comments
 (0)