1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
use termion::event::{Event};
use crate::widget::{Widget, WidgetCore};
use crate::coordinates::{Coordinates, Size, Position};
use crate::fail::{HResult, HError, ErrorLog};
#[derive(PartialEq)]
pub struct HBox<T: Widget> {
pub core: WidgetCore,
pub widgets: Vec<T>,
pub ratios: Option<Vec<usize>>,
pub active: Option<usize>,
}
impl<T> HBox<T> where T: Widget + PartialEq {
pub fn new(core: &WidgetCore) -> HBox<T> {
HBox { core: core.clone(),
widgets: vec![],
ratios: None,
active: None
}
}
pub fn resize_children(&mut self) -> HResult<()> {
let len = self.widgets.len();
if len == 0 { return Ok(()) }
let coords: Vec<Coordinates> = self.calculate_coordinates()?;
for (widget, coord) in self.widgets.iter_mut().zip(coords.iter()) {
widget.set_coordinates(coord).log();
}
Ok(())
}
pub fn push_widget(&mut self, widget: T) {
self.widgets.push(widget);
}
pub fn pop_widget(&mut self) -> Option<T> {
let widget = self.widgets.pop();
widget
}
pub fn prepend_widget(&mut self, widget: T) {
self.widgets.insert(0, widget);
}
pub fn set_ratios(&mut self, ratios: Vec<usize>) {
self.ratios = Some(ratios);
}
pub fn calculate_equal_ratios(&self) -> HResult<Vec<usize>> {
let len = self.widgets.len();
if len == 0 { return HError::no_widget(); }
let ratios = (0..len).map(|_| 100 / len).collect();
Ok(ratios)
}
pub fn calculate_coordinates(&self)
-> HResult<Vec<Coordinates>> {
let box_coords = self.get_coordinates()?;
let box_xsize = box_coords.xsize();
let box_ysize = box_coords.ysize();
let box_top = box_coords.top().y();
let ratios = match &self.ratios {
Some(ratios) => ratios.clone(),
None => self.calculate_equal_ratios()?
};
let coords = ratios.iter().fold(Vec::<Coordinates>::new(), |mut coords, ratio| {
let ratio = *ratio as u16;
let len = coords.len();
let gap = if len == 0 { 0 } else { 1 };
let widget_xsize = box_xsize * ratio / 100;
let widget_xpos = if len == 0 {
box_coords.top().x()
} else {
let prev_coords = coords.last().unwrap();
let prev_xsize = prev_coords.xsize();
let prev_xpos = prev_coords.position().x();
prev_xsize + prev_xpos + gap
};
coords.push(Coordinates {
size: Size((widget_xsize,
box_ysize)),
position: Position((widget_xpos,
box_top))
});
coords
});
Ok(coords)
}
pub fn active_widget(&self) -> &T {
&self.widgets.last().unwrap()
}
}
impl<T> Widget for HBox<T> where T: Widget + PartialEq {
fn get_core(&self) -> HResult<&WidgetCore> {
Ok(&self.core)
}
fn get_core_mut(&mut self) -> HResult<&mut WidgetCore> {
Ok(&mut self.core)
}
fn set_coordinates(&mut self, coordinates: &Coordinates) -> HResult<()> {
self.core.coordinates = coordinates.clone();
self.resize_children()
}
fn render_header(&self) -> HResult<String> {
self.active_widget().render_header()
}
fn refresh(&mut self) -> HResult<()> {
self.resize_children().log();
for child in &mut self.widgets {
child.refresh().log();
}
Ok(())
}
fn get_drawlist(&self) -> HResult<String> {
Ok(self.widgets.iter().map(|child| {
child.get_drawlist().unwrap()
}).collect())
}
fn on_event(&mut self, event: Event) -> HResult<()> {
self.widgets.last_mut()?.on_event(event)?;
Ok(())
}
}
|