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}