Actually compute the layout of elements within a for loop

This commit is contained in:
Olivier Goffart 2020-09-07 14:04:14 +02:00
parent d924ec6bd9
commit 16f5cf42e3
6 changed files with 69 additions and 5 deletions

View file

@ -249,6 +249,12 @@ struct Repeater
const auto &x = data.at(i);
return { &C::component_type, x.get() };
}
void compute_layout() const {
for (auto &x : data) {
x->compute_layout({ &C::component_type, x.get() });
}
}
};
Flickable::Flickable()

View file

@ -81,4 +81,11 @@ where
pub fn borrow_item_vec(&self) -> core::cell::Ref<Vec<Pin<Rc<C>>>> {
self.components.borrow()
}
/// Recompute the layout of each chile elements
pub fn compute_layout(&self) {
for c in self.components.borrow().iter() {
c.as_ref().compute_layout();
}
}
}

View file

@ -367,6 +367,7 @@ fn handle_repeater(
init: &mut Vec<String>,
children_visitor_cases: &mut Vec<String>,
repeated_input_branch: &mut Vec<String>,
layout_repeater_code: &mut Vec<String>,
diag: &mut BuildDiagnostics,
) {
let parent_element = base_component.parent_element.upgrade().unwrap();
@ -420,6 +421,7 @@ fn handle_repeater(
i = repeater_count,
id = repeater_id,
));
layout_repeater_code.push(format!("self->{}.compute_layout();", repeater_id));
component_struct.members.push((
Access::Private,
@ -659,6 +661,7 @@ fn generate_component(
let mut children_visitor_cases = vec![];
let mut repeated_input_branch = vec![];
let mut repeater_layout_code = vec![];
let mut tree_array = vec![];
let mut repeater_count = 0;
super::build_array_helper(component, |item_rc, children_offset, is_flickable_rect| {
@ -691,6 +694,7 @@ fn generate_component(
&mut init,
&mut children_visitor_cases,
&mut repeated_input_branch,
&mut repeater_layout_code,
diag,
);
repeater_count += 1;
@ -807,7 +811,7 @@ fn generate_component(
name: "compute_layout".into(),
signature: "(sixtyfps::private_api::ComponentRef component) -> void".into(),
is_static: true,
statements: Some(compute_layout(component)),
statements: Some(compute_layout(component, &mut repeater_layout_code)),
..Default::default()
}),
));
@ -1415,7 +1419,10 @@ impl<'a> LayoutTreeItem<'a> {
}
}
fn compute_layout(component: &Rc<Component>) -> Vec<String> {
fn compute_layout(
component: &Rc<Component>,
repeater_layout_code: &mut Vec<String>,
) -> Vec<String> {
let mut res = vec![];
res.push(format!(
@ -1440,6 +1447,8 @@ fn compute_layout(component: &Rc<Component>) -> Vec<String> {
res.push(" }".into());
});
res.append(repeater_layout_code);
res
}

View file

@ -17,7 +17,7 @@ use crate::expression_tree::{
use crate::layout::{gen::LayoutItemCodeGen, Layout, LayoutElement};
use crate::object_tree::{Component, ElementRc};
use crate::typeregister::Type;
use proc_macro2::TokenStream;
use proc_macro2::{Ident, TokenStream};
use quote::quote;
use std::rc::Rc;
@ -352,7 +352,7 @@ fn generate_component(
Vec::new()
};
let layouts = compute_layout(component);
let layouts = compute_layout(component, &repeated_element_names);
let mut visibility = None;
let mut parent_component_type = None;
if let Some(parent_element) = component.parent_element.upgrade() {
@ -1183,7 +1183,7 @@ impl<'a> LayoutTreeItem<'a> {
}
}
fn compute_layout(component: &Rc<Component>) -> TokenStream {
fn compute_layout(component: &Rc<Component>, repeated_element_names: &[Ident]) -> TokenStream {
let mut layouts = vec![];
component.layout_constraints.borrow().iter().for_each(|layout| {
let mut inverse_layout_tree = Vec::new();
@ -1212,6 +1212,8 @@ fn compute_layout(component: &Rc<Component>) -> TokenStream {
let _self = self;
#(#layouts)*
#(self.#repeated_element_names.compute_layout();)*
}
}
}

View file

@ -1059,6 +1059,15 @@ extern "C" fn compute_layout(component: ComponentRefPin) {
layout.solve(instance_ref);
});
});
for rep_in_comp in &instance_ref.component_type.repeater {
generativity::make_guard!(guard);
let rep_in_comp = rep_in_comp.unerase(guard);
let vec = rep_in_comp.offset.apply(instance_ref.as_ref()).borrow();
for c in vec.iter() {
c.borrow().as_ref().compute_layout();
}
}
}
/// Get the component description from a ComponentRef

View file

@ -34,3 +34,34 @@ TestCase := Rectangle {
}
}
}
/*
```cpp
TestCase instance;
TestCase::compute_layout({&TestCase::component_type, &instance });
sixtyfps::testing::send_mouse_click(instance, 190., 190.);
assert(instance.get_value() == 1+1);
sixtyfps::testing::send_mouse_click(instance, 5., 290.);
assert(instance.get_value() == 1+1+2);
```
```rust
let instance = TestCase::new();
let instance = instance.as_ref();
use sixtyfps::re_exports::Component;
instance.compute_layout();
sixtyfps::testing::send_mouse_click(instance, 190., 190.);
assert_eq!(instance.get_value(), 1+1);
sixtyfps::testing::send_mouse_click(instance, 5., 290.);
assert_eq!(instance.get_value(), 1+1+2);
```
// FIXME: JS test because layout are not computed
*/