Fix Popup in C++

This commit is contained in:
Olivier Goffart 2020-12-01 10:16:41 +01:00
parent 99e66a6b55
commit 564d6a0744
4 changed files with 68 additions and 20 deletions

View file

@ -120,6 +120,13 @@ public:
sixtyfps_component_window_set_component(&inner, &self_rc); sixtyfps_component_window_set_component(&inner, &self_rc);
} }
template<typename Component, typename Parent>
void show_popup(const Parent *parent_component, cbindgen_private::Point p) const
{
auto popup = Component::create(parent_component).into_dyn();
cbindgen_private::sixtyfps_component_window_show_popup(&inner, &popup, p);
}
private: private:
cbindgen_private::ComponentWindowOpaque inner; cbindgen_private::ComponentWindowOpaque inner;
}; };
@ -215,6 +222,11 @@ public:
const T *operator->() const { return inner.operator->(); } const T *operator->() const { return inner.operator->(); }
const T &operator*() const { return inner.operator*(); } const T &operator*() const { return inner.operator*(); }
/// internal function that returns the internal handle
vtable::VRc<private_api::ComponentVTable> into_dyn() const {
return inner.into_dyn();
}
}; };
/// A weak reference to the component. Can be constructed from a `ComponentHandle<T>` /// A weak reference to the component. Can be constructed from a `ComponentHandle<T>`

View file

@ -326,12 +326,12 @@ Note: it is not allowed to access properties on element within the popup from ou
```60 ```60
Example := Window { Example := Window {
width: 270px; width: 100px;
height: 100px; height: 100px;
popup := PopupWindow { popup := PopupWindow {
Rectangle { height:100%; width: 100%; color: yellow; } Rectangle { height:100%; width: 100%; color: yellow; }
x: 20px; y: 20px; height: 50px; width: 150px; x: 20px; y: 20px; height: 50px; width: 50px;
} }
TouchArea { TouchArea {

View file

@ -640,6 +640,15 @@ fn generate_component(
let component_id = component_id(component); let component_id = component_id(component);
let mut component_struct = Struct { name: component_id.clone(), ..Default::default() }; let mut component_struct = Struct { name: component_id.clone(), ..Default::default() };
for c in component.popup_windows.borrow().iter() {
let mut friends = vec![self::component_id(&c.component)];
generate_component(file, &c.component, diag, Some(&mut friends));
if let Some(sub_components) = sub_components.as_mut() {
sub_components.extend_from_slice(friends.as_slice());
}
component_struct.friends.append(&mut friends);
}
let is_root = component.parent_element.upgrade().is_none(); let is_root = component.parent_element.upgrade().is_none();
let mut init = vec!["[[maybe_unused]] auto self = this;".into()]; let mut init = vec!["[[maybe_unused]] auto self = this;".into()];
@ -747,10 +756,8 @@ fn generate_component(
if !is_root { if !is_root {
let parent_element = component.parent_element.upgrade().unwrap(); let parent_element = component.parent_element.upgrade().unwrap();
let mut update_statements = vec![]; if parent_element.borrow().repeated.as_ref().map_or(false, |r| !r.is_conditional_element) {
let cpp_model_data_type = model_data_type(&parent_element, diag); let cpp_model_data_type = model_data_type(&parent_element, diag);
if !parent_element.borrow().repeated.as_ref().map_or(false, |r| r.is_conditional_element) {
component_struct.members.push(( component_struct.members.push((
Access::Private, Access::Private,
Declaration::Var(Var { Declaration::Var(Var {
@ -769,7 +776,29 @@ fn generate_component(
}), }),
)); ));
update_statements = vec!["index.set(i);".into(), "model_data.set(data);".into()]; let update_statements = vec!["index.set(i);".into(), "model_data.set(data);".into()];
component_struct.members.push((
Access::Public, // Because Repeater accesses it
Declaration::Function(Function {
name: "update_data".into(),
signature: format!(
"(int i, const {} &data) const -> void",
cpp_model_data_type
),
statements: Some(update_statements),
..Function::default()
}),
));
} else if parent_element.borrow().repeated.is_some() {
component_struct.members.push((
Access::Public, // Because Repeater accesses it
Declaration::Function(Function {
name: "update_data".into(),
signature: "(int, int) const -> void".into(),
statements: Some(vec![]),
..Function::default()
}),
));
} }
let parent_component_id = self::component_id( let parent_component_id = self::component_id(
&component &component
@ -793,18 +822,6 @@ fn generate_component(
}), }),
)); ));
component_struct.friends.push(parent_component_id); component_struct.friends.push(parent_component_id);
component_struct.members.push((
Access::Public, // Because Repeater accesses it
Declaration::Function(Function {
name: "update_data".into(),
signature: format!(
"([[maybe_unused]] int i, [[maybe_unused]] const {} &data) const -> void",
cpp_model_data_type
),
statements: Some(update_statements),
..Function::default()
}),
));
let p_y = access_member(&component.root_element, "y", component, "this"); let p_y = access_member(&component.root_element, "y", component, "this");
let p_height = access_member(&component.root_element, "height", component, "this"); let p_height = access_member(&component.root_element, "height", component, "this");
@ -829,7 +846,7 @@ fn generate_component(
..Function::default() ..Function::default()
}), }),
)); ));
} else { } else if parent_element.borrow().repeated.is_some() {
let p_x = access_member(&component.root_element, "x", component, "this"); let p_x = access_member(&component.root_element, "x", component, "this");
component_struct.members.push(( component_struct.members.push((
Access::Public, // Because Repeater accesses it Access::Public, // Because Repeater accesses it
@ -1409,6 +1426,24 @@ fn compile_expression(e: &crate::expression_tree::Expression, component: &Rc<Com
panic!("internal error: argument to SetFocusItem must be an element") panic!("internal error: argument to SetFocusItem must be an element")
} }
} }
Expression::BuiltinFunctionReference(BuiltinFunction::ShowPopupWindow) => {
if arguments.len() != 1 {
panic!("internal error: incorrect argument count to SetFocusItem call");
}
if let Expression::ElementReference(popup_window) = &arguments[0] {
let popup_window = popup_window.upgrade().unwrap();
let pop_comp = popup_window.borrow().enclosing_component.upgrade().unwrap();
let popup_window_id = component_id(&pop_comp);
let parent_component = pop_comp.parent_element.upgrade().unwrap().borrow().enclosing_component.upgrade().unwrap();
let popup_list = parent_component.popup_windows.borrow();
let popup = popup_list.iter().find(|p| Rc::ptr_eq(&p.component, &pop_comp)).unwrap();
let x = access_named_reference(&popup.x, component, "self");
let y = access_named_reference(&popup.y, component, "self");
format!("self->window.show_popup<{}>(self, {{ {}.get(), {}.get() }} );", popup_window_id, x, y)
} else {
panic!("internal error: argument to SetFocusItem must be an element")
}
}
_ => { _ => {
let mut args = arguments.iter().map(|e| compile_expression(e, component)); let mut args = arguments.iter().map(|e| compile_expression(e, component));

View file

@ -155,6 +155,7 @@ fn gen_corelib(include_dir: &Path) -> anyhow::Result<()> {
"sixtyfps_component_window_free_graphics_resources", "sixtyfps_component_window_free_graphics_resources",
"sixtyfps_component_window_set_focus_item", "sixtyfps_component_window_set_focus_item",
"sixtyfps_component_window_set_component", "sixtyfps_component_window_set_component",
"sixtyfps_component_window_show_popup",
"sixtyfps_new_path_elements", "sixtyfps_new_path_elements",
"sixtyfps_new_path_events", "sixtyfps_new_path_events",
] ]