mirror of
https://github.com/slint-ui/slint.git
synced 2025-09-28 21:04:47 +00:00
Compiler: properly transform property access from base expression in state
Fix #5038
This commit is contained in:
parent
aebc7570c8
commit
2c0ba2bc0f
2 changed files with 83 additions and 12 deletions
|
@ -204,27 +204,28 @@ enum ExpressionForProperty {
|
||||||
fn expression_for_property(element: &ElementRc, name: &str) -> ExpressionForProperty {
|
fn expression_for_property(element: &ElementRc, name: &str) -> ExpressionForProperty {
|
||||||
let mut element_it = Some(element.clone());
|
let mut element_it = Some(element.clone());
|
||||||
let mut in_base = false;
|
let mut in_base = false;
|
||||||
while let Some(element) = element_it {
|
while let Some(elem) = element_it {
|
||||||
if let Some(e) = element.borrow().bindings.get(name) {
|
if let Some(e) = elem.borrow().bindings.get(name) {
|
||||||
let e = e.borrow();
|
let e = e.borrow();
|
||||||
if !e.two_way_bindings.is_empty() {
|
if !e.two_way_bindings.is_empty() {
|
||||||
return ExpressionForProperty::TwoWayBinding;
|
return ExpressionForProperty::TwoWayBinding;
|
||||||
}
|
}
|
||||||
if !matches!(e.expression, Expression::Invalid) {
|
let mut expr = e.expression.clone();
|
||||||
|
if !matches!(expr, Expression::Invalid) {
|
||||||
if in_base {
|
if in_base {
|
||||||
// Check that the expresison is valid in the new scope
|
// Check that the expresison is valid in the new scope
|
||||||
let mut has_invalid = false;
|
let mut has_invalid = false;
|
||||||
e.expression.visit_recursive(&mut |ex| match ex {
|
expr.visit_recursive_mut(&mut |ex| match ex {
|
||||||
Expression::CallbackReference(nr, _)
|
Expression::CallbackReference(nr, _)
|
||||||
| Expression::PropertyReference(nr)
|
| Expression::PropertyReference(nr)
|
||||||
| Expression::FunctionReference(nr, _) => {
|
| Expression::FunctionReference(nr, _) => {
|
||||||
let e = nr.element();
|
let e = nr.element();
|
||||||
if !Rc::ptr_eq(&e, &element)
|
if Rc::ptr_eq(&e, &elem) {
|
||||||
&& Weak::ptr_eq(
|
*nr = NamedReference::new(element, nr.name());
|
||||||
&e.borrow().enclosing_component,
|
} else if Weak::ptr_eq(
|
||||||
&element.borrow().enclosing_component,
|
&e.borrow().enclosing_component,
|
||||||
)
|
&elem.borrow().enclosing_component,
|
||||||
{
|
) {
|
||||||
has_invalid = true;
|
has_invalid = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -235,10 +236,10 @@ fn expression_for_property(element: &ElementRc, name: &str) -> ExpressionForProp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ExpressionForProperty::Expression(e.expression.clone());
|
return ExpressionForProperty::Expression(expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
element_it = if let ElementType::Component(base) = &element.borrow().base_type {
|
element_it = if let ElementType::Component(base) = &elem.borrow().base_type {
|
||||||
in_base = true;
|
in_base = true;
|
||||||
Some(base.root_element.clone())
|
Some(base.root_element.clone())
|
||||||
} else {
|
} else {
|
||||||
|
|
70
tests/cases/properties/issue5038_state_in_base.slint
Normal file
70
tests/cases/properties/issue5038_state_in_base.slint
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial
|
||||||
|
|
||||||
|
export global Glob {
|
||||||
|
in-out property <bool> cond2;
|
||||||
|
}
|
||||||
|
|
||||||
|
component Base inherits Rectangle {
|
||||||
|
in property <int> value;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export component R1 inherits Base {
|
||||||
|
|
||||||
|
t := TouchArea { }
|
||||||
|
|
||||||
|
ti := TextInput { text: Glob.cond2 ? "a" : "b"; }
|
||||||
|
|
||||||
|
|
||||||
|
states [
|
||||||
|
xxx when ti.text == "a" : {
|
||||||
|
value: 1;
|
||||||
|
}
|
||||||
|
hover when t.has-hover: {
|
||||||
|
background: white;
|
||||||
|
value: 2;
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export component R2 inherits R1 { }
|
||||||
|
|
||||||
|
export component TestCase inherits Window {
|
||||||
|
in property <bool> cond1;
|
||||||
|
r2 := R2 {
|
||||||
|
states [
|
||||||
|
s1 when cond1: {
|
||||||
|
background: white;
|
||||||
|
value: 3;
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
out property <int> value: r2.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
```cpp
|
||||||
|
auto handle = TestCase::create();
|
||||||
|
const TestCase &instance = *handle;
|
||||||
|
assert_eq(instance.get_value(), 0);
|
||||||
|
instance.global<Glob>().set_cond2(true);
|
||||||
|
assert_eq(instance.get_value(), 1);
|
||||||
|
instance.set_cond1(true);
|
||||||
|
assert_eq(instance.get_value(), 3);
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
```rust
|
||||||
|
let instance = TestCase::new().unwrap();
|
||||||
|
assert_eq!(instance.get_value(), 0);
|
||||||
|
instance.global::<Glob<'_>>().set_cond2(true);
|
||||||
|
assert_eq!(instance.get_value(), 1);
|
||||||
|
instance.set_cond1(true);
|
||||||
|
assert_eq!(instance.get_value(), 3);
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
Loading…
Add table
Add a link
Reference in a new issue