rustty/ui/
layout.rs

1use core::position::{Pos, Size, HasSize, HasPosition};
2
3pub enum VerticalAlign {
4    Top,
5    Middle,
6    Bottom,
7}
8
9pub enum HorizontalAlign {
10    Left,
11    Middle,
12    Right,
13}
14
15pub trait Alignable: HasSize + HasPosition {
16    fn halign(&mut self, parent: &HasSize, halign: HorizontalAlign, margin: usize) {
17        let (cols, _) = self.size();
18        let (_, y) = self.origin();
19        let (parent_cols, _) = parent.size();
20        let newx = match halign {
21            HorizontalAlign::Left => margin,
22            HorizontalAlign::Right => parent_cols - cols - margin,
23            HorizontalAlign::Middle => (parent_cols - cols) / 2,
24        };
25        self.set_origin((newx, y));
26    }
27
28    fn valign(&mut self, parent: &HasSize, valign: VerticalAlign, margin: usize) {
29        let (_, rows) = self.size();
30        let (x, _) = self.origin();
31        let (_, parent_rows) = parent.size();
32        let newy = match valign {
33            VerticalAlign::Top => margin,
34            VerticalAlign::Bottom => parent_rows - rows - margin,
35            VerticalAlign::Middle => (parent_rows - rows) / 2,
36        };
37        self.set_origin((x, newy));
38    }
39
40    fn align(&mut self,
41             parent: &HasSize,
42             halign: HorizontalAlign,
43             valign: VerticalAlign,
44             margin: usize) {
45        self.halign(parent, halign, margin);
46        self.valign(parent, valign, margin);
47    }
48}
49
50pub struct HorizontalLayout<'a> {
51    origin: Pos,
52    size: Size,
53    inner_margin: usize,
54    elems: Vec<&'a mut Alignable>,
55}
56
57impl<'a> HorizontalLayout<'a> {
58    pub fn new(elems: Vec<&mut Alignable>, inner_margin: usize) -> HorizontalLayout {
59        let first_origin = elems.first().unwrap().origin();
60        let total_width = elems.iter().fold(0, |acc, item| acc + item.size().0);
61        let width = total_width + inner_margin * (elems.len() - 1);
62        HorizontalLayout {
63            origin: first_origin,
64            size: (width, 1),
65            inner_margin: inner_margin,
66            elems: elems,
67        }
68    }
69
70    pub fn align_elems(&mut self) {
71        let (x, y) = self.origin();
72        let mut current_x = x;
73        for elem in self.elems.iter_mut() {
74            elem.set_origin((current_x, y));
75            current_x += elem.size().0 + self.inner_margin;
76        }
77    }
78}
79
80impl<'a> HasSize for HorizontalLayout<'a> {
81    fn size(&self) -> Size {
82        self.size
83    }
84}
85
86impl<'a> HasPosition for HorizontalLayout<'a> {
87    fn origin(&self) -> Pos {
88        self.origin
89    }
90
91    fn set_origin(&mut self, new_origin: Pos) {
92        self.origin = new_origin;
93    }
94}
95
96impl<'a> Alignable for HorizontalLayout<'a> {}