1use qualia::{Area, Direction, Position, Vector, Size, SurfaceAccess, SurfaceId};
9
10use frame::{Frame, Geometry, Mobility, Mode, Side};
11use searching::Searching;
12use packing::Packing;
13
14pub trait Settling {
18 fn settle(&mut self, target: &mut Frame, area: Option<Area>, sa: &mut SurfaceAccess);
22
23 fn resettle(&mut self, target: &mut Frame, position: Option<Position>, sa: &mut SurfaceAccess);
27
28 fn pop_recursively(&mut self, pop: &mut Frame);
32
33 fn change_geometry(&mut self, geometry: Geometry, sa: &mut SurfaceAccess);
35
36 fn ramify(&mut self, geometry: Geometry) -> Frame;
48
49 fn deramify(&mut self);
51
52 fn jumpin(&mut self, side: Side, target: &mut Frame, sa: &mut SurfaceAccess);
54
55 fn jump(&mut self, side: Side, target: &mut Frame, sa: &mut SurfaceAccess);
57
58 fn dock(&mut self, target: &mut Frame, size: Size, sa: &mut SurfaceAccess);
60
61 fn anchorize(&mut self, sa: &mut SurfaceAccess);
63
64 fn deanchorize(&mut self, area: Area, sa: &mut SurfaceAccess);
67
68 fn resize(&mut self, direction: Direction, magnitude: isize, sa: &mut SurfaceAccess);
71
72 fn move_with_contents(&mut self, vector: Vector);
74
75 fn destroy_self(&mut self, sa: &mut SurfaceAccess);
77}
78
79impl Settling for Frame {
82 fn settle(&mut self, target: &mut Frame, area: Option<Area>, sa: &mut SurfaceAccess) {
83 if let Some(ref mut buildable) = target.find_buildable() {
84 if buildable.get_geometry() == Geometry::Stacked {
85 buildable.prepend(self);
86 if let Some(area) = area {
87 self.set_plumbing_mobility(Mobility::Floating);
88 self.set_size(area.size, sa);
89 self.set_plumbing_position(area.pos);
90 } else {
91 self.set_plumbing_mobility(Mobility::Anchored);
92 }
93 } else {
94 buildable.append(self);
95 self.set_plumbing_mobility(Mobility::Anchored);
96 }
97 buildable.relax(sa);
98 }
99 }
100
101 fn resettle(&mut self, target: &mut Frame, position: Option<Position>, sa: &mut SurfaceAccess) {
102 let area = {
103 if self.get_mobility().is_floating() && target.get_mode().is_workspace() {
105 let mut area = self.get_area();
106 if let Some(position) = position {
107 area.pos = position;
108 }
109 Some(area)
110 } else {
111 None
112 }
113 };
114 self.remove_self(sa);
115 self.settle(target, area, sa);
116 }
117
118 fn pop_recursively(&mut self, pop: &mut Frame) {
119 if self.equals_exact(pop) {
121 return;
122 }
123
124 if let Some(ref mut parent) = pop.get_parent() {
126 if parent.get_geometry() == Geometry::Stacked {
128 pop.remove();
129 parent.prepend(pop);
130 }
131
132 pop.pop();
134
135 self.pop_recursively(parent);
137 }
138 }
139
140 fn change_geometry(&mut self, geometry: Geometry, sa: &mut SurfaceAccess) {
141 self.set_plumbing_geometry(geometry);
142 self.homogenize(sa);
143 }
144
145 fn ramify(&mut self, geometry: Geometry) -> Frame {
146 if !self.is_top() {
147 let parent = self.get_parent().expect("should have parent");
148 if self.count_children() == 1 {
149 return self.clone();
150 }
151 if parent.count_children() == 1 {
152 return parent;
153 }
154 }
155
156 let (distancer_mobility, distancer_mode) = if self.is_top() {
157 (self.get_mobility(), self.get_mode())
158 } else {
159 (Mobility::Anchored, Mode::Container)
160 };
161
162 let frame_mode = if self.get_mode().is_leaf() {
163 self.get_mode()
164 } else {
165 Mode::Container
166 };
167
168 let mut distancer = Frame::new(SurfaceId::invalid(),
169 geometry,
170 distancer_mobility,
171 distancer_mode,
172 self.get_position(),
173 self.get_size(),
174 self.get_title());
175 self.prejoin(&mut distancer);
176 self.remove();
177 self.set_plumbing_mobility(Mobility::Anchored);
178 self.set_plumbing_mode(frame_mode);
179 self.set_plumbing_position(Position::default());
180 distancer.prepend(self);
181 distancer
182 }
183
184 fn deramify(&mut self) {
185 let len = self.count_children();
186 if len == 1 {
187 let mut first = self.get_first_time().expect("should have exactly one child");
188 let len = first.count_children();
189 if len == 1 {
190 let mut second = first.get_first_time().expect("should have exactly one child");
191 first.remove();
192 second.remove();
193 self.prepend(&mut second);
194 first.destroy();
195 } else if len == 0 {
196 self.set_plumbing_mode(first.get_mode());
197 self.set_plumbing_sid(first.get_sid());
198 first.remove();
199 first.destroy();
200 }
201 }
202 }
203
204 fn jumpin(&mut self, side: Side, target: &mut Frame, sa: &mut SurfaceAccess) {
205 if let Some(mut target_parent) = target.get_parent() {
206 match side {
207 Side::Before => {
208 target.prejoin(self);
209 target_parent.relax(sa);
210 }
211 Side::After => {
212 target.adjoin(self);
213 target_parent.relax(sa);
214 }
215 Side::On => {
216 let mut new_target = {
217 if !target_parent.is_top() &&
218 target_parent.count_children() == 1 {
219 target_parent.clone()
220 } else if target.get_mode().is_leaf() {
221 target.ramify(Geometry::Stacked)
222 } else {
223 target.clone()
224 }
225 };
226
227 self.settle(&mut new_target, None, sa);
228 }
229 }
230 }
231 }
232
233 fn jump(&mut self, side: Side, target: &mut Frame, sa: &mut SurfaceAccess) {
234 self.remove_self(sa);
235 self.jumpin(side, target, sa);
236 }
237
238 fn dock(&mut self, target: &mut Frame, size: Size, sa: &mut SurfaceAccess) {
239 target.set_plumbing_geometry(Geometry::Vertical);
240 self.set_plumbing_mobility(Mobility::Docked);
241 self.set_plumbing_size(size);
242 self.set_plumbing_position(Position::default());
243 target.prepend(self);
244 target.relax(sa);
245 }
246
247 fn anchorize(&mut self, sa: &mut SurfaceAccess) {
248 if self.is_reanchorizable() && self.get_mobility().is_floating() {
249 let parent = self.get_parent().expect("should have parent");
251 self.set_size(parent.get_size(), sa);
252 self.set_plumbing_position(Position::default());
253 self.set_plumbing_mobility(Mobility::Anchored);
254 }
255 }
256
257 fn deanchorize(&mut self, area: Area, sa: &mut SurfaceAccess) {
258 if self.is_reanchorizable() && self.get_mobility().is_anchored() {
259 let mut workspace = self.find_top().expect("should have toplevel");
260 let parent = self.get_parent().expect("should have parent");
261 if !parent.equals_exact(&workspace) {
262 self.remove_self(sa);
263 workspace.prepend(self);
264 }
265 self.set_size(area.size, sa);
266 self.set_plumbing_position(area.pos);
267 self.set_plumbing_mobility(Mobility::Floating);
268 }
269 }
270
271 fn resize(&mut self, direction: Direction, magnitude: isize, sa: &mut SurfaceAccess) {
272 if direction.is_planar() && !self.is_top() {
273 match self.get_mobility() {
274 Mobility::Floating => {
275 let move_vector = {
276 if direction == Direction::North {
277 Vector::new(0, -magnitude)
278 } else if direction == Direction::West {
279 Vector::new(-magnitude, 0)
280 } else {
281 Vector::new(0, 0)
282 }
283 };
284
285 let resize_vector = {
286 if direction == Direction::North || direction == Direction::South {
287 Vector::new(0, magnitude)
288 } else if direction == Direction::West || direction == Direction::East {
289 Vector::new(magnitude, 0)
290 } else {
291 Vector::new(0, 0)
292 }
293 };
294
295 let new_size = self.get_size().sized(resize_vector);
296 self.set_size(new_size, sa);
297 self.move_with_contents(move_vector);
298 }
299 Mobility::Anchored => {
300 if let Some(neighbour) = self.find_neighbouring(direction) {
301 if neighbour.get_mobility().is_anchored() {
302 let (mut first, mut second) = {
303 if direction == Direction::North || direction == Direction::West {
304 (neighbour.clone(), self.clone())
305 } else {
306 (self.clone(), neighbour.clone())
307 }
308 };
309
310 let (move_vector, resize_vector) = {
311 if direction == Direction::North {
312 (Vector::new(0, -magnitude), Vector::new(0, magnitude))
313 } else if direction == Direction::East {
314 (Vector::new(magnitude, 0), Vector::new(-magnitude, 0))
315 } else if direction == Direction::South {
316 (Vector::new(0, magnitude), Vector::new(0, -magnitude))
317 } else if direction == Direction::West {
318 (Vector::new(-magnitude, 0), Vector::new(magnitude, 0))
319 } else {
320 (Vector::new(0, 0), Vector::new(0, 0))
321 }
322 };
323
324 first.change_size(resize_vector.opposite(), sa);
325 second.change_size(resize_vector, sa);
326 second.move_with_contents(move_vector);
327 }
328 } else if let Some(mut parent) = self.get_parent() {
329 parent.resize(direction, magnitude, sa);
330 }
331 }
332 Mobility::Docked => {
333 }
335 }
336 }
337 }
338
339 fn move_with_contents(&mut self, vector: Vector) {
340 let new_position = self.get_position() + vector.clone();
342 self.set_plumbing_position(new_position);
343 }
344
345 fn destroy_self(&mut self, sa: &mut SurfaceAccess) {
346 self.remove_self(sa);
347 self.destroy();
348 }
349}
350
351