-
Notifications
You must be signed in to change notification settings - Fork 499
/
repeater_component.rs
135 lines (124 loc) · 5.04 KB
/
repeater_component.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// 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);
adjust_popups(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,
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);
}
}
})
});
}
fn adjust_popups(component: &Rc<Component>) {
component.popup_windows.borrow_mut().retain(|popup| {
let parent = popup
.component
.parent_element
.upgrade()
.unwrap()
.borrow()
.enclosing_component
.upgrade()
.unwrap();
if Rc::ptr_eq(&parent, component) {
return true;
}
parent.popup_windows.borrow_mut().push(popup.clone());
false
});
}