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:
Olivier Goffart 2020-09-04 15:35:49 +02:00
parent c8fa3354be
commit f5aeb9ba60
4 changed files with 44 additions and 42 deletions

View file

@ -124,7 +124,7 @@ struct PropertyTracker
}
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(
&inner,
[](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:
cbindgen_private::PropertyTrackerOpaque inner;
};

View file

@ -373,13 +373,11 @@ fn handle_repeater(
let repeater_id =
format!("repeater_{}", base_component.parent_element.upgrade().unwrap().borrow().id);
let model = compile_expression(&repeated.model, parent_component);
let model = if !repeated.is_conditional_element {
format!("{}.get()", model)
} else {
let mut model = compile_expression(&repeated.model, parent_component);
if repeated.is_conditional_element {
// bool converts to int
// 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() {
@ -389,7 +387,7 @@ fn handle_repeater(
i = repeater_count
));
init.push(format!(
"self->{repeater_id}.update_model({model}, self);",
"self->{repeater_id}.update_model({model}.get(), self);",
repeater_id = repeater_id,
model = model,
));
@ -406,9 +404,9 @@ fn handle_repeater(
children_visitor_cases.push(format!(
"\n case {i}: {{
if (self->model_{i}.is_dirty()) {{
self->model_{i}.evaluate([&] {{
self->{id}.update_model({model}, self);
}});
self->{id}.update_model(self->model_{i}.evaluate([&] {{
return {model};
}}).get(), self);
}}
return self->{id}.visit(order, visitor);
}}",

View file

@ -233,12 +233,12 @@ fn generate_component(
let mut model = compile_expression(&repeated.model, component);
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() {
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())
});
});
@ -250,12 +250,13 @@ fn generate_component(
repeated_visit_branch.push(quote!(
#repeater_index => {
if self_pinned.#model_name.is_dirty() {
self_pinned.#repeater_id.update_model(
#component_id::FIELD_OFFSETS.#model_name.apply_pin(self_pinned).evaluate(|| {
let _self = self_pinned.clone();
self_pinned.#repeater_id.update_model(#model, || {
#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)
}
@ -683,7 +684,6 @@ fn compile_expression(e: &Expression, component: &Rc<Component>) -> TokenStream
quote!(sixtyfps::re_exports::SharedString::from(format!("{}", #f).as_str()))
}
(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) => {
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);
quote!(#window_ref.scale_factor())
}
BuiltinFunction::Debug => {
quote!(println!("FIXME: the debug statement in rust should print the argument");)
}

View file

@ -221,19 +221,18 @@ extern "C" fn visit_children_item(
if let Some(listener_offset) = rep_in_comp.property_tracker {
let listener = listener_offset.apply_pin(instance);
if listener.is_dirty() {
listener.evaluate(|| {
match eval::eval_expression(
match listener.evaluate(|| {
eval::eval_expression(
&rep_in_comp.model,
InstanceRef { instance, component_type },
&mut Default::default(),
) {
)
}) {
crate::Value::Number(count) => populate_model(
&mut *vec,
rep_in_comp,
component,
(0..count as i32)
.into_iter()
.map(|v| crate::Value::Number(v as f64)),
(0..count as i32).into_iter().map(|v| crate::Value::Number(v as f64)),
),
crate::Value::Array(a) => {
populate_model(&mut *vec, rep_in_comp, component, a.into_iter())
@ -246,7 +245,6 @@ extern "C" fn visit_children_item(
),
_ => panic!("Unsupported model"),
}
});
}
}
match order {