i_slint_compiler/passes/
optimize_useless_rectangles.rs1use crate::langtype::ElementType;
10use crate::object_tree::*;
11use std::rc::Rc;
12
13pub fn optimize_useless_rectangles(root_component: &Rc<Component>) {
14 recurse_elem_including_sub_components(root_component, &(), &mut |parent_, _| {
15 let mut parent = parent_.borrow_mut();
16 let children = std::mem::take(&mut parent.children);
17
18 for elem in children {
19 if !can_optimize(&elem) {
20 parent.children.push(elem);
21 continue;
22 }
23
24 parent.children.extend(std::mem::take(&mut elem.borrow_mut().children));
25 if let Some(last) = parent.debug.last_mut() {
26 last.element_boundary = true;
27 }
28 parent.debug.extend(std::mem::take(&mut elem.borrow_mut().debug));
29
30 let enclosing = parent.enclosing_component.upgrade().unwrap();
31
32 for popup in enclosing.popup_windows.borrow_mut().iter_mut() {
33 if Rc::ptr_eq(&popup.parent_element, &elem) {
34 popup.parent_element = parent_.clone();
36 }
37 }
38
39 enclosing.optimized_elements.borrow_mut().push(elem);
40 }
41 });
42}
43
44fn can_optimize(elem: &ElementRc) -> bool {
46 let element = elem.borrow();
47 if element.is_flickable_content || element.has_popup_child || element.is_component_placeholder {
48 return false;
49 };
50
51 if element.child_of_layout {
52 return false;
54 }
55
56 let base_type = match &element.base_type {
57 ElementType::Builtin(base_type) if base_type.name == "Rectangle" => base_type,
58 ElementType::Builtin(base_type) if base_type.native_class.class_name == "Empty" => {
59 base_type
60 }
61 _ => return false,
62 };
63
64 if element.z_order.is_some() || element.has_dynamic_z_order() {
67 return false;
68 }
69
70 let analysis = element.property_analysis.borrow();
71 for coord in ["x", "y"] {
72 if element.binding(coord).is_some() || analysis.get(coord).is_some_and(|a| a.is_set) {
73 return false;
74 }
75 }
76 if analysis.get("absolute-position").is_some_and(|a| a.is_read) {
77 return false;
78 }
79
80 !element
82 .real_bindings()
83 .map(|(property_name, _)| property_name)
84 .chain(analysis.iter().filter(|(_, v)| v.is_set).map(|(k, _)| k))
85 .any(|property_name| {
86 !element.property_declarations.contains_key(property_name.as_str())
87 && base_type.properties.contains_key(property_name.as_str())
88 })
89 && element.accessibility_props.0.is_empty()
90}