tui: Use table model for labeled container

This commit is contained in:
Erik Kundt 2023-05-17 12:25:23 +02:00
parent de6bb8fdb0
commit d01028502e
1 changed files with 27 additions and 41 deletions

View File

@ -1,18 +1,19 @@
use tuirealm::command::{Cmd, CmdResult}; use tuirealm::command::{Cmd, CmdResult};
use tuirealm::props::{ use tuirealm::props::{
AttrValue, Attribute, BorderSides, BorderType, Color, PropPayload, PropValue, Props, Style, AttrValue, Attribute, BorderSides, BorderType, Color, Props, Style, TextModifiers,
TextModifiers,
}; };
use tuirealm::tui::layout::{Constraint, Direction, Layout, Rect}; use tuirealm::tui::layout::{Constraint, Direction, Layout, Rect};
use tuirealm::tui::widgets::{Block, Cell, Row}; use tuirealm::tui::widgets::{Block, Row};
use tuirealm::{Frame, MockComponent, State, StateValue}; use tuirealm::{Frame, MockComponent, State, StateValue};
use crate::ui::ext::HeaderBlock; use crate::ui::ext::HeaderBlock;
use crate::ui::layout; use crate::ui::layout;
use crate::ui::state::TabState; use crate::ui::state::TabState;
use crate::ui::theme::Theme;
use crate::ui::widget::{Widget, WidgetComponent}; use crate::ui::widget::{Widget, WidgetComponent};
use super::label::Label; use super::label::Label;
use super::list::{Table, TableItem, TableModel};
/// Some user events need to be handled globally (e.g. user presses key `q` to quit /// Some user events need to be handled globally (e.g. user presses key `q` to quit
/// the application). This component can be used in conjunction with SubEventClause /// the application). This component can be used in conjunction with SubEventClause
@ -127,47 +128,31 @@ impl WidgetComponent for Tabs {
} }
/// A labeled container header. /// A labeled container header.
#[derive(Default)] pub struct Header<V, const W: usize>
pub struct Header; where
V: TableItem<W>,
{
model: TableModel<V, W>,
theme: Theme,
}
impl Header { impl<V, const W: usize> Header<V, W>
fn content<'a>(spans: Vec<PropValue>) -> Row<'a> { where
Row::new( V: TableItem<W>,
spans {
.iter() pub fn new(model: TableModel<V, W>, theme: Theme) -> Self {
.map(|span| Cell::from(span.clone().unwrap_text_span().content)) Self { model, theme }
.collect::<Vec<_>>(),
)
}
fn widths(widths: Vec<PropValue>) -> Vec<Constraint> {
widths
.iter()
.map(|prop| Constraint::Percentage(prop.clone().unwrap_u16()))
.collect()
} }
} }
impl WidgetComponent for Header { impl<V, const W: usize> WidgetComponent for Header<V, W>
where
V: TableItem<W> + Clone,
{
fn view(&mut self, properties: &Props, frame: &mut Frame, area: Rect) { fn view(&mut self, properties: &Props, frame: &mut Frame, area: Rect) {
let display = properties let display = properties
.get_or(Attribute::Display, AttrValue::Flag(true)) .get_or(Attribute::Display, AttrValue::Flag(true))
.unwrap_flag(); .unwrap_flag();
let content = properties
.get_or(
Attribute::Content,
AttrValue::Payload(PropPayload::Vec(vec![])),
)
.unwrap_payload()
.unwrap_vec();
let widths = properties
.get_or(
Attribute::Custom("widths"),
AttrValue::Payload(PropPayload::Vec(vec![])),
)
.unwrap_payload()
.unwrap_vec();
if display { if display {
let block = HeaderBlock::default() let block = HeaderBlock::default()
.borders(BorderSides::all()) .borders(BorderSides::all())
@ -182,11 +167,12 @@ impl WidgetComponent for Header {
.horizontal_margin(1) .horizontal_margin(1)
.split(area); .split(area);
let header = Self::content(content); let widths =
let widths = Self::widths(widths); Table::<V, W>::widths(area, self.model.widths(), self.theme.tables.spacing);
let header: Row<'_> = Row::new(self.model.header(&self.theme));
let table = tuirealm::tui::widgets::Table::new(vec![]) let table = tuirealm::tui::widgets::Table::new(vec![])
.column_spacing(3u16) .column_spacing(self.theme.tables.spacing)
.header(header) .header(header)
.widths(&widths); .widths(&widths);
frame.render_widget(table, layout[0]); frame.render_widget(table, layout[0]);
@ -203,12 +189,12 @@ impl WidgetComponent for Header {
} }
pub struct LabeledContainer { pub struct LabeledContainer {
header: Widget<Header>, header: Widget<Header<(), 1>>,
component: Box<dyn MockComponent>, component: Box<dyn MockComponent>,
} }
impl LabeledContainer { impl LabeledContainer {
pub fn new(header: Widget<Header>, component: Box<dyn MockComponent>) -> Self { pub fn new(header: Widget<Header<(), 1>>, component: Box<dyn MockComponent>) -> Self {
Self { header, component } Self { header, component }
} }
} }