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::props::{
AttrValue, Attribute, BorderSides, BorderType, Color, PropPayload, PropValue, Props, Style,
TextModifiers,
AttrValue, Attribute, BorderSides, BorderType, Color, Props, Style, TextModifiers,
};
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 crate::ui::ext::HeaderBlock;
use crate::ui::layout;
use crate::ui::state::TabState;
use crate::ui::theme::Theme;
use crate::ui::widget::{Widget, WidgetComponent};
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
/// the application). This component can be used in conjunction with SubEventClause
@ -127,47 +128,31 @@ impl WidgetComponent for Tabs {
}
/// A labeled container header.
#[derive(Default)]
pub struct Header;
pub struct Header<V, const W: usize>
where
V: TableItem<W>,
{
model: TableModel<V, W>,
theme: Theme,
}
impl Header {
fn content<'a>(spans: Vec<PropValue>) -> Row<'a> {
Row::new(
spans
.iter()
.map(|span| Cell::from(span.clone().unwrap_text_span().content))
.collect::<Vec<_>>(),
)
}
fn widths(widths: Vec<PropValue>) -> Vec<Constraint> {
widths
.iter()
.map(|prop| Constraint::Percentage(prop.clone().unwrap_u16()))
.collect()
impl<V, const W: usize> Header<V, W>
where
V: TableItem<W>,
{
pub fn new(model: TableModel<V, W>, theme: Theme) -> Self {
Self { model, theme }
}
}
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) {
let display = properties
.get_or(Attribute::Display, AttrValue::Flag(true))
.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 {
let block = HeaderBlock::default()
.borders(BorderSides::all())
@ -182,11 +167,12 @@ impl WidgetComponent for Header {
.horizontal_margin(1)
.split(area);
let header = Self::content(content);
let widths = Self::widths(widths);
let 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![])
.column_spacing(3u16)
.column_spacing(self.theme.tables.spacing)
.header(header)
.widths(&widths);
frame.render_widget(table, layout[0]);
@ -203,12 +189,12 @@ impl WidgetComponent for Header {
}
pub struct LabeledContainer {
header: Widget<Header>,
header: Widget<Header<(), 1>>,
component: Box<dyn MockComponent>,
}
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 }
}
}