cognitive_frames/
packing.rs

1// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
2// the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/
3
4//! This module contains extra settling functionality for `frames::Frame`.
5
6// -------------------------------------------------------------------------------------------------
7
8use qualia::{Position, Size, Vector};
9use qualia::{SurfaceAccess, surface_state};
10
11use frame::{Frame, Geometry, Mobility};
12
13// -------------------------------------------------------------------------------------------------
14
15/// Extension trait for `Frame` adding more packing functionality.
16pub trait Packing {
17    /// TODO: Implement relaxing. Currently relaxing is equivalent to homogenizing.
18    fn relax(&mut self, sa: &mut SurfaceAccess);
19
20    /// Make all subsurfaces have the same size and proper layout.
21    /// Homogenizing works only on directed frames.
22    fn homogenize(&mut self, sa: &mut SurfaceAccess);
23
24    /// Set size of the frame and resize its subframe accordingly.
25    fn change_size(&mut self, vactor: Vector, sa: &mut SurfaceAccess);
26
27    /// Set size of the frame and resize its subframe accordingly.
28    fn set_size(&mut self, size: Size, sa: &mut SurfaceAccess);
29
30    /// Remove given frame and relax old parent.
31    fn remove_self(&mut self, sa: &mut SurfaceAccess);
32}
33
34// -------------------------------------------------------------------------------------------------
35
36impl Packing for Frame {
37    fn relax(&mut self, sa: &mut SurfaceAccess) {
38        self.homogenize(sa);
39    }
40
41    fn homogenize(&mut self, sa: &mut SurfaceAccess) {
42        let len = self.count_anchored_children();
43        if len < 1 {
44            return;
45        }
46
47        // Decide how to resize and move twigs
48        let mut size = Size::new(0, 0);
49        let mut increment = Vector::new(0, 0);
50        match self.get_geometry() {
51            Geometry::Stacked => {
52                size = self.get_size();
53            }
54            Geometry::Vertical => {
55                let mut docked_height = 0;
56                for frame in self.space_iter() {
57                    if frame.get_mobility().is_docked() {
58                        docked_height += frame.get_size().height;
59                    }
60                }
61                size.width = self.get_size().width;
62                size.height = (self.get_size().height - docked_height) / len;
63                increment.y = size.height as isize;
64            }
65            Geometry::Horizontal => {
66                let mut docked_width = 0;
67                for frame in self.space_iter() {
68                    if frame.get_mobility().is_docked() {
69                        docked_width += frame.get_size().width;
70                    }
71                }
72                size.height = self.get_size().height;
73                size.width = (self.get_size().width - docked_width) / len;
74                increment.x = size.width as isize;
75            }
76        }
77
78        // Resize and reposition all subframes recursively
79        let mut pos = Position::default();
80        for mut frame in self.space_iter() {
81            match frame.get_mobility() {
82                Mobility::Anchored => {
83                    frame.set_size(size, sa);
84                    frame.set_plumbing_position(pos);
85                    pos = pos + increment;
86                }
87                Mobility::Docked => {
88                    match self.get_geometry() {
89                        Geometry::Stacked => {}
90                        Geometry::Vertical => pos.y += frame.get_size().height as isize,
91                        Geometry::Horizontal => pos.x += frame.get_size().width as isize,
92                    }
93                }
94                Mobility::Floating => {}
95            }
96        }
97    }
98
99    fn change_size(&mut self, vector: Vector, sa: &mut SurfaceAccess) {
100        let size = self.get_size().sized(vector);
101        self.set_size(size, sa);
102    }
103
104    fn set_size(&mut self, size: Size, sa: &mut SurfaceAccess) {
105        // Set size for given frame.
106        let old_size = self.get_size();
107        self.set_plumbing_size(size.clone());
108        sa.reconfigure(self.get_sid(), size.clone(), surface_state::MAXIMIZED);
109
110        // Set size to frames children.
111        match self.get_geometry() {
112            Geometry::Horizontal => {
113                if old_size.width == size.width {
114                    for mut frame in self.space_iter() {
115                        let mut frame_size = frame.get_size();
116                        frame_size.height = size.height;
117                        frame.set_size(frame_size, sa);
118                    }
119                } else {
120                    self.relax(sa);
121                }
122            }
123            Geometry::Vertical => {
124                if old_size.height == size.height {
125                    for mut frame in self.space_iter() {
126                        let mut frame_size = frame.get_size();
127                        frame_size.width = size.width;
128                        frame.set_size(frame_size, sa);
129                    }
130                } else {
131                    self.relax(sa);
132                }
133            }
134            Geometry::Stacked => {
135                for mut frame in self.space_iter() {
136                    if !frame.get_mobility().is_floating() {
137                        frame.set_size(size.clone(), sa);
138                    }
139                }
140            }
141        }
142    }
143
144    fn remove_self(&mut self, sa: &mut SurfaceAccess) {
145        if let Some(ref mut parent) = self.get_parent() {
146            self.remove();
147            let len = parent.count_children();
148            if len == 0 && !parent.is_top() {
149                parent.remove_self(sa);
150            } else {
151                parent.relax(sa);
152            }
153        }
154    }
155}
156
157// -------------------------------------------------------------------------------------------------