Radish alpha
r
Radicle terminal user interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
Factor out common form widget
Erik Kundt committed 2 years ago
commit 1d26f1612cbc2ea6226a3ecdf716a95113750d49
parent 22d58114c69f27b4b5421dbdcf0b9734e829885a
3 files changed +115 -58
modified src/ui/widget/common.rs
@@ -1,5 +1,6 @@
pub mod container;
pub mod context;
+
pub mod form;
pub mod label;
pub mod list;

added src/ui/widget/common/form.rs
@@ -0,0 +1,83 @@
+
use tui_realm_stdlib::Input;
+
use tuirealm::command::{Cmd, CmdResult};
+
use tuirealm::tui::layout::{Constraint, Direction, Rect};
+
use tuirealm::{AttrValue, Attribute, Frame, MockComponent, Props, State};
+

+
use crate::ui::state::FormState;
+
use crate::ui::theme::Theme;
+
use crate::ui::widget::WidgetComponent;
+

+
pub struct Form {
+
    // This form's fields: title, tags, assignees, description.
+
    inputs: Vec<Input>,
+
    /// State that holds the current focus etc.
+
    state: FormState,
+
}
+

+
impl Form {
+
    pub fn new(_theme: Theme, inputs: Vec<Input>) -> Self {
+
        let state = FormState::new(Some(0), inputs.len());
+

+
        Self { inputs, state }
+
    }
+
}
+

+
impl WidgetComponent for Form {
+
    fn view(&mut self, properties: &Props, frame: &mut Frame, area: Rect) {
+
        use tuirealm::props::Layout;
+
        // Clear and set current focus
+
        let focus = self.state.focus().unwrap_or(0);
+
        for input in &mut self.inputs {
+
            input.attr(Attribute::Focus, AttrValue::Flag(false));
+
        }
+
        if let Some(input) = self.inputs.get_mut(focus) {
+
            input.attr(Attribute::Focus, AttrValue::Flag(true));
+
        }
+

+
        let layout = Layout::default()
+
            .direction(Direction::Vertical)
+
            .constraints(
+
                &self
+
                    .inputs
+
                    .iter()
+
                    .map(|_| Constraint::Length(3))
+
                    .collect::<Vec<_>>(),
+
            );
+
        let layout = properties
+
            .get_or(Attribute::Layout, AttrValue::Layout(layout))
+
            .unwrap_layout();
+
        let layout = layout.chunks(area);
+

+
        for (index, area) in layout.iter().enumerate().take(self.inputs.len()) {
+
            if let Some(input) = self.inputs.get_mut(index) {
+
                input.view(frame, *area);
+
            }
+
        }
+
    }
+

+
    fn state(&self) -> State {
+
        State::None
+
    }
+

+
    fn perform(&mut self, _properties: &Props, cmd: Cmd) -> CmdResult {
+
        use tuirealm::command::Direction;
+
        match cmd {
+
            Cmd::Move(Direction::Up) => {
+
                self.state.focus_previous();
+
                CmdResult::None
+
            }
+
            Cmd::Move(Direction::Down) => {
+
                self.state.focus_next();
+
                CmdResult::None
+
            }
+
            _ => {
+
                let focus = self.state.focus().unwrap_or(0);
+
                if let Some(input) = self.inputs.get_mut(focus) {
+
                    input.perform(cmd)
+
                } else {
+
                    CmdResult::None
+
                }
+
            }
+
        }
+
    }
+
}
modified src/ui/widget/issue.rs
@@ -11,10 +11,9 @@ use tuirealm::tui::layout::Constraint;
use tuirealm::tui::layout::Direction;
use tuirealm::tui::layout::Layout;

-
use super::common::container::Container;
-
use super::common::container::LabeledContainer;
-
use super::common::context::ContextBar;
-
use super::common::context::Progress;
+
use super::common::container::{Container, LabeledContainer};
+
use super::common::context::{ContextBar, Progress};
+
use super::common::form::Form;
use super::common::label::Textarea;
use super::common::list::List;
use super::common::list::Property;
@@ -23,7 +22,6 @@ use super::Widget;
use crate::ui::cob;
use crate::ui::cob::IssueItem;
use crate::ui::context::Context;
-
use crate::ui::state::FormState;
use crate::ui::theme::Theme;

use super::*;
@@ -252,14 +250,14 @@ impl WidgetComponent for CommentBody {
pub struct NewForm {
    /// The issue this form writes its input values to.
    _issue: Issue,
-
    // This form's fields: title, tags, assignees, description.
-
    inputs: Vec<Input>,
-
    /// State that holds the current focus etc.
-
    state: FormState,
+
    /// The actual form.
+
    form: Widget<Form>,
}

impl NewForm {
-
    pub fn new(_context: &Context, theme: &Theme) -> Self {
+
    pub fn new(theme: &Theme) -> Self {
+
        use tuirealm::props::Layout;
+

        let foreground = theme.colors.default_fg;
        let placeholder_style = Style::default().fg(theme.colors.input_placeholder_fg);
        let inactive_style = Style::default().fg(theme.colors.container_border_fg);
@@ -288,42 +286,35 @@ impl NewForm {
            .inactive(inactive_style)
            .placeholder("Description", placeholder_style);

-
        let state = FormState::new(Some(0), 4);
+
        let mut form = Widget::new(Form::new(
+
            theme.clone(),
+
            vec![title, tags, assignees, description],
+
        ));
+
        form.attr(
+
            Attribute::Layout,
+
            AttrValue::Layout(
+
                Layout::default().constraints(
+
                    [
+
                        Constraint::Length(3),
+
                        Constraint::Length(3),
+
                        Constraint::Length(3),
+
                        Constraint::Min(3),
+
                    ]
+
                    .as_ref(),
+
                ),
+
            ),
+
        );

        Self {
            _issue: Issue::default(),
-
            inputs: vec![title, tags, assignees, description],
-
            state,
+
            form,
        }
    }
}

impl WidgetComponent for NewForm {
    fn view(&mut self, _properties: &Props, frame: &mut Frame, area: Rect) {
-
        // Clear and set current focus
-
        let focus = self.state.focus().unwrap_or(0);
-
        for input in &mut self.inputs {
-
            input.attr(Attribute::Focus, AttrValue::Flag(false));
-
        }
-
        if let Some(input) = self.inputs.get_mut(focus) {
-
            input.attr(Attribute::Focus, AttrValue::Flag(true));
-
        }
-

-
        let layout = Layout::default()
-
            .direction(Direction::Vertical)
-
            .constraints([
-
                Constraint::Length(3),
-
                Constraint::Length(3),
-
                Constraint::Length(3),
-
                Constraint::Min(3),
-
            ])
-
            .split(area);
-

-
        for (index, area) in layout.iter().enumerate().take(self.inputs.len()) {
-
            if let Some(input) = self.inputs.get_mut(index) {
-
                input.view(frame, *area);
-
            }
-
        }
+
        self.form.view(frame, area);
    }

    fn state(&self) -> State {
@@ -331,25 +322,7 @@ impl WidgetComponent for NewForm {
    }

    fn perform(&mut self, _properties: &Props, cmd: Cmd) -> CmdResult {
-
        use tuirealm::command::Direction;
-
        match cmd {
-
            Cmd::Move(Direction::Up) => {
-
                self.state.focus_previous();
-
                CmdResult::None
-
            }
-
            Cmd::Move(Direction::Down) => {
-
                self.state.focus_next();
-
                CmdResult::None
-
            }
-
            _ => {
-
                let focus = self.state.focus().unwrap_or(0);
-
                if let Some(input) = self.inputs.get_mut(focus) {
-
                    input.perform(cmd)
-
                } else {
-
                    CmdResult::None
-
                }
-
            }
-
        }
+
        self.form.perform(cmd)
    }
}

@@ -373,8 +346,8 @@ pub fn description(
    Widget::new(body)
}

-
pub fn new_form(context: &Context, theme: &Theme) -> Widget<NewForm> {
-
    let form = NewForm::new(context, theme);
+
pub fn new_form(_context: &Context, theme: &Theme) -> Widget<NewForm> {
+
    let form = NewForm::new(theme);
    Widget::new(form)
}