Fix calls to BuiltinFunction::ImplicitLayoutInfo for sub-components in C++

Provide a layout_info implementation for sub-components and call it. This
disables the lowering the implicit_layout_info call again,
also to ensure that when this
is installed from the use-site of the sub-component, the self can be used to obtain
the info (by calling the new generated function).
This commit is contained in:
Simon Hausmann 2021-10-28 21:47:37 +02:00
parent 08c49a5ff4
commit ae25dd3d07
3 changed files with 85 additions and 29 deletions

View file

@ -751,8 +751,7 @@ fn generate_component(
let mut component_struct = Struct { name: component_id.clone(), ..Default::default() }; let mut component_struct = Struct { name: component_id.clone(), ..Default::default() };
let is_child_component = component.parent_element.upgrade().is_some(); let is_child_component = component.parent_element.upgrade().is_some();
let is_sub_component = let is_sub_component = component.is_sub_component();
!component.is_root_component.get() && !is_child_component && !component.is_global();
for c in component.popup_windows.borrow().iter() { for c in component.popup_windows.borrow().iter() {
let mut friends = vec![self::component_id(&c.component)]; let mut friends = vec![self::component_id(&c.component)];
@ -1339,6 +1338,22 @@ fn generate_component(
..Default::default() ..Default::default()
}), }),
)); ));
component_struct.members.push((
Access::Public,
Declaration::Function(Function {
name: "layout_info".into(),
signature:
"(sixtyfps::Orientation o, sixtyfps::private_api::WindowRc *window_handle) -> sixtyfps::LayoutInfo"
.into(),
statements: Some(layout_info_function_body(
&component,
"auto self = this;".to_owned(),
Some("window_handle"),
)),
..Default::default()
}),
));
} }
let used_types = component.used_types.borrow(); let used_types = component.used_types.borrow();
@ -1497,13 +1512,10 @@ fn generate_component_vtable(
"([[maybe_unused]] sixtyfps::private_api::ComponentRef component, sixtyfps::Orientation o) -> sixtyfps::LayoutInfo" "([[maybe_unused]] sixtyfps::private_api::ComponentRef component, sixtyfps::Orientation o) -> sixtyfps::LayoutInfo"
.into(), .into(),
is_static: true, is_static: true,
statements: Some(vec![ statements: Some(layout_info_function_body(&component, format!(
format!("[[maybe_unused]] auto self = reinterpret_cast<const {}*>(component.instance);", component_id), "[[maybe_unused]] auto self = reinterpret_cast<const {}*>(component.instance);",
format!("if (o == sixtyfps::Orientation::Horizontal) return {};", component_id
get_layout_info(&component.root_element, component, &component.root_constraints.borrow(), Orientation::Horizontal)), ), None)),
format!("else return {};",
get_layout_info(&component.root_element, component, &component.root_constraints.borrow(), Orientation::Vertical))
]),
..Default::default() ..Default::default()
}), }),
)); ));
@ -1896,13 +1908,20 @@ fn compile_expression(
if let Expression::ElementReference(item) = &arguments[0] { if let Expression::ElementReference(item) = &arguments[0] {
let item = item.upgrade().unwrap(); let item = item.upgrade().unwrap();
let item = item.borrow(); let item = item.borrow();
let native_item = item.base_type.as_native(); if item.sub_component().is_some() {
format!("{vt}->layouting_info({{{vt}, const_cast<sixtyfps::cbindgen_private::{ty}*>(&self->{id})}}, {o}, &m_window.window_handle())", format!("self->{compo}.layout_info({o}, &m_window.window_handle())",
vt = native_item.cpp_vtable_getter, compo = ident(&item.id),
ty = native_item.class_name, o = to_cpp_orientation(*orientation)
id = ident(&item.id), )
o = to_cpp_orientation(*orientation), } else {
) let native_item = item.base_type.as_native();
format!("{vt}->layouting_info({{{vt}, const_cast<sixtyfps::cbindgen_private::{ty}*>(&self->{id})}}, {o}, &m_window.window_handle())",
vt = native_item.cpp_vtable_getter,
ty = native_item.class_name,
id = ident(&item.id),
o = to_cpp_orientation(*orientation),
)
}
} else { } else {
panic!("internal error: argument to ImplicitLayoutInfo must be an element") panic!("internal error: argument to ImplicitLayoutInfo must be an element")
} }
@ -2252,7 +2271,7 @@ fn grid_layout_cell_data(
"sixtyfps::GridLayoutCellData {{ {}, {}, {} }}", "sixtyfps::GridLayoutCellData {{ {}, {}, {} }}",
col_or_row, col_or_row,
span, span,
get_layout_info(&c.item.element, component, &c.item.constraints, orientation), get_layout_info(&c.item.element, component, &c.item.constraints, orientation, None),
) )
}) })
.join(", ") .join(", ")
@ -2279,7 +2298,7 @@ fn box_layout_data(
let mut cells = layout.elems.iter().map(|li| { let mut cells = layout.elems.iter().map(|li| {
format!( format!(
"sixtyfps::BoxLayoutCellData{{ {} }}", "sixtyfps::BoxLayoutCellData{{ {} }}",
get_layout_info(&li.element, component, &li.constraints, orientation) get_layout_info(&li.element, component, &li.constraints, orientation, None)
) )
}); });
if let Some((ri, _)) = &mut repeated_indices { if let Some((ri, _)) = &mut repeated_indices {
@ -2320,7 +2339,7 @@ fn box_layout_data(
} else { } else {
push_code += &format!( push_code += &format!(
"cells.push_back({{ {} }});", "cells.push_back({{ {} }});",
get_layout_info(&item.element, component, &item.constraints, orientation) get_layout_info(&item.element, component, &item.constraints, orientation, None)
); );
} }
} }
@ -2362,24 +2381,32 @@ fn get_layout_info(
component: &Rc<Component>, component: &Rc<Component>,
constraints: &crate::layout::LayoutConstraints, constraints: &crate::layout::LayoutConstraints,
orientation: Orientation, orientation: Orientation,
custom_window_handle_accessor: Option<&'_ str>,
) -> String { ) -> String {
let window_handle = if let Some(custom_accessor) = custom_window_handle_accessor {
custom_accessor
} else {
"&self->m_window.window_handle()"
};
let mut layout_info = if let Some(layout_info_prop) = let mut layout_info = if let Some(layout_info_prop) =
&elem.borrow().layout_info_prop(orientation) &elem.borrow().layout_info_prop(orientation)
{ {
format!("{}.get()", access_named_reference(layout_info_prop, component, "self")) format!("{}.get()", access_named_reference(layout_info_prop, component, "self"))
} else if let Type::Component(_sub_component) = &elem.borrow().base_type { } else if elem.borrow().sub_component().is_some() {
format!( format!(
"self->{id}.layouting_info({o}, &self->m_window.window_handle())", "self->{id}.layout_info({o}, {window_handle})",
id = ident(&elem.borrow().id), id = ident(&elem.borrow().id),
o = to_cpp_orientation(orientation), o = to_cpp_orientation(orientation),
window_handle = window_handle
) )
} else { } else {
format!( format!(
"{vt}->layouting_info({{{vt}, const_cast<sixtyfps::cbindgen_private::{ty}*>(&self->{id})}}, {o}, &self->m_window.window_handle())", "{vt}->layouting_info({{{vt}, const_cast<sixtyfps::cbindgen_private::{ty}*>(&self->{id})}}, {o}, {window_handle})",
vt = elem.borrow().base_type.as_native().cpp_vtable_getter, vt = elem.borrow().base_type.as_native().cpp_vtable_getter,
ty = elem.borrow().base_type.as_native().class_name, ty = elem.borrow().base_type.as_native().class_name,
id = ident(&elem.borrow().id), id = ident(&elem.borrow().id),
o = to_cpp_orientation(orientation), o = to_cpp_orientation(orientation),
window_handle = window_handle
) )
}; };
@ -2397,6 +2424,36 @@ fn get_layout_info(
layout_info layout_info
} }
fn layout_info_function_body(
component: &Rc<Component>,
self_accessor: String,
custom_window_accessor: Option<&'_ str>,
) -> Vec<String> {
vec![
self_accessor,
format!(
"if (o == sixtyfps::Orientation::Horizontal) return {};",
get_layout_info(
&component.root_element,
component,
&component.root_constraints.borrow(),
Orientation::Horizontal,
custom_window_accessor
)
),
format!(
"else return {};",
get_layout_info(
&component.root_element,
component,
&component.root_constraints.borrow(),
Orientation::Vertical,
custom_window_accessor
)
),
]
}
fn compile_path(path: &crate::expression_tree::Path, component: &Rc<Component>) -> String { fn compile_path(path: &crate::expression_tree::Path, component: &Rc<Component>) -> String {
match path { match path {
crate::expression_tree::Path::Elements(elements) => { crate::expression_tree::Path::Elements(elements) => {

View file

@ -482,13 +482,6 @@ pub fn layout_info_type() -> Type {
/// Get the implicit layout info of a particular element /// Get the implicit layout info of a particular element
pub fn implicit_layout_info_call(elem: &ElementRc, orientation: Orientation) -> Expression { pub fn implicit_layout_info_call(elem: &ElementRc, orientation: Orientation) -> Expression {
match &elem.borrow().base_type { match &elem.borrow().base_type {
Type::Component(base_comp) => match &base_comp.root_element.borrow().layout_info_prop {
Some((hor, vert)) => Expression::PropertyReference(match orientation {
Orientation::Horizontal => hor.clone(),
Orientation::Vertical => vert.clone(),
}),
None => implicit_layout_info_call(&base_comp.root_element, orientation),
},
Type::Builtin(base_type) if base_type.name == "Rectangle" => { Type::Builtin(base_type) if base_type.name == "Rectangle" => {
// hard-code the value for rectangle because many rectangle end up optimized away and we // hard-code the value for rectangle because many rectangle end up optimized away and we
// don't want to depend on the element. // don't want to depend on the element.

View file

@ -293,6 +293,12 @@ impl Component {
.map(|name| name.original_name()) .map(|name| name.original_name())
.collect() .collect()
} }
pub fn is_sub_component(&self) -> bool {
!self.is_root_component.get()
&& self.parent_element.upgrade().is_none()
&& !self.is_global()
}
} }
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]