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 { pub core: WidgetCore, pub widgets: Vec, pub ratios: Option>, pub active: Option, } impl HBox where T: Widget + PartialEq { pub fn new(core: &WidgetCore) -> HBox { 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 = 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 { 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) { self.ratios = Some(ratios); } pub fn calculate_equal_ratios(&self) -> HResult> { 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> { 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::::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 Widget for HBox 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 render_header(&self) -> HResult { self.active_widget().render_header() } fn refresh(&mut self) -> HResult<()> { self.resize_children().log(); for child in &mut self.widgets { child.refresh()? } Ok(()) } fn get_drawlist(&self) -> HResult { 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(()) } }