mirror of
https://github.com/slint-ui/slint.git
synced 2025-09-29 05:14:48 +00:00

* Make sure that the compiler don't panic if the parent of a PopupWindow is optimized (by not optiizing such element) * Ensure that we can call popup.show() from within a deeper repeater * Ensure that the parent element of the popup is the right one in case of repeater (and not the node in the parent component) This partially revertad5991f8fa
and6c7a7aed0e
because we must do the lower_popup adter the repeater pass, because otherwise the parent element of the created component for the PopupWindow might be wrong and it is not easy to adjust (we would have to make Component::parent_element a RefCell or duplicate it again. Fixes #1132
116 lines
4.6 KiB
Rust
116 lines
4.6 KiB
Rust
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
|
|
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
|
|
|
|
/*!
|
|
Make sure that the Repeated expression are just components without any children
|
|
*/
|
|
|
|
use crate::expression_tree::{Expression, NamedReference};
|
|
use crate::langtype::Type;
|
|
use crate::object_tree::*;
|
|
use std::cell::RefCell;
|
|
use std::rc::Rc;
|
|
|
|
pub fn process_repeater_components(component: &Rc<Component>) {
|
|
create_repeater_components(component);
|
|
adjust_references(component);
|
|
}
|
|
|
|
fn create_repeater_components(component: &Rc<Component>) {
|
|
recurse_elem(&component.root_element, &(), &mut |elem, _| {
|
|
let is_listview = match &elem.borrow().repeated {
|
|
Some(r) => r.is_listview.clone(),
|
|
None => return,
|
|
};
|
|
let parent_element = Rc::downgrade(elem);
|
|
let mut elem = elem.borrow_mut();
|
|
|
|
let comp = Rc::new(Component {
|
|
root_element: Rc::new(RefCell::new(Element {
|
|
id: elem.id.clone(),
|
|
base_type: std::mem::take(&mut elem.base_type),
|
|
bindings: std::mem::take(&mut elem.bindings),
|
|
property_analysis: std::mem::take(&mut elem.property_analysis),
|
|
children: std::mem::take(&mut elem.children),
|
|
property_declarations: std::mem::take(&mut elem.property_declarations),
|
|
named_references: Default::default(),
|
|
repeated: None,
|
|
node: elem.node.clone(),
|
|
enclosing_component: Default::default(),
|
|
states: std::mem::take(&mut elem.states),
|
|
transitions: std::mem::take(&mut elem.transitions),
|
|
child_of_layout: elem.child_of_layout || is_listview.is_some(),
|
|
layout_info_prop: elem.layout_info_prop.take(),
|
|
is_flickable_viewport: elem.is_flickable_viewport,
|
|
has_popup_child: elem.has_popup_child,
|
|
item_index: Default::default(), // Not determined yet
|
|
item_index_of_first_children: Default::default(),
|
|
inline_depth: 0,
|
|
})),
|
|
parent_element,
|
|
..Component::default()
|
|
});
|
|
|
|
if let Some(listview) = is_listview {
|
|
if !comp.root_element.borrow().is_binding_set("height", false) {
|
|
let preferred = Expression::PropertyReference(NamedReference::new(
|
|
&comp.root_element,
|
|
"preferred-height",
|
|
));
|
|
comp.root_element
|
|
.borrow_mut()
|
|
.bindings
|
|
.insert("height".into(), RefCell::new(preferred.into()));
|
|
}
|
|
if !comp.root_element.borrow().is_binding_set("width", false) {
|
|
comp.root_element.borrow_mut().bindings.insert(
|
|
"width".into(),
|
|
RefCell::new(Expression::PropertyReference(listview.listview_width).into()),
|
|
);
|
|
}
|
|
|
|
NamedReference::new(&comp.root_element, "y").mark_as_set();
|
|
}
|
|
|
|
let weak = Rc::downgrade(&comp);
|
|
recurse_elem(&comp.root_element, &(), &mut |e, _| {
|
|
e.borrow_mut().enclosing_component = weak.clone()
|
|
});
|
|
create_repeater_components(&comp);
|
|
elem.base_type = Type::Component(comp);
|
|
});
|
|
|
|
for p in component.popup_windows.borrow().iter() {
|
|
create_repeater_components(&p.component);
|
|
}
|
|
}
|
|
|
|
/// Make sure that references to property within the repeated element actually point to the reference
|
|
/// to the root of the newly created component
|
|
fn adjust_references(comp: &Rc<Component>) {
|
|
visit_all_named_references(comp, &mut |nr| {
|
|
if nr.name() == "$model" {
|
|
return;
|
|
}
|
|
let e = nr.element();
|
|
if e.borrow().repeated.is_some() {
|
|
if let Type::Component(c) = e.borrow().base_type.clone() {
|
|
*nr = NamedReference::new(&c.root_element, nr.name())
|
|
};
|
|
}
|
|
});
|
|
// Transform any references to the repeated element to refer to the root of each instance.
|
|
visit_all_expressions(comp, |expr, _| {
|
|
expr.visit_recursive_mut(&mut |expr| {
|
|
if let Expression::ElementReference(ref mut element_ref) = expr {
|
|
if let Some(repeater_element) =
|
|
element_ref.upgrade().filter(|e| e.borrow().repeated.is_some())
|
|
{
|
|
let inner_element =
|
|
repeater_element.borrow().base_type.as_component().root_element.clone();
|
|
*element_ref = Rc::downgrade(&inner_element);
|
|
}
|
|
}
|
|
})
|
|
});
|
|
}
|