rustty_oxide/hlayout.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 horizontally for drawing within a
18/// [Dialog](struct.Dialog.html)
19///
20/// # Examples
21///
22/// ```
23/// use oxide::core::{HorizontalAlign, VerticalAlign, ButtonResult, Widget, Button};
24/// use oxide::ui::{Dialog, StdButton, HorizontalLayout};
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 hlayout = HorizontalLayout::from_vec(buttons, 1);
36/// hlayout.pack(&maindlg, HorizontalAlign::Middle, VerticalAlign::Bottom, (0,1));
37///
38/// maindlg.add_layout(hlayout);
39/// ```
40///
41pub struct HorizontalLayout {
42 frame: Frame,
43 inner_margin: usize,
44 origin: Pos,
45 widgets: Vec<Box<Button>>
46}
47
48impl HorizontalLayout {
49 /// Construct a `HorizontalLayout` object from a vector of boxed objects that implement
50 /// [Button](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::{ButtonResult, Button};
57 /// use oxide::{StdButton, HorizontalLayout};
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 = HorizontalLayout::from_vec(v, 1);
65 /// ```
66 ///
67 pub fn from_vec(widgets: Vec<Box<Button>>, inner_margin: usize) -> HorizontalLayout {
68 let first_origin = widgets.first().unwrap().frame().origin();
69 let total_width = widgets.iter().fold(0, |acc, item| acc + item.frame().size().0);
70 let width = total_width + inner_margin * (widgets.len() - 1);
71 HorizontalLayout {
72 frame: Frame::new(width, 1),
73 inner_margin: inner_margin,
74 origin: first_origin,
75 widgets: widgets
76 }
77 }
78
79}
80
81impl Widget for HorizontalLayout {
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 HorizontalLayout {
109 fn align_elems(&mut self) {
110 let (x, y) = self.origin;
111 let mut current_x = x;
112 for widget in self.widgets.iter_mut() {
113 widget.frame_mut().set_origin((current_x, y));
114 current_x += widget.frame_mut().size().0 + 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}