Radish alpha
r
Radicle terminal user interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
tui: Use table model for labeled container
Erik Kundt committed 2 years ago
commit 5051f43edfe4d97a0977e914a3b3c2d95fb373be
parent 0b615459bcbfd32cfea8ecbe47fb08dda34f7eef
1 file changed +27 -41
modified radicle-tui/src/ui/widget/common/container.rs
@@ -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;
-

-
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<_>>(),
-
        )
-
    }
+
pub struct Header<V, const W: usize>
+
where
+
    V: TableItem<W>,
+
{
+
    model: TableModel<V, W>,
+
    theme: Theme,
+
}

-
    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 }
    }
}