mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-01 06:11:16 +00:00
Cpp: Give each generated component a ComponentWindow
That's a counted reference to the window in the run-time and avoids the need to do the parent->parent->window dance.
This commit is contained in:
parent
f9ced44188
commit
54ee7b3556
4 changed files with 45 additions and 30 deletions
|
@ -77,7 +77,10 @@ class ComponentWindow
|
||||||
public:
|
public:
|
||||||
ComponentWindow() { cbindgen_private::sixtyfps_component_window_init(&inner); }
|
ComponentWindow() { cbindgen_private::sixtyfps_component_window_init(&inner); }
|
||||||
~ComponentWindow() { cbindgen_private::sixtyfps_component_window_drop(&inner); }
|
~ComponentWindow() { cbindgen_private::sixtyfps_component_window_drop(&inner); }
|
||||||
ComponentWindow(const ComponentWindow &) = delete;
|
ComponentWindow(const ComponentWindow &other)
|
||||||
|
{
|
||||||
|
cbindgen_private::sixtyfps_component_window_clone(&other.inner, &inner);
|
||||||
|
}
|
||||||
ComponentWindow(ComponentWindow &&) = delete;
|
ComponentWindow(ComponentWindow &&) = delete;
|
||||||
ComponentWindow &operator=(const ComponentWindow &) = delete;
|
ComponentWindow &operator=(const ComponentWindow &) = delete;
|
||||||
|
|
||||||
|
|
|
@ -111,6 +111,7 @@ mod cpp_ast {
|
||||||
is_friend: false,
|
is_friend: false,
|
||||||
statements: f.statements.take(),
|
statements: f.statements.take(),
|
||||||
template_parameters: f.template_parameters.clone(),
|
template_parameters: f.template_parameters.clone(),
|
||||||
|
constructor_member_initializers: f.constructor_member_initializers.clone(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -133,6 +134,8 @@ mod cpp_ast {
|
||||||
pub statements: Option<Vec<String>>,
|
pub statements: Option<Vec<String>>,
|
||||||
/// What's inside template<...> if any
|
/// What's inside template<...> if any
|
||||||
pub template_parameters: Option<String>,
|
pub template_parameters: Option<String>,
|
||||||
|
/// Explicit initializers, such as FooClass::FooClass() : someMember(42) {}
|
||||||
|
pub constructor_member_initializers: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Function {
|
impl Display for Function {
|
||||||
|
@ -154,6 +157,9 @@ mod cpp_ast {
|
||||||
}
|
}
|
||||||
write!(f, "{} {}", self.name, self.signature)?;
|
write!(f, "{} {}", self.name, self.signature)?;
|
||||||
if let Some(st) = &self.statements {
|
if let Some(st) = &self.statements {
|
||||||
|
if !self.constructor_member_initializers.is_empty() {
|
||||||
|
writeln!(f, "\n : {}", self.constructor_member_initializers.join(","))?;
|
||||||
|
}
|
||||||
writeln!(f, "{{")?;
|
writeln!(f, "{{")?;
|
||||||
for s in st {
|
for s in st {
|
||||||
indent(f)?;
|
indent(f)?;
|
||||||
|
@ -821,6 +827,14 @@ fn generate_component(
|
||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
component_struct.members.push((
|
||||||
|
Access::Private,
|
||||||
|
Declaration::Var(Var {
|
||||||
|
ty: "sixtyfps::private_api::ComponentWindow".into(),
|
||||||
|
name: "window".into(),
|
||||||
|
..Var::default()
|
||||||
|
}),
|
||||||
|
));
|
||||||
} else if !component.is_global() {
|
} else if !component.is_global() {
|
||||||
component_struct.members.push((
|
component_struct.members.push((
|
||||||
Access::Public, // FIXME: many of the different component bindings need to access this
|
Access::Public, // FIXME: many of the different component bindings need to access this
|
||||||
|
@ -853,10 +867,7 @@ fn generate_component(
|
||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
|
|
||||||
init.push(format!(
|
init.push("self->window.init_items(this, item_tree());".into());
|
||||||
"{}.init_items(this, item_tree());",
|
|
||||||
window = window_ref_expression(component)
|
|
||||||
));
|
|
||||||
|
|
||||||
component_struct.friends.push("sixtyfps::private_api::ComponentWindow".into());
|
component_struct.friends.push("sixtyfps::private_api::ComponentWindow".into());
|
||||||
|
|
||||||
|
@ -952,6 +963,11 @@ fn generate_component(
|
||||||
signature: format!("({})", constructor_parent_arg),
|
signature: format!("({})", constructor_parent_arg),
|
||||||
is_constructor_or_destructor: true,
|
is_constructor_or_destructor: true,
|
||||||
statements: Some(init),
|
statements: Some(init),
|
||||||
|
constructor_member_initializers: if !component.is_global() && !is_root {
|
||||||
|
vec!["window(parent->window)".into()]
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
|
@ -963,10 +979,7 @@ fn generate_component(
|
||||||
if component.parent_element.upgrade().is_some() {
|
if component.parent_element.upgrade().is_some() {
|
||||||
destructor.push("if (!parent) return;".to_owned())
|
destructor.push("if (!parent) return;".to_owned())
|
||||||
}
|
}
|
||||||
destructor.push(format!(
|
destructor.push("self->window.free_graphics_resources(this);".into());
|
||||||
"{window}.free_graphics_resources(this);",
|
|
||||||
window = window_ref_expression(component)
|
|
||||||
));
|
|
||||||
|
|
||||||
component_struct.members.push((
|
component_struct.members.push((
|
||||||
Access::Public,
|
Access::Public,
|
||||||
|
@ -1276,17 +1289,6 @@ fn access_named_reference(
|
||||||
access_member(&nr.element.upgrade().unwrap(), &nr.name, component, component_cpp)
|
access_member(&nr.element.upgrade().unwrap(), &nr.name, component, component_cpp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return an expression that gets the window
|
|
||||||
fn window_ref_expression(component: &Rc<Component>) -> String {
|
|
||||||
let mut root_component = component.clone();
|
|
||||||
let mut component_cpp = "self".to_owned();
|
|
||||||
while let Some(p) = root_component.parent_element.upgrade() {
|
|
||||||
root_component = p.borrow().enclosing_component.upgrade().unwrap();
|
|
||||||
component_cpp = format!("{}->parent", component_cpp);
|
|
||||||
}
|
|
||||||
format!("{}->window", component_cpp)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn compile_expression(e: &crate::expression_tree::Expression, component: &Rc<Component>) -> String {
|
fn compile_expression(e: &crate::expression_tree::Expression, component: &Rc<Component>) -> String {
|
||||||
match e {
|
match e {
|
||||||
Expression::StringLiteral(s) => {
|
Expression::StringLiteral(s) => {
|
||||||
|
@ -1305,7 +1307,7 @@ fn compile_expression(e: &crate::expression_tree::Expression, component: &Rc<Com
|
||||||
),
|
),
|
||||||
Expression::BuiltinFunctionReference(funcref) => match funcref {
|
Expression::BuiltinFunctionReference(funcref) => match funcref {
|
||||||
BuiltinFunction::GetWindowScaleFactor => {
|
BuiltinFunction::GetWindowScaleFactor => {
|
||||||
format!("{}.scale_factor", window_ref_expression(component))
|
"self->window.scale_factor".into()
|
||||||
}
|
}
|
||||||
BuiltinFunction::Debug => {
|
BuiltinFunction::Debug => {
|
||||||
"[](auto... args){ (std::cout << ... << args) << std::endl; return nullptr; }"
|
"[](auto... args){ (std::cout << ... << args) << std::endl; return nullptr; }"
|
||||||
|
@ -1316,7 +1318,7 @@ fn compile_expression(e: &crate::expression_tree::Expression, component: &Rc<Com
|
||||||
BuiltinFunction::Ceil => "[](float a){ return std::ceil(a); }".into(),
|
BuiltinFunction::Ceil => "[](float a){ return std::ceil(a); }".into(),
|
||||||
BuiltinFunction::Floor => "[](float a){ return std::floor(a); }".into(),
|
BuiltinFunction::Floor => "[](float a){ return std::floor(a); }".into(),
|
||||||
BuiltinFunction::SetFocusItem => {
|
BuiltinFunction::SetFocusItem => {
|
||||||
format!("{}.set_focus_item", window_ref_expression(component))
|
"self->window.set_focus_item".into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* std::from_chars is unfortunately not yet implemented in gcc
|
/* std::from_chars is unfortunately not yet implemented in gcc
|
||||||
|
@ -1418,7 +1420,6 @@ fn compile_expression(e: &crate::expression_tree::Expression, component: &Rc<Com
|
||||||
if let Expression::ElementReference(focus_item) = &arguments[0] {
|
if let Expression::ElementReference(focus_item) = &arguments[0] {
|
||||||
let focus_item = focus_item.upgrade().unwrap();
|
let focus_item = focus_item.upgrade().unwrap();
|
||||||
let focus_item = focus_item.borrow();
|
let focus_item = focus_item.borrow();
|
||||||
let window_ref = window_ref_expression(component);
|
|
||||||
let component =
|
let component =
|
||||||
format!("{{&{}::component_type, this}}", component_id(component));
|
format!("{{&{}::component_type, this}}", component_id(component));
|
||||||
let item = format!(
|
let item = format!(
|
||||||
|
@ -1426,7 +1427,7 @@ fn compile_expression(e: &crate::expression_tree::Expression, component: &Rc<Com
|
||||||
vt = focus_item.base_type.as_native().vtable_symbol,
|
vt = focus_item.base_type.as_native().vtable_symbol,
|
||||||
item = focus_item.id
|
item = focus_item.id
|
||||||
);
|
);
|
||||||
format!("{}.set_focus_item({}, {});", window_ref, component, item)
|
format!("self->window.set_focus_item({}, {});", component, item)
|
||||||
} else {
|
} else {
|
||||||
panic!("internal error: argument to SetFocusItem must be an element")
|
panic!("internal error: argument to SetFocusItem must be an element")
|
||||||
}
|
}
|
||||||
|
@ -1809,11 +1810,10 @@ fn get_layout_info_ref<'a, 'b>(
|
||||||
});
|
});
|
||||||
let elem_info = item.element.as_ref().map(|elem| {
|
let elem_info = item.element.as_ref().map(|elem| {
|
||||||
format!(
|
format!(
|
||||||
"sixtyfps::private_api::{vt}.layouting_info({{&sixtyfps::private_api::{vt}, const_cast<sixtyfps::{ty}*>(&self->{id})}}, &{window})",
|
"sixtyfps::private_api::{vt}.layouting_info({{&sixtyfps::private_api::{vt}, const_cast<sixtyfps::{ty}*>(&self->{id})}}, &self->window)",
|
||||||
vt = elem.borrow().base_type.as_native().vtable_symbol,
|
vt = elem.borrow().base_type.as_native().vtable_symbol,
|
||||||
ty = elem.borrow().base_type.as_native().class_name,
|
ty = elem.borrow().base_type.as_native().class_name,
|
||||||
id = elem.borrow().id,
|
id = elem.borrow().id,
|
||||||
window = window_ref_expression(component)
|
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let mut layout_info = match (layout_info, elem_info) {
|
let mut layout_info = match (layout_info, elem_info) {
|
||||||
|
@ -2052,10 +2052,7 @@ fn compute_layout(
|
||||||
let mut res = vec![intro.clone()];
|
let mut res = vec![intro.clone()];
|
||||||
let mut layout_info = vec![
|
let mut layout_info = vec![
|
||||||
intro.clone(),
|
intro.clone(),
|
||||||
format!(
|
"return self->root_item().vtable->layouting_info(self->root_item(), &self->window);".into(),
|
||||||
"return self->root_item().vtable->layouting_info(self->root_item(), &{});",
|
|
||||||
window_ref_expression(component)
|
|
||||||
),
|
|
||||||
];
|
];
|
||||||
let component_layouts = component.layouts.borrow();
|
let component_layouts = component.layouts.borrow();
|
||||||
component_layouts.iter().enumerate().for_each(|(idx, layout)| {
|
component_layouts.iter().enumerate().for_each(|(idx, layout)| {
|
||||||
|
|
|
@ -553,6 +553,20 @@ pub mod ffi {
|
||||||
core::ptr::read(handle as *mut ComponentWindow);
|
core::ptr::read(handle as *mut ComponentWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Releases the reference to the component window held by handle.
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn sixtyfps_component_window_clone(
|
||||||
|
source: *const ComponentWindowOpaque,
|
||||||
|
target: *mut ComponentWindowOpaque,
|
||||||
|
) {
|
||||||
|
assert_eq!(
|
||||||
|
core::mem::size_of::<ComponentWindow>(),
|
||||||
|
core::mem::size_of::<ComponentWindowOpaque>()
|
||||||
|
);
|
||||||
|
let window = &*(source as *const ComponentWindow);
|
||||||
|
core::ptr::write(target as *mut ComponentWindow, window.clone());
|
||||||
|
}
|
||||||
|
|
||||||
/// Spins an event loop and renders the items of the provided component in this window.
|
/// Spins an event loop and renders the items of the provided component in this window.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn sixtyfps_component_window_run(handle: *const ComponentWindowOpaque) {
|
pub unsafe extern "C" fn sixtyfps_component_window_run(handle: *const ComponentWindowOpaque) {
|
||||||
|
|
|
@ -139,6 +139,7 @@ fn gen_corelib(include_dir: &Path) -> anyhow::Result<()> {
|
||||||
special_config.export.exclude = [
|
special_config.export.exclude = [
|
||||||
"sixtyfps_visit_item_tree",
|
"sixtyfps_visit_item_tree",
|
||||||
"sixtyfps_component_window_drop",
|
"sixtyfps_component_window_drop",
|
||||||
|
"sixtyfps_component_window_clone",
|
||||||
"sixtyfps_component_window_run",
|
"sixtyfps_component_window_run",
|
||||||
"sixtyfps_component_window_get_scale_factor",
|
"sixtyfps_component_window_get_scale_factor",
|
||||||
"sixtyfps_component_window_set_scale_factor",
|
"sixtyfps_component_window_set_scale_factor",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue