Radish alpha
r
Radicle terminal user interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
lib: Use themed styles everywhere
Erik Kundt committed 2 years ago
commit ddc10a45e7f916923654c26154e42b2f1af2f4d6
parent b5d8453d013f4b81934da88d649ea3685f113dc2
10 files changed +105 -170
modified bin/commands/issue/suite/ui.rs
@@ -72,8 +72,7 @@ impl IssueBrowser {
            _ => items.first().cloned(),
        };

-
        let table = Widget::new(Table::new(&items, selected, header, widths, theme.clone()))
-
            .highlight(style::highlight().fg.unwrap());
+
        let table = Widget::new(Table::new(&items, selected, header, widths, theme.clone()));

        Self { items, table }
    }
@@ -123,8 +122,7 @@ impl LargeList {
        let selected =
            selected.map(|(id, issue)| IssueItem::from((context.profile(), repo, id, issue)));

-
        let list = Widget::new(List::new(&items, selected, theme.clone()))
-
            .highlight(style::highlight().fg.unwrap());
+
        let list = Widget::new(List::new(&items, selected, theme.clone()));

        let container = tui::ui::container(theme, list.to_boxed());

@@ -174,8 +172,8 @@ impl IssueHeader {
        let item = IssueItem::from((context.profile(), repo, id, issue.clone()));

        let title = Property::new(
-
            tui::ui::label("Title").foreground(style::cyan().fg.unwrap()),
-
            tui::ui::label(item.title()).foreground(style::reset().fg.unwrap()),
+
            tui::ui::label("Title").style(style::cyan()),
+
            tui::ui::label(item.title()).style(style::reset()),
        );

        let author_style = match alias {
@@ -184,25 +182,21 @@ impl IssueHeader {
        };

        let author = tui::ui::label(&cob::format_author(issue.author().id(), &alias, by_you))
-
            .foreground(author_style.fg.unwrap());
-
        let author = Property::new(
-
            tui::ui::label("Author").foreground(style::cyan().fg.unwrap()),
-
            author,
-
        );
+
            .style(author_style);
+
        let author = Property::new(tui::ui::label("Author").style(style::cyan()), author);

        let issue_id = Property::new(
-
            tui::ui::label("Issue").foreground(style::cyan().fg.unwrap()),
-
            tui::ui::label(&id.to_string()).foreground(style::gray().fg.unwrap()),
+
            tui::ui::label("Issue").style(style::cyan()),
+
            tui::ui::label(&id.to_string()).style(style::gray()),
        );

        let labels = Property::new(
-
            tui::ui::label("Labels").foreground(style::cyan().fg.unwrap()),
-
            tui::ui::label(&cob::format_labels(item.labels()))
-
                .foreground(style::lightblue().fg.unwrap()),
+
            tui::ui::label("Labels").style(style::cyan()),
+
            tui::ui::label(&cob::format_labels(item.labels())).style(style::lightblue()),
        );

        let assignees = Property::new(
-
            tui::ui::label("Assignees").foreground(style::cyan().fg.unwrap()),
+
            tui::ui::label("Assignees").style(style::cyan()),
            tui::ui::label(&cob::format_assignees(
                &item
                    .assignees()
@@ -210,12 +204,12 @@ impl IssueHeader {
                    .map(|item| (item.did(), item.alias(), item.is_you()))
                    .collect::<Vec<_>>(),
            ))
-
            .foreground(author_style.fg.unwrap()),
+
            .style(author_style),
        );

        let state = Property::new(
-
            tui::ui::label("Status").foreground(style::cyan().fg.unwrap()),
-
            tui::ui::label(&item.state().to_string()).foreground(style::reset().fg.unwrap()),
+
            tui::ui::label("Status").style(style::cyan()),
+
            tui::ui::label(&item.state().to_string()).style(style::reset()),
        );

        let table = tui::ui::property_table(
@@ -306,7 +300,7 @@ impl CommentBody {
        };
        let textarea = Widget::new(Textarea::default())
            .content(AttrValue::String(content))
-
            .foreground(style::reset().fg.unwrap());
+
            .style(style::reset());

        let textarea = tui::ui::container(theme, textarea.to_boxed());

@@ -336,7 +330,7 @@ impl WidgetComponent for CommentBody {
pub fn list_navigation(theme: &Theme) -> Widget<Tabs> {
    tui::ui::tabs(
        theme,
-
        vec![tui::ui::reversable_label("Issues").foreground(style::magenta().fg.unwrap())],
+
        vec![tui::ui::reversable_label("Issues").style(style::magenta())],
    )
}

modified bin/commands/patch/list/ui.rs
@@ -23,14 +23,14 @@ pub struct PatchBrowser {
impl PatchBrowser {
    pub fn new(context: &Context, theme: &Theme, selected: Option<(PatchId, Patch)>) -> Self {
        let header = [
-
            tui::ui::label(" ● ").foreground(style::reset_dim().fg.unwrap()),
-
            tui::ui::label("ID").foreground(style::reset_dim().fg.unwrap()),
-
            tui::ui::label("Title").foreground(style::reset_dim().fg.unwrap()),
-
            tui::ui::label("Author").foreground(style::reset_dim().fg.unwrap()),
-
            tui::ui::label("Head").foreground(style::reset_dim().fg.unwrap()),
-
            tui::ui::label("+").foreground(style::reset_dim().fg.unwrap()),
-
            tui::ui::label("-").foreground(style::reset_dim().fg.unwrap()),
-
            tui::ui::label("Updated").foreground(style::reset_dim().fg.unwrap()),
+
            tui::ui::label(" ● ").style(style::reset_dim()),
+
            tui::ui::label("ID").style(style::reset_dim()),
+
            tui::ui::label("Title").style(style::reset_dim()),
+
            tui::ui::label("Author").style(style::reset_dim()),
+
            tui::ui::label("Head").style(style::reset_dim()),
+
            tui::ui::label("+").style(style::reset_dim()),
+
            tui::ui::label("-").style(style::reset_dim()),
+
            tui::ui::label("Updated").style(style::reset_dim()),
        ];

        let widths = [
@@ -64,8 +64,7 @@ impl PatchBrowser {
            _ => items.first().cloned(),
        };

-
        let table = Widget::new(Table::new(&items, selected, header, widths, theme.clone()))
-
            .highlight(style::highlight().fg.unwrap());
+
        let table = Widget::new(Table::new(&items, selected, header, widths, theme.clone()));

        Self { items, table }
    }
@@ -97,7 +96,7 @@ impl WidgetComponent for PatchBrowser {
pub fn list_navigation(theme: &Theme) -> Widget<Tabs> {
    tui::ui::tabs(
        theme,
-
        vec![tui::ui::reversable_label("Patches").foreground(style::cyan().fg.unwrap())],
+
        vec![tui::ui::reversable_label("Patches").style(style::cyan())],
    )
}

@@ -131,47 +130,23 @@ pub fn browse_context(context: &Context, _theme: &Theme, progress: Progress) ->
        }
    }

-
    let context = label(" Patches ")
-
        .foreground(style::magenta_reversed().fg.unwrap())
-
        .background(style::magenta_reversed().bg.unwrap());
-

-
    let divider = label(" | ")
-
        .foreground(style::default_reversed().fg.unwrap())
-
        .background(style::default_reversed().bg.unwrap());
-

-
    let draft_n = label(&format!("{draft}"))
-
        .foreground(style::default_reversed().fg.unwrap())
-
        .background(style::default_reversed().bg.unwrap());
-
    let draft = label(" Draft")
-
        .foreground(style::default_reversed().fg.unwrap())
-
        .background(style::default_reversed().bg.unwrap());
-

-
    let open_n = label(&format!("{open}"))
-
        .foreground(style::green().fg.unwrap())
-
        .background(style::default_reversed().bg.unwrap());
-
    let open = label(" Open")
-
        .foreground(style::default_reversed().fg.unwrap())
-
        .background(style::default_reversed().bg.unwrap());
-

-
    let archived_n = label(&format!("{archived}"))
-
        .foreground(style::yellow().fg.unwrap())
-
        .background(style::default_reversed().bg.unwrap());
-
    let archived = label(" Archived")
-
        .foreground(style::default_reversed().fg.unwrap())
-
        .background(style::default_reversed().bg.unwrap());
-

-
    let merged_n = label(&format!("{merged}"))
-
        .foreground(style::cyan().fg.unwrap())
-
        .background(style::default_reversed().bg.unwrap());
-
    let merged = label(" Merged ")
-
        .foreground(style::default_reversed().fg.unwrap())
-
        .background(style::default_reversed().bg.unwrap());
-

-
    let progress = label(&format!(" {} ", progress.to_string()))
-
        .foreground(style::magenta_reversed().fg.unwrap())
-
        .background(style::magenta_reversed().bg.unwrap());
-

-
    let spacer = label("").background(style::default_reversed().bg.unwrap());
+
    let context = label(" Patches ").style(style::magenta_reversed());
+
    let divider = label(" | ").style(style::default_reversed());
+

+
    let draft_n = label(&format!("{draft}")).style(style::default_reversed());
+
    let draft = label(" Draft").style(style::default_reversed());
+

+
    let open_n = label(&format!("{open}")).style(style::green_default_reversed());
+
    let open = label(" Open").style(style::default_reversed());
+

+
    let archived_n = label(&format!("{archived}")).style(style::yellow_default_reversed());
+
    let archived = label(" Archived").style(style::default_reversed());
+

+
    let merged_n = label(&format!("{merged}")).style(style::cyan_default_reversed());
+
    let merged = label(" Merged ").style(style::default_reversed());
+

+
    let progress = label(&format!(" {} ", progress.to_string())).style(style::magenta_reversed());
+
    let spacer = label("").style(style::default_reversed());

    let context_bar = ContextBar::new(
        label_group(&[context]),
modified bin/commands/patch/suite/ui.rs
@@ -68,8 +68,7 @@ impl PatchBrowser {
            _ => items.first().cloned(),
        };

-
        let table = Widget::new(Table::new(&items, selected, header, widths, theme.clone()))
-
            .highlight(style::highlight().fg.unwrap());
+
        let table = Widget::new(Table::new(&items, selected, header, widths, theme.clone()));

        Self { items, table }
    }
@@ -163,7 +162,7 @@ impl WidgetComponent for Files {
pub fn list_navigation(theme: &Theme) -> Widget<Tabs> {
    tui::ui::tabs(
        theme,
-
        vec![tui::ui::reversable_label("Patches").foreground(style::magenta().fg.unwrap())],
+
        vec![tui::ui::reversable_label("Patches").style(style::magenta())],
    )
}

@@ -171,8 +170,8 @@ pub fn navigation(theme: &Theme) -> Widget<Tabs> {
    tui::ui::tabs(
        theme,
        vec![
-
            tui::ui::reversable_label("Activity").foreground(style::magenta().fg.unwrap()),
-
            tui::ui::reversable_label("Files").foreground(style::magenta().fg.unwrap()),
+
            tui::ui::reversable_label("Activity").style(style::magenta()),
+
            tui::ui::reversable_label("Files").style(style::magenta()),
        ],
    )
}
@@ -186,14 +185,14 @@ pub fn patches(
}

pub fn activity(_theme: &Theme) -> Widget<Activity> {
-
    let not_implemented = tui::ui::label("not implemented").foreground(style::reset().fg.unwrap());
+
    let not_implemented = tui::ui::label("not implemented").style(style::reset());
    let activity = Activity::new(not_implemented);

    Widget::new(activity)
}

pub fn files(_theme: &Theme) -> Widget<Files> {
-
    let not_implemented = tui::ui::label("not implemented").foreground(style::reset().fg.unwrap());
+
    let not_implemented = tui::ui::label("not implemented").style(style::reset());
    let files = Files::new(not_implemented);

    Widget::new(files)
modified src/ui.rs
@@ -73,18 +73,15 @@ pub fn labeled_container(
    title: &str,
    component: Box<dyn MockComponent>,
) -> Widget<LabeledContainer> {
-
    let header = container_header(
-
        theme,
-
        label(&format!(" {title} ")).foreground(style::reset().fg.unwrap()),
-
    );
+
    let header = container_header(theme, label(&format!(" {title} ")).style(style::reset()));
    let container = LabeledContainer::new(header, component, theme.clone());

    Widget::new(container)
}

pub fn shortcut(theme: &Theme, short: &str, long: &str) -> Widget<Shortcut> {
-
    let short = label(short).foreground(style::gray().fg.unwrap());
-
    let long = label(long).foreground(style::gray_dim().fg.unwrap());
+
    let short = label(short).style(style::gray());
+
    let long = label(long).style(style::gray_dim());
    let divider = label(&theme.icons.whitespace.to_string());

    // TODO: Remove when size constraints are implemented
@@ -99,17 +96,16 @@ pub fn shortcut(theme: &Theme, short: &str, long: &str) -> Widget<Shortcut> {
}

pub fn shortcuts(theme: &Theme, shortcuts: Vec<Widget<Shortcut>>) -> Widget<Shortcuts> {
-
    let divider = label(&format!(" {} ", theme.icons.shortcutbar_divider))
-
        .foreground(style::gray_dim().fg.unwrap());
+
    let divider = label(&format!(" {} ", theme.icons.shortcutbar_divider)).style(style::gray_dim());
    let shortcut_bar = Shortcuts::new(shortcuts, divider);

    Widget::new(shortcut_bar).height(1)
}

pub fn property(theme: &Theme, name: &str, value: &str) -> Widget<Property> {
-
    let name = label(name).foreground(style::cyan().fg.unwrap());
+
    let name = label(name).style(style::cyan());
    let divider = label(&format!(" {} ", theme.icons.property_divider));
-
    let value = label(value).foreground(style::reset().fg.unwrap());
+
    let value = label(value).style(style::reset());

    // TODO: Remove when size constraints are implemented
    let name_w = name.query(Attribute::Width).unwrap().unwrap_size();
@@ -141,8 +137,8 @@ pub fn tabs(_theme: &Theme, tabs: Vec<Widget<Label>>) -> Widget<Tabs> {
}

pub fn app_info(context: &Context) -> Widget<AppInfo> {
-
    let project = label(context.project().name()).foreground(style::cyan().fg.unwrap());
-
    let rid = label(&format!(" ({})", context.id())).foreground(style::yellow().fg.unwrap());
+
    let project = label(context.project().name()).style(style::cyan());
+
    let rid = label(&format!(" ({})", context.id())).style(style::yellow());

    let project_w = project
        .query(Attribute::Width)
@@ -162,8 +158,7 @@ pub fn app_header(
    theme: &Theme,
    nav: Option<Widget<Tabs>>,
) -> Widget<AppHeader> {
-
    let line =
-
        label(&theme.icons.tab_overline.to_string()).foreground(style::magenta().fg.unwrap());
+
    let line = label(&theme.icons.tab_overline.to_string()).style(style::magenta());
    let line = Widget::new(VerticalLine::new(line));
    let info = app_info(context);
    let header = AppHeader::new(nav, info, line);
modified src/ui/theme.rs
@@ -117,6 +117,27 @@ pub mod style {
        Style::default().fg(Color::DarkGray).bg(Color::Yellow)
    }

+
    pub fn green_default_reversed() -> Style {
+
        Style::default()
+
            .fg(Color::Green)
+
            .bg(Color::DarkGray)
+
            .add_modifier(TextModifiers::DIM)
+
    }
+

+
    pub fn yellow_default_reversed() -> Style {
+
        Style::default()
+
            .fg(Color::Yellow)
+
            .bg(Color::DarkGray)
+
            .add_modifier(TextModifiers::DIM)
+
    }
+

+
    pub fn cyan_default_reversed() -> Style {
+
        Style::default()
+
            .fg(Color::Cyan)
+
            .bg(Color::DarkGray)
+
            .add_modifier(TextModifiers::DIM)
+
    }
+

    pub fn border(focus: bool) -> Style {
        if focus {
            gray_dim()
@@ -126,6 +147,6 @@ pub mod style {
    }

    pub fn highlight() -> Style {
-
        darkgray()
+
        Style::default().bg(Color::DarkGray)
    }
}
modified src/ui/widget.rs
@@ -8,7 +8,7 @@ mod utils;
use std::ops::Deref;

use tuirealm::command::{Cmd, CmdResult};
-
use tuirealm::props::{AttrValue, Attribute, Color, Layout, Props, TextModifiers};
+
use tuirealm::props::{AttrValue, Attribute, Layout, Props, Style};
use tuirealm::tui::layout::Rect;
use tuirealm::{Frame, MockComponent, State};

@@ -44,33 +44,6 @@ impl<T: WidgetComponent> Widget<T> {
        }
    }

-
    pub fn foreground(mut self, fg: Color) -> Self {
-
        self.attr(Attribute::Foreground, AttrValue::Color(fg));
-
        self
-
    }
-

-
    pub fn dim(mut self) -> Self {
-
        let props = self
-
            .query(Attribute::TextProps)
-
            .unwrap_or(AttrValue::TextModifiers(TextModifiers::empty()));
-

-
        self.attr(
-
            Attribute::TextProps,
-
            AttrValue::TextModifiers(props.unwrap_text_modifiers() | TextModifiers::DIM),
-
        );
-
        self
-
    }
-

-
    pub fn highlight(mut self, fg: Color) -> Self {
-
        self.attr(Attribute::HighlightedColor, AttrValue::Color(fg));
-
        self
-
    }
-

-
    pub fn background(mut self, bg: Color) -> Self {
-
        self.attr(Attribute::Background, AttrValue::Color(bg));
-
        self
-
    }
-

    pub fn height(mut self, h: u16) -> Self {
        self.attr(Attribute::Height, AttrValue::Size(h));
        self
@@ -96,6 +69,11 @@ impl<T: WidgetComponent> Widget<T> {
        self
    }

+
    pub fn style(mut self, style: Style) -> Self {
+
        self.attr(Attribute::Style, AttrValue::Style(style));
+
        self
+
    }
+

    pub fn to_boxed(self) -> Box<Self> {
        Box::new(self)
    }
modified src/ui/widget/context.rs
@@ -217,21 +217,11 @@ pub fn bar(
) -> Widget<ContextBar> {
    use crate::ui::{label, label_group};

-
    let label_0 = label(&format!(" {label_0} "))
-
        .foreground(style::magenta_reversed().fg.unwrap())
-
        .background(style::magenta_reversed().bg.unwrap());
-
    let label_1 = label(&format!(" {label_1} "))
-
        .foreground(style::default_reversed().fg.unwrap())
-
        .background(style::default_reversed().bg.unwrap());
-
    let label_2 = label(&format!(" {label_2} "))
-
        .foreground(style::default_reversed().fg.unwrap())
-
        .background(style::default_reversed().bg.unwrap());
-
    let label_3 = label(&format!(" {label_3} "))
-
        .foreground(style::default_reversed().fg.unwrap())
-
        .background(style::default_reversed().bg.unwrap());
-
    let label_4 = label(&format!(" {label_4} "))
-
        .foreground(style::default_reversed().fg.unwrap())
-
        .background(style::default_reversed().bg.unwrap());
+
    let label_0 = label(&format!(" {label_0} ")).style(style::magenta_reversed());
+
    let label_1 = label(&format!(" {label_1} ")).style(style::default_reversed());
+
    let label_2 = label(&format!(" {label_2} ")).style(style::default_reversed());
+
    let label_3 = label(&format!(" {label_3} ")).style(style::default_reversed());
+
    let label_4 = label(&format!(" {label_4} ")).style(style::default_reversed());

    let label_0 = label_group(&[label_0]);
    let label_1 = label_group(&[label_1]);
modified src/ui/widget/form.rs
@@ -29,7 +29,7 @@ impl TextField {

        Self {
            input: container,
-
            placeholder: crate::ui::label(title).foreground(style::gray_dim().fg.unwrap()),
+
            placeholder: crate::ui::label(title).style(style::gray_dim()),
            show_placeholder: true,
        }
    }
@@ -103,7 +103,7 @@ impl TextArea {

        Self {
            input: container,
-
            placeholder: crate::ui::label(title).foreground(style::gray_dim().fg.unwrap()),
+
            placeholder: crate::ui::label(title).style(style::gray_dim()),
            show_placeholder: true,
        }
    }
modified src/ui/widget/label.rs
@@ -23,25 +23,16 @@ impl WidgetComponent for Label {
        let display = properties
            .get_or(Attribute::Display, AttrValue::Flag(true))
            .unwrap_flag();
-
        let foreground = properties
-
            .get_or(Attribute::Foreground, AttrValue::Color(Color::Reset))
-
            .unwrap_color();
-
        let background = properties
-
            .get_or(Attribute::Background, AttrValue::Color(Color::Reset))
-
            .unwrap_color();
+
        let style = properties
+
            .get_or(Attribute::Style, AttrValue::Style(Style::default()))
+
            .unwrap_style();

        if display {
-
            let mut label = match properties.get(Attribute::TextProps) {
-
                Some(modifiers) => Label::default()
-
                    .foreground(foreground)
-
                    .background(background)
-
                    .modifiers(modifiers.unwrap_text_modifiers())
-
                    .text(content),
-
                None => Label::default()
-
                    .foreground(foreground)
-
                    .background(background)
-
                    .text(content),
-
            };
+
            let mut label = Label::default()
+
                .foreground(style.fg.unwrap_or(Color::Reset))
+
                .background(style.bg.unwrap_or(Color::Reset))
+
                .modifiers(style.add_modifier)
+
                .text(content);

            label.view(frame, area);
        }
modified src/ui/widget/list.rs
@@ -1,5 +1,5 @@
use tuirealm::command::{Cmd, CmdResult};
-
use tuirealm::props::{AttrValue, Attribute, BorderSides, Color, Props, Style};
+
use tuirealm::props::{AttrValue, Attribute, BorderSides, Props};
use tuirealm::tui::layout::{Constraint, Direction, Layout, Rect};
use tuirealm::tui::widgets::{Block, Cell, ListState, Row, TableState};
use tuirealm::{Frame, MockComponent, State, StateValue};
@@ -226,10 +226,6 @@ where
    V: TableItem<W> + Clone + PartialEq,
{
    fn view(&mut self, properties: &Props, frame: &mut Frame, area: Rect) {
-
        let highlight = properties
-
            .get_or(Attribute::HighlightedColor, AttrValue::Color(Color::Reset))
-
            .unwrap_color();
-

        let focus = properties
            .get_or(Attribute::Focus, AttrValue::Flag(false))
            .unwrap_flag();
@@ -253,7 +249,7 @@ where
                    .border_style(style::border(focus))
                    .border_type(self.theme.border_type),
            )
-
            .highlight_style(Style::default().bg(highlight))
+
            .highlight_style(style::highlight())
            .column_spacing(self.theme.tables.spacing)
            .widths(&widths);

@@ -330,19 +326,15 @@ impl<V> WidgetComponent for List<V>
where
    V: ListItem + Clone + PartialEq,
{
-
    fn view(&mut self, properties: &Props, frame: &mut Frame, area: Rect) {
+
    fn view(&mut self, _properties: &Props, frame: &mut Frame, area: Rect) {
        use tuirealm::tui::widgets::{List, ListItem};

-
        let highlight = properties
-
            .get_or(Attribute::HighlightedColor, AttrValue::Color(Color::Reset))
-
            .unwrap_color();
-

        let rows: Vec<ListItem> = self
            .items
            .iter()
            .map(|item| item.row(&self.theme))
            .collect();
-
        let list = List::new(rows).highlight_style(Style::default().bg(highlight));
+
        let list = List::new(rows).highlight_style(style::highlight());

        frame.render_stateful_widget(list, area, &mut ListState::from(&self.state));
    }