use ratatui_core::layout;
use ratatui_core::style;
use ratatui_core::terminal::Frame;
use ratatui_widgets::block;
use ratatui_widgets::borders;
use super::element::{Element, ElementWithChildren};
use crate::error;
pub struct Container {
border: Option<ContainerBorder>,
children: Vec<Box<dyn Element>>,
constraint: layout::Constraint,
direction: layout::Direction,
fill: style::Style,
layout: Option<layout::Layout>,
}
impl ElementWithChildren for Container {
#[inline(always)]
fn add_child(&mut self, child: Box<dyn Element>) -> Result<(), error::LintuiniError>{
self.children.push(child);
Ok(())
}
#[inline(always)]
fn children(&self) -> &[Box<dyn Element>] {
self.children.as_slice()
}
#[inline(always)]
fn children_mut(&mut self) -> &mut [Box<dyn Element>] {
self.children.as_mut_slice()
}
}
impl Element for Container {
#[inline(always)]
fn constraint(&self) -> &layout::Constraint {
&self.constraint
}
fn render(&self, frm: &mut Frame, rect: layout::Rect) -> Result<(), error::LintuiniError> {
let blk = match &self.border {
Some(bs) => block::Block::bordered().style(self.fill).border_type(bs.kind).border_style(bs.style),
None => block::Block::new().style(self.fill),
};
frm.render_widget(blk, rect);
if self.layout.is_none() {
debug_assert!(
self.children.len() == 0,
"child count did not match number of layout fields"
);
return Ok(());
}
// TODO: children
Ok(())
}
}
#[derive(Default)]
pub struct ContainerBuilder {
border: Option<ContainerBorder>,
constraint: layout::Constraint,
direction: layout::Direction,
fill: style::Style,
}
impl ContainerBuilder {
#[inline(always)]
pub fn new() -> Self {
ContainerBuilder::default()
}
#[inline(always)]
pub fn fill(mut self, style: style::Style) -> Self {
self.fill = style;
self
}
#[inline(always)]
pub fn constraint(mut self, constraint: layout::Constraint) -> Self {
self.constraint = constraint;
self
}
#[inline(always)]
pub fn direction(mut self, direction: layout::Direction) -> Self {
self.direction = direction;
self
}
#[inline(always)]
pub fn border_style(mut self, style: style::Style) -> Self {
match self.border {
Some(mut bs) => { bs.style = style; },
None => { self.border = Some(ContainerBorder { style: style, ..Default::default() }) },
}
self
}
#[inline(always)]
pub fn border_type(mut self, kind: borders::BorderType) -> Self {
match self.border {
Some(mut bs) => { bs.kind = kind; },
None => { self.border = Some(ContainerBorder { kind: kind, ..Default::default() }) },
}
self
}
#[inline(always)]
pub fn build(self) -> Container {
Container {
border: self.border,
constraint: self.constraint,
children: Vec::new(),
direction: self.direction,
fill: self.fill,
layout: None,
}
}
}
#[derive(Clone, Copy, Default)]
pub struct ContainerBorder {
style: style::Style,
kind: borders::BorderType,
}