mirror of
https://github.com/slint-ui/slint.git
synced 2025-08-04 02:39:28 +00:00
Fix change handler with callback
Don't merge a property with a global property if it has a change handler as we can't mobe the change handler in the global Fixes #7784 If two property are merged that each have a change handler, we must merge the change handler. (Note that the order in which they are being called is not deterministic) Fixes #7747
This commit is contained in:
parent
e5ecb9cf6c
commit
d63168d51b
2 changed files with 113 additions and 10 deletions
|
@ -21,17 +21,23 @@ struct PropertySets {
|
|||
|
||||
impl PropertySets {
|
||||
fn add_link(&mut self, p1: NamedReference, p2: NamedReference) {
|
||||
let (e1, e2) = (p1.element(), p2.element());
|
||||
if !std::rc::Weak::ptr_eq(
|
||||
&p1.element().borrow().enclosing_component,
|
||||
&p2.element().borrow().enclosing_component,
|
||||
) && !p1.element().borrow().enclosing_component.upgrade().unwrap().is_global()
|
||||
&& !p2.element().borrow().enclosing_component.upgrade().unwrap().is_global()
|
||||
{
|
||||
// We can only merge aliases if they are in the same Component. (unless one of them is global)
|
||||
// TODO: actually we could still merge two alias in a component pointing to the same
|
||||
// property in a parent component
|
||||
return;
|
||||
&e1.borrow().enclosing_component,
|
||||
&e2.borrow().enclosing_component,
|
||||
) {
|
||||
if !(e1.borrow().enclosing_component.upgrade().unwrap().is_global()
|
||||
&& !e2.borrow().change_callbacks.contains_key(p2.name()))
|
||||
&& !(e2.borrow().enclosing_component.upgrade().unwrap().is_global()
|
||||
&& !e1.borrow().change_callbacks.contains_key(p1.name()))
|
||||
{
|
||||
// We can only merge aliases if they are in the same Component. (unless one of them is global if the other one don't have change event)
|
||||
// TODO: actually we could still merge two alias in a component pointing to the same
|
||||
// property in a parent component
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(s1) = self.map.get(&p1).cloned() {
|
||||
if let Some(s2) = self.map.get(&p2).cloned() {
|
||||
if Rc::ptr_eq(&s1, &s2) {
|
||||
|
@ -159,10 +165,14 @@ pub fn remove_aliases(doc: &Document, diag: &mut BuildDiagnostics) {
|
|||
let mut elem = elem.borrow_mut();
|
||||
if let Some(old_change_callback) = elem.change_callbacks.remove(remove.name()) {
|
||||
drop(elem);
|
||||
let mut old_change_callback = old_change_callback.into_inner();
|
||||
to_elem
|
||||
.borrow_mut()
|
||||
.change_callbacks
|
||||
.insert(to.name().clone(), old_change_callback);
|
||||
.entry(to.name().clone())
|
||||
.or_default()
|
||||
.borrow_mut()
|
||||
.append(&mut old_change_callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
93
tests/cases/properties/changes_alias.slint
Normal file
93
tests/cases/properties/changes_alias.slint
Normal file
|
@ -0,0 +1,93 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
|
||||
|
||||
|
||||
export global State {
|
||||
// Issue #7784
|
||||
in property <int> tab-names;
|
||||
|
||||
in-out property <int> r;
|
||||
}
|
||||
|
||||
// issue #7747
|
||||
component Inner {
|
||||
in-out property <int> test-value;
|
||||
|
||||
changed test-value => {
|
||||
State.r += root.test-value * 10000;
|
||||
}
|
||||
}
|
||||
|
||||
component Intermediate {
|
||||
in-out property <int> test-value;
|
||||
|
||||
changed test-value => {
|
||||
State.r += root.test-value * 100;
|
||||
}
|
||||
|
||||
Inner {
|
||||
test-value <=> root.test-value;
|
||||
}
|
||||
|
||||
@children
|
||||
}
|
||||
|
||||
export component TestCase inherits Window {
|
||||
// Issue #7784
|
||||
out property <int> current-tab;
|
||||
in property <int> tab-names <=> State.tab-names;
|
||||
changed tab-names => {
|
||||
current-tab = tab-names;
|
||||
}
|
||||
|
||||
// Issue #7747
|
||||
in-out property <int> test-value;
|
||||
changed test-value => {
|
||||
State.r += root.test-value;
|
||||
}
|
||||
Intermediate {
|
||||
test-value <=> root.test-value;
|
||||
Text {
|
||||
text: "xx";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
```rust
|
||||
let instance = TestCase::new().unwrap();
|
||||
instance.global::<State<'_>>().set_tab_names(5);
|
||||
slint_testing::mock_elapsed_time(10);
|
||||
assert_eq!(instance.get_current_tab(), 5);
|
||||
|
||||
instance.set_test_value(8);
|
||||
slint_testing::mock_elapsed_time(10);
|
||||
assert_eq!(instance.global::<State<'_>>().get_r(), 80808);
|
||||
```
|
||||
|
||||
```cpp
|
||||
auto handle = TestCase::create();
|
||||
const TestCase &instance = *handle;
|
||||
instance.global<State>().set_tab_names(5);
|
||||
slint_testing::mock_elapsed_time(10);
|
||||
assert_eq(instance.get_current_tab(), 5);
|
||||
|
||||
instance.set_test_value(8);
|
||||
slint_testing::mock_elapsed_time(10);
|
||||
assert_eq(instance.global<State>().get_r(), 80808);
|
||||
```
|
||||
|
||||
```js
|
||||
var instance = new slint.TestCase({});
|
||||
instance.State.tab_names = 5;
|
||||
slintlib.private_api.mock_elapsed_time(10);
|
||||
assert.equal(instance.current_tab, 5);
|
||||
|
||||
instance.test_value = 8;
|
||||
slintlib.private_api.mock_elapsed_time(10);
|
||||
assert.equal(instance.State.r, 80808);
|
||||
```
|
||||
|
||||
*/
|
Loading…
Add table
Add a link
Reference in a new issue