mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-01 06:11:16 +00:00
Only the computation of the model needs to be done in the evaluation scope for it
Otherwise any change in any of the properties of the delegate will cause the model to be reset.
This commit is contained in:
parent
c8fa3354be
commit
f5aeb9ba60
4 changed files with 44 additions and 42 deletions
|
@ -124,7 +124,7 @@ struct PropertyTracker
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
void evaluate(const F &f) const {
|
auto evaluate(const F &f) const -> std::enable_if_t<std::is_same_v<decltype(f()), void>> {
|
||||||
cbindgen_private::sixtyfps_property_tracker_evaluate(
|
cbindgen_private::sixtyfps_property_tracker_evaluate(
|
||||||
&inner,
|
&inner,
|
||||||
[](void *f){ (*reinterpret_cast<const F*>(f))(); },
|
[](void *f){ (*reinterpret_cast<const F*>(f))(); },
|
||||||
|
@ -132,6 +132,13 @@ struct PropertyTracker
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
auto evaluate(const F &f) const -> std::enable_if_t<!std::is_same_v<decltype(f()), void>, decltype(f())> {
|
||||||
|
decltype(f()) result;
|
||||||
|
this->evaluate([&] { result = f(); } );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cbindgen_private::PropertyTrackerOpaque inner;
|
cbindgen_private::PropertyTrackerOpaque inner;
|
||||||
};
|
};
|
||||||
|
|
|
@ -373,13 +373,11 @@ fn handle_repeater(
|
||||||
let repeater_id =
|
let repeater_id =
|
||||||
format!("repeater_{}", base_component.parent_element.upgrade().unwrap().borrow().id);
|
format!("repeater_{}", base_component.parent_element.upgrade().unwrap().borrow().id);
|
||||||
|
|
||||||
let model = compile_expression(&repeated.model, parent_component);
|
let mut model = compile_expression(&repeated.model, parent_component);
|
||||||
let model = if !repeated.is_conditional_element {
|
if repeated.is_conditional_element {
|
||||||
format!("{}.get()", model)
|
|
||||||
} else {
|
|
||||||
// bool converts to int
|
// bool converts to int
|
||||||
// FIXME: don't do a heap allocation here
|
// FIXME: don't do a heap allocation here
|
||||||
format!("std::make_shared<sixtyfps::IntModel>({}).get()", model)
|
model = format!("std::make_shared<sixtyfps::IntModel>({})", model)
|
||||||
};
|
};
|
||||||
|
|
||||||
if repeated.model.is_constant() {
|
if repeated.model.is_constant() {
|
||||||
|
@ -389,7 +387,7 @@ fn handle_repeater(
|
||||||
i = repeater_count
|
i = repeater_count
|
||||||
));
|
));
|
||||||
init.push(format!(
|
init.push(format!(
|
||||||
"self->{repeater_id}.update_model({model}, self);",
|
"self->{repeater_id}.update_model({model}.get(), self);",
|
||||||
repeater_id = repeater_id,
|
repeater_id = repeater_id,
|
||||||
model = model,
|
model = model,
|
||||||
));
|
));
|
||||||
|
@ -406,9 +404,9 @@ fn handle_repeater(
|
||||||
children_visitor_cases.push(format!(
|
children_visitor_cases.push(format!(
|
||||||
"\n case {i}: {{
|
"\n case {i}: {{
|
||||||
if (self->model_{i}.is_dirty()) {{
|
if (self->model_{i}.is_dirty()) {{
|
||||||
self->model_{i}.evaluate([&] {{
|
self->{id}.update_model(self->model_{i}.evaluate([&] {{
|
||||||
self->{id}.update_model({model}, self);
|
return {model};
|
||||||
}});
|
}}).get(), self);
|
||||||
}}
|
}}
|
||||||
return self->{id}.visit(order, visitor);
|
return self->{id}.visit(order, visitor);
|
||||||
}}",
|
}}",
|
||||||
|
|
|
@ -233,12 +233,12 @@ fn generate_component(
|
||||||
|
|
||||||
let mut model = compile_expression(&repeated.model, component);
|
let mut model = compile_expression(&repeated.model, component);
|
||||||
if repeated.is_conditional_element {
|
if repeated.is_conditional_element {
|
||||||
model = quote!((if #model {Some(())} else {None}).iter().cloned())
|
model = quote!((if #model {Some(())} else {None}))
|
||||||
}
|
}
|
||||||
|
|
||||||
if repeated.model.is_constant() {
|
if repeated.model.is_constant() {
|
||||||
init.push(quote! {
|
init.push(quote! {
|
||||||
self_pinned.#repeater_id.update_model(#model, || {
|
self_pinned.#repeater_id.update_model((#model).into_iter(), || {
|
||||||
#rep_component_id::new(self_pinned.self_weak.get().unwrap().clone())
|
#rep_component_id::new(self_pinned.self_weak.get().unwrap().clone())
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -250,12 +250,13 @@ fn generate_component(
|
||||||
repeated_visit_branch.push(quote!(
|
repeated_visit_branch.push(quote!(
|
||||||
#repeater_index => {
|
#repeater_index => {
|
||||||
if self_pinned.#model_name.is_dirty() {
|
if self_pinned.#model_name.is_dirty() {
|
||||||
#component_id::FIELD_OFFSETS.#model_name.apply_pin(self_pinned).evaluate(|| {
|
self_pinned.#repeater_id.update_model(
|
||||||
let _self = self_pinned.clone();
|
#component_id::FIELD_OFFSETS.#model_name.apply_pin(self_pinned).evaluate(|| {
|
||||||
self_pinned.#repeater_id.update_model(#model, || {
|
let _self = self_pinned.clone();
|
||||||
#rep_component_id::new(self_pinned.self_weak.get().unwrap().clone())
|
#model
|
||||||
});
|
}).into_iter(),
|
||||||
});
|
|| { #rep_component_id::new(self_pinned.self_weak.get().unwrap().clone()) }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
self_pinned.#repeater_id.visit(order, visitor)
|
self_pinned.#repeater_id.visit(order, visitor)
|
||||||
}
|
}
|
||||||
|
@ -683,7 +684,6 @@ fn compile_expression(e: &Expression, component: &Rc<Component>) -> TokenStream
|
||||||
quote!(sixtyfps::re_exports::SharedString::from(format!("{}", #f).as_str()))
|
quote!(sixtyfps::re_exports::SharedString::from(format!("{}", #f).as_str()))
|
||||||
}
|
}
|
||||||
(Type::Float32, Type::Model) | (Type::Int32, Type::Model) => quote!((0..#f as i32)),
|
(Type::Float32, Type::Model) | (Type::Int32, Type::Model) => quote!((0..#f as i32)),
|
||||||
(Type::Array(_), Type::Model) => quote!(#f.iter().cloned()),
|
|
||||||
(Type::Float32, Type::Color) => {
|
(Type::Float32, Type::Color) => {
|
||||||
quote!(sixtyfps::re_exports::Color::from_argb_encoded(#f as u32))
|
quote!(sixtyfps::re_exports::Color::from_argb_encoded(#f as u32))
|
||||||
}
|
}
|
||||||
|
@ -705,7 +705,6 @@ fn compile_expression(e: &Expression, component: &Rc<Component>) -> TokenStream
|
||||||
let window_ref = window_ref_expression(component);
|
let window_ref = window_ref_expression(component);
|
||||||
quote!(#window_ref.scale_factor())
|
quote!(#window_ref.scale_factor())
|
||||||
}
|
}
|
||||||
|
|
||||||
BuiltinFunction::Debug => {
|
BuiltinFunction::Debug => {
|
||||||
quote!(println!("FIXME: the debug statement in rust should print the argument");)
|
quote!(println!("FIXME: the debug statement in rust should print the argument");)
|
||||||
}
|
}
|
||||||
|
|
|
@ -221,32 +221,30 @@ extern "C" fn visit_children_item(
|
||||||
if let Some(listener_offset) = rep_in_comp.property_tracker {
|
if let Some(listener_offset) = rep_in_comp.property_tracker {
|
||||||
let listener = listener_offset.apply_pin(instance);
|
let listener = listener_offset.apply_pin(instance);
|
||||||
if listener.is_dirty() {
|
if listener.is_dirty() {
|
||||||
listener.evaluate(|| {
|
match listener.evaluate(|| {
|
||||||
match eval::eval_expression(
|
eval::eval_expression(
|
||||||
&rep_in_comp.model,
|
&rep_in_comp.model,
|
||||||
InstanceRef { instance, component_type },
|
InstanceRef { instance, component_type },
|
||||||
&mut Default::default(),
|
&mut Default::default(),
|
||||||
) {
|
)
|
||||||
crate::Value::Number(count) => populate_model(
|
}) {
|
||||||
&mut *vec,
|
crate::Value::Number(count) => populate_model(
|
||||||
rep_in_comp,
|
&mut *vec,
|
||||||
component,
|
rep_in_comp,
|
||||||
(0..count as i32)
|
component,
|
||||||
.into_iter()
|
(0..count as i32).into_iter().map(|v| crate::Value::Number(v as f64)),
|
||||||
.map(|v| crate::Value::Number(v as f64)),
|
),
|
||||||
),
|
crate::Value::Array(a) => {
|
||||||
crate::Value::Array(a) => {
|
populate_model(&mut *vec, rep_in_comp, component, a.into_iter())
|
||||||
populate_model(&mut *vec, rep_in_comp, component, a.into_iter())
|
|
||||||
}
|
|
||||||
crate::Value::Bool(b) => populate_model(
|
|
||||||
&mut *vec,
|
|
||||||
rep_in_comp,
|
|
||||||
component,
|
|
||||||
(if b { Some(crate::Value::Void) } else { None }).into_iter(),
|
|
||||||
),
|
|
||||||
_ => panic!("Unsupported model"),
|
|
||||||
}
|
}
|
||||||
});
|
crate::Value::Bool(b) => populate_model(
|
||||||
|
&mut *vec,
|
||||||
|
rep_in_comp,
|
||||||
|
component,
|
||||||
|
(if b { Some(crate::Value::Void) } else { None }).into_iter(),
|
||||||
|
),
|
||||||
|
_ => panic!("Unsupported model"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match order {
|
match order {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue