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); const auto &x = data.at(i);
return { &C::component_type, x.get() }; return { &C::component_type, x.get() };
} }
void compute_layout() const {
for (auto &x : data) {
x->compute_layout({ &C::component_type, x.get() });
}
}
}; };
Flickable::Flickable() Flickable::Flickable()

View file

@ -81,4 +81,11 @@ where
pub fn borrow_item_vec(&self) -> core::cell::Ref<Vec<Pin<Rc<C>>>> { pub fn borrow_item_vec(&self) -> core::cell::Ref<Vec<Pin<Rc<C>>>> {
self.components.borrow() 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>, init: &mut Vec<String>,
children_visitor_cases: &mut Vec<String>, children_visitor_cases: &mut Vec<String>,
repeated_input_branch: &mut Vec<String>, repeated_input_branch: &mut Vec<String>,
layout_repeater_code: &mut Vec<String>,
diag: &mut BuildDiagnostics, diag: &mut BuildDiagnostics,
) { ) {
let parent_element = base_component.parent_element.upgrade().unwrap(); let parent_element = base_component.parent_element.upgrade().unwrap();
@ -420,6 +421,7 @@ fn handle_repeater(
i = repeater_count, i = repeater_count,
id = repeater_id, id = repeater_id,
)); ));
layout_repeater_code.push(format!("self->{}.compute_layout();", repeater_id));
component_struct.members.push(( component_struct.members.push((
Access::Private, Access::Private,
@ -659,6 +661,7 @@ fn generate_component(
let mut children_visitor_cases = vec![]; let mut children_visitor_cases = vec![];
let mut repeated_input_branch = vec![]; let mut repeated_input_branch = vec![];
let mut repeater_layout_code = vec![];
let mut tree_array = vec![]; let mut tree_array = vec![];
let mut repeater_count = 0; let mut repeater_count = 0;
super::build_array_helper(component, |item_rc, children_offset, is_flickable_rect| { super::build_array_helper(component, |item_rc, children_offset, is_flickable_rect| {
@ -691,6 +694,7 @@ fn generate_component(
&mut init, &mut init,
&mut children_visitor_cases, &mut children_visitor_cases,
&mut repeated_input_branch, &mut repeated_input_branch,
&mut repeater_layout_code,
diag, diag,
); );
repeater_count += 1; repeater_count += 1;
@ -807,7 +811,7 @@ fn generate_component(
name: "compute_layout".into(), name: "compute_layout".into(),
signature: "(sixtyfps::private_api::ComponentRef component) -> void".into(), signature: "(sixtyfps::private_api::ComponentRef component) -> void".into(),
is_static: true, is_static: true,
statements: Some(compute_layout(component)), statements: Some(compute_layout(component, &mut repeater_layout_code)),
..Default::default() ..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![]; let mut res = vec![];
res.push(format!( res.push(format!(
@ -1440,6 +1447,8 @@ fn compute_layout(component: &Rc<Component>) -> Vec<String> {
res.push(" }".into()); res.push(" }".into());
}); });
res.append(repeater_layout_code);
res res
} }

View file

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

View file

@ -1059,6 +1059,15 @@ extern "C" fn compute_layout(component: ComponentRefPin) {
layout.solve(instance_ref); 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 /// 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
*/