rustty_oxide/
vlayout.rs

1use rustty::{Size, Pos, HasSize, HasPosition};
2use rustty::CellAccessor;
3use std::boxed::Box;
4use std::collections::HashMap;
5use core::{
6    Layout, 
7    Alignable, 
8    HorizontalAlign,
9    VerticalAlign, 
10    Widget, 
11    Frame, 
12    Button,
13    Painter,
14    ButtonResult
15};
16
17/// Hold buttons and align them vertically for drawing within a 
18/// [Dialog](struct.Dialog.html)
19///
20/// # Examples
21///
22/// ```
23/// use oxide::core::{HorizontalAlign, VerticalAlign, ButtonResult, Button, Widget};
24/// use oxide::{Dialog, StdButton, VerticalLayout};
25///
26/// let mut maindlg = Dialog::new(60, 10);
27///
28/// let b1 = StdButton::new("Quit", 'q', ButtonResult::Ok);
29/// let b2 = StdButton::new("Foo!", 'f', ButtonResult::Custom(1));
30/// let b3 = StdButton::new("Bar!", 'b', ButtonResult::Custom(2));
31///
32/// let buttons = vec![b1, b2, b3].into_iter().map(Box::new);
33/// let buttons = buttons.map(|x| x as Box<Button>).collect();
34///
35/// let mut vlayout = VerticalLayout::from_vec(buttons, 1);
36/// vlayout.pack(&maindlg, HorizontalAlign::Middle, VerticalAlign::Bottom, (0,1));
37///     
38/// maindlg.add_layout(vlayout);
39/// ```
40///
41pub struct VerticalLayout {
42    frame: Frame,
43    inner_margin: usize,
44    origin: Pos,
45    widgets: Vec<Box<Button>>
46}
47
48impl VerticalLayout {
49    /// Construct a `VerticalLayout` object from a vector of boxed objects that implement
50    /// [Button](ui/core/button/trait.Button.html). The current API for this function will
51    /// change *very* soon
52    ///
53    /// # Examples
54    ///
55    /// ```
56    /// use oxide::core::{Button, ButtonResult};
57    /// use oxide::{StdButton, VerticalLayout};
58    ///
59    /// let b1 = StdButton::new("Quit", 'q', ButtonResult::Ok);
60    /// let b2 = StdButton::new("Foo!", 'f', ButtonResult::Custom(1));
61    /// let b3 = StdButton::new("Bar!", 'b', ButtonResult::Custom(2));
62    ///
63    /// let v = vec![b1, b2, b3].into_iter().map(Box::new).map(|x| x as Box<Button>).collect();
64    /// let mut hlayout = VerticalLayout::from_vec(v, 1);
65    /// ```
66    ///
67    pub fn from_vec(widgets: Vec<Box<Button>>, inner_margin: usize) -> VerticalLayout {
68        let first_origin = widgets.first().unwrap().frame().origin();
69        let height = widgets.len() + widgets.len() * inner_margin;
70        let width = widgets.iter().map(|s| s.frame().size().0).max().unwrap();
71        VerticalLayout {
72            frame: Frame::new(width, height),
73            inner_margin: inner_margin,
74            origin: first_origin,
75            widgets: widgets
76        }
77    }
78
79}
80
81impl Widget for VerticalLayout {
82    fn draw(&mut self, parent: &mut CellAccessor) { 
83        self.frame.draw_into(parent);
84    }
85
86    fn pack(&mut self, parent: &HasSize, halign: HorizontalAlign, valign: VerticalAlign,
87                margin: (usize, usize)) {
88        self.frame.align(parent, halign, valign, margin);
89    }
90
91    fn draw_box(&mut self) {
92        self.frame.draw_box();
93    }
94
95    fn resize(&mut self, new_size: Size) {
96        self.frame.resize(new_size);
97    }
98
99    fn frame(&self) -> &Frame {
100        &self.frame
101    }
102
103    fn frame_mut(&mut self) -> &mut Frame {
104        &mut self.frame
105    }
106}
107
108impl Layout for VerticalLayout {
109    fn align_elems(&mut self) {
110        let (x, y) = self.origin;
111        let mut current_y = y;
112        for widget in self.widgets.iter_mut() {
113            widget.frame_mut().set_origin((x, current_y));
114            current_y += 1 + self.inner_margin;
115        }
116        for w in self.widgets.iter() {
117            w.frame().draw_into(&mut self.frame);
118        }
119    }
120
121    fn forward_keys(&mut self, map: &mut HashMap<char, ButtonResult>) {
122       for w in self.widgets.iter() {
123            map.insert(w.accel(), w.result());
124       }
125    }
126}