tui: Use table model for labeled container
This commit is contained in:
parent
de6bb8fdb0
commit
d01028502e
|
|
@ -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 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue