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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
use super::types::*;
use super::bounds::*;
use super::modifier::*;
use super::attributes::*;
use super::super::diff::*;
use super::super::binding_canvas::*;
use super::super::resource_manager::*;
use ControlType::*;
use ControlAttribute::*;
///
/// Represents a control
///
#[derive(Clone, PartialEq, Debug)]
pub struct Control {
/// Attributes for this control
attributes: Vec<ControlAttribute>,
/// Type of this control
control_type: ControlType
}
impl Control {
/// Creates a new control of a particular type
pub fn new(control_type: ControlType) -> Control {
Control { attributes: vec![], control_type: control_type }
}
/// Creates a new container control
pub fn container() -> Control {
Self::new(Container)
}
/// Creates a new cropping container control
pub fn cropping_container() -> Control {
Self::new(CroppingContainer)
}
/// Creates a new scrolling container control
pub fn scrolling_container() -> Control {
Self::new(ScrollingContainer)
}
/// Creates a new popup control
pub fn popup() -> Control {
Self::new(Popup)
}
/// Creates a new button control
pub fn button() -> Control {
Self::new(Button)
}
/// Creates a new label control
pub fn label() -> Control {
Self::new(Label)
}
/// Create a new empty control
pub fn empty() -> Control {
Self::new(Empty)
}
/// Creates a new canvas control
pub fn canvas() -> Control {
Self::new(ControlType::Canvas)
}
/// Creates a new slider control
pub fn slider() -> Control {
Self::new(ControlType::Slider)
}
/// Creates a new rotor control
pub fn rotor() -> Control {
Self::new(ControlType::Rotor)
}
/// Adds an attribute to this control
pub fn add_attribute(&mut self, attribute: ControlAttribute) {
self.attributes.push(attribute);
}
/// Creates a control with some attributes added to it
pub fn with<T: ControlModifier>(mut self, modifier: T) -> Control {
modifier.modify(&mut self);
self
}
///
/// Creates a control with an added controller
///
pub fn with_controller(self, controller: &str) -> Control {
self.with(ControlAttribute::Controller(String::from(controller)))
}
/// Returns an iterator over the attributes for this control
pub fn attributes<'a>(&'a self) -> Box<Iterator<Item=&'a ControlAttribute>+'a> {
Box::new(self.attributes.iter())
}
/// The type of this control
pub fn control_type(&self) -> ControlType {
self.control_type
}
///
/// True if any of the attributes of this control exactly match the specified attribute
/// (using the rules of is_different_flat, so no recursion when there are subcomponents)
///
pub fn has_attribute_flat(&self, attr: &ControlAttribute) -> bool {
self.attributes.iter()
.any(|test_attr| !test_attr.is_different_flat(attr))
}
///
/// If this control has a controller attribute, finds it
///
pub fn controller<'a>(&'a self) -> Option<&'a str> {
self.attributes.iter()
.map(|attr| attr.controller())
.find(|attr| attr.is_some())
.map(|attr| attr.unwrap())
}
///
/// If this control has a controller attribute, finds it
///
pub fn subcomponents<'a>(&'a self) -> Option<&'a Vec<Control>> {
self.attributes.iter()
.map(|attr| attr.subcomponents())
.find(|attr| attr.is_some())
.map(|attr| attr.unwrap())
}
///
/// Finds the bounding box for this control if it exists
///
pub fn bounding_box<'a>(&'a self) -> Option<&'a Bounds> {
self.attributes.iter()
.map(|attr| attr.bounding_box())
.find(|attr| attr.is_some())
.map(|attr| attr.unwrap())
}
///
/// If this control has a canvas attribute, finds it
///
pub fn canvas_resource<'a>(&'a self) -> Option<&Resource<BindingCanvas>> {
self.attributes.iter()
.map(|attr| attr.canvas())
.find(|attr| attr.is_some())
.map(|attr| attr.unwrap())
}
///
/// Finds the names of all of the controllers referenced by this control and its subcontrols
///
pub fn all_controllers(&self) -> Vec<String> {
let mut result = vec![];
fn all_controllers(ctrl: &Control, result: &mut Vec<String>) {
// Push the controller to the result if there is one
if let Some(controller_name) = ctrl.controller() {
result.push(String::from(controller_name));
}
// Go through the subcomponents as well
if let Some(subcomponents) = ctrl.subcomponents() {
for subcomponent in subcomponents.iter() {
all_controllers(subcomponent, result);
}
}
}
all_controllers(self, &mut result);
// Remove duplicate controllers
result.sort();
result.dedup();
result
}
///
/// Visits the control tree and performs a mapping function on each item
///
pub fn map<TFn: Fn(&Control) -> Control>(&self, map_fn: &TFn) -> Control {
// Map this control
let mut new_control = map_fn(self);
// Map any subcomponents that might exist
let num_attributes = new_control.attributes.len();
for index in 0..num_attributes {
// TODO: we really only want to update the attribute if
// it's a subcomponents attribute but we end up with an
// awkward code structure as there's no elegant way to
// release the borrow caused by the subcomponents ref in
// the if statement here before updating the value. This
// construction looks better but clones all the attributes
// to leave them unupdated
new_control.attributes[index] =
if let SubComponents(ref subcomponents) = new_control.attributes[index] {
// Map each of the subcomponents
let mut new_subcomponents = vec![];
for component in subcomponents.iter() {
new_subcomponents.push(component.map(map_fn));
}
ControlAttribute::SubComponents(new_subcomponents)
} else {
// Attribute remains the same
new_control.attributes[index].clone()
};
}
new_control
}
}
impl DiffableTree for Control {
fn child_nodes<'a>(&'a self) -> Vec<&'a Self> {
self.attributes
.iter()
.map(|attr| attr.subcomponents().map(|component| component.iter()))
.filter(|maybe_components| maybe_components.is_some())
.flat_map(|components| components.unwrap())
.collect()
}
fn is_different(&self, compare_to: &Self) -> bool {
self.control_type() != compare_to.control_type()
|| self.attributes.iter().any(|attr| !compare_to.has_attribute_flat(attr))
}
}