tui: Support container focus
This commit is contained in:
parent
dcfd481424
commit
3a7cef8cea
|
|
@ -111,8 +111,8 @@ impl ViewPage for HomeView {
|
|||
) -> Result<()> {
|
||||
if let Message::NavigationChanged(index) = message {
|
||||
self.active_component = Cid::Home(HomeCid::from(index as usize));
|
||||
app.active(&self.active_component)?;
|
||||
}
|
||||
app.active(&self.active_component)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -148,16 +148,12 @@ impl ViewPage for HomeView {
|
|||
/// Issue detail page
|
||||
///
|
||||
pub struct IssuePage {
|
||||
active_component: Cid,
|
||||
issue: (IssueId, Issue),
|
||||
}
|
||||
|
||||
impl IssuePage {
|
||||
pub fn new(issue: (IssueId, Issue)) -> Self {
|
||||
IssuePage {
|
||||
active_component: Cid::Issue(IssueCid::List),
|
||||
issue,
|
||||
}
|
||||
IssuePage { issue }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -186,7 +182,7 @@ impl ViewPage for IssuePage {
|
|||
app.remount(Cid::Issue(IssueCid::Details), details, vec![])?;
|
||||
app.remount(Cid::Issue(IssueCid::Shortcuts), shortcuts, vec![])?;
|
||||
|
||||
app.active(&self.active_component)?;
|
||||
app.active(&Cid::Issue(IssueCid::List))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -212,8 +208,14 @@ impl ViewPage for IssuePage {
|
|||
let details = widget::issue::details(context, theme, (id, issue)).to_boxed();
|
||||
app.remount(Cid::Issue(IssueCid::Details), details, vec![])?;
|
||||
}
|
||||
Message::Issue(IssueMessage::FocusList) => {
|
||||
app.active(&Cid::Issue(IssueCid::List))?;
|
||||
}
|
||||
Message::Issue(IssueMessage::FocusDiscussion) => {
|
||||
app.active(&Cid::Issue(IssueCid::Discussion))?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
app.active(&self.active_component)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ pub struct Colors {
|
|||
pub context_id_fg: Color,
|
||||
pub context_id_bg: Color,
|
||||
pub context_id_author_fg: Color,
|
||||
pub container_border_fg: Color,
|
||||
pub container_border_focus_fg: Color,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
@ -105,6 +107,8 @@ pub fn default_dark() -> Theme {
|
|||
context_id_fg: Color::Cyan,
|
||||
context_id_bg: COLOR_DEFAULT_DARKEST,
|
||||
context_id_author_fg: Color::Gray,
|
||||
container_border_fg: COLOR_DEFAULT_DARKEST,
|
||||
container_border_focus_fg: COLOR_DEFAULT_DARK,
|
||||
},
|
||||
icons: Icons {
|
||||
property_divider: '∙',
|
||||
|
|
|
|||
|
|
@ -45,8 +45,8 @@ pub fn container_header(theme: &Theme, label: Widget<Label>) -> Widget<Header<1>
|
|||
Widget::new(header)
|
||||
}
|
||||
|
||||
pub fn container(_theme: &Theme, component: Box<dyn MockComponent>) -> Widget<Container> {
|
||||
let container = Container::new(component);
|
||||
pub fn container(theme: &Theme, component: Box<dyn MockComponent>) -> Widget<Container> {
|
||||
let container = Container::new(component, theme.clone());
|
||||
Widget::new(container)
|
||||
}
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ pub fn labeled_container(
|
|||
theme,
|
||||
label(&format!(" {title} ")).foreground(theme.colors.default_fg),
|
||||
);
|
||||
let container = LabeledContainer::new(header, component);
|
||||
let container = LabeledContainer::new(header, component, theme.clone());
|
||||
|
||||
Widget::new(container)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
use tuirealm::command::{Cmd, CmdResult};
|
||||
use tuirealm::props::{
|
||||
AttrValue, Attribute, BorderSides, BorderType, Color, Props, Style, TextModifiers,
|
||||
};
|
||||
use tuirealm::props::{AttrValue, Attribute, BorderSides, BorderType, Props, Style, TextModifiers};
|
||||
use tuirealm::tui::layout::{Constraint, Direction, Layout, Rect};
|
||||
use tuirealm::tui::widgets::{Block, Cell, Row};
|
||||
use tuirealm::{Frame, MockComponent, State, StateValue};
|
||||
|
|
@ -276,10 +274,20 @@ impl<const W: usize> WidgetComponent for Header<W> {
|
|||
let display = properties
|
||||
.get_or(Attribute::Display, AttrValue::Flag(true))
|
||||
.unwrap_flag();
|
||||
let focus = properties
|
||||
.get_or(Attribute::Focus, AttrValue::Flag(false))
|
||||
.unwrap_flag();
|
||||
|
||||
let color = if focus {
|
||||
self.theme.colors.container_border_focus_fg
|
||||
} else {
|
||||
self.theme.colors.container_border_fg
|
||||
};
|
||||
|
||||
if display {
|
||||
let block = HeaderBlock::default()
|
||||
.borders(BorderSides::all())
|
||||
.border_style(Style::default().fg(Color::Rgb(48, 48, 48)))
|
||||
.border_style(Style::default().fg(color))
|
||||
.border_type(BorderType::Rounded);
|
||||
frame.render_widget(block, area);
|
||||
|
||||
|
|
@ -322,11 +330,12 @@ impl<const W: usize> WidgetComponent for Header<W> {
|
|||
|
||||
pub struct Container {
|
||||
component: Box<dyn MockComponent>,
|
||||
theme: Theme,
|
||||
}
|
||||
|
||||
impl Container {
|
||||
pub fn new(component: Box<dyn MockComponent>) -> Self {
|
||||
Self { component }
|
||||
pub fn new(component: Box<dyn MockComponent>, theme: Theme) -> Self {
|
||||
Self { component, theme }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -335,6 +344,15 @@ impl WidgetComponent for Container {
|
|||
let display = properties
|
||||
.get_or(Attribute::Display, AttrValue::Flag(true))
|
||||
.unwrap_flag();
|
||||
let focus = properties
|
||||
.get_or(Attribute::Focus, AttrValue::Flag(false))
|
||||
.unwrap_flag();
|
||||
|
||||
let color = if focus {
|
||||
self.theme.colors.container_border_focus_fg
|
||||
} else {
|
||||
self.theme.colors.container_border_fg
|
||||
};
|
||||
|
||||
if display {
|
||||
// Make some space on the left
|
||||
|
|
@ -349,7 +367,7 @@ impl WidgetComponent for Container {
|
|||
|
||||
let block = Block::default()
|
||||
.borders(BorderSides::ALL)
|
||||
.border_style(Style::default().fg(Color::Rgb(48, 48, 48)))
|
||||
.border_style(Style::default().fg(color))
|
||||
.border_type(BorderType::Rounded);
|
||||
frame.render_widget(block, area);
|
||||
}
|
||||
|
|
@ -367,11 +385,16 @@ impl WidgetComponent for Container {
|
|||
pub struct LabeledContainer {
|
||||
header: Widget<Header<1>>,
|
||||
component: Box<dyn MockComponent>,
|
||||
theme: Theme,
|
||||
}
|
||||
|
||||
impl LabeledContainer {
|
||||
pub fn new(header: Widget<Header<1>>, component: Box<dyn MockComponent>) -> Self {
|
||||
Self { header, component }
|
||||
pub fn new(header: Widget<Header<1>>, component: Box<dyn MockComponent>, theme: Theme) -> Self {
|
||||
Self {
|
||||
header,
|
||||
component,
|
||||
theme,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -380,6 +403,16 @@ impl WidgetComponent for LabeledContainer {
|
|||
let display = properties
|
||||
.get_or(Attribute::Display, AttrValue::Flag(true))
|
||||
.unwrap_flag();
|
||||
let focus = properties
|
||||
.get_or(Attribute::Focus, AttrValue::Flag(false))
|
||||
.unwrap_flag();
|
||||
|
||||
let color = if focus {
|
||||
self.theme.colors.container_border_focus_fg
|
||||
} else {
|
||||
self.theme.colors.container_border_fg
|
||||
};
|
||||
|
||||
let header_height = self
|
||||
.header
|
||||
.query(Attribute::Height)
|
||||
|
|
@ -399,14 +432,17 @@ impl WidgetComponent for LabeledContainer {
|
|||
.constraints(vec![Constraint::Length(1), Constraint::Min(0)].as_ref())
|
||||
.split(layout[1]);
|
||||
// reverse draw order: child needs to be drawn first?
|
||||
|
||||
self.component.attr(Attribute::Focus, AttrValue::Flag(focus));
|
||||
self.component.view(frame, inner_layout[1]);
|
||||
|
||||
let block = Block::default()
|
||||
.borders(BorderSides::BOTTOM | BorderSides::LEFT | BorderSides::RIGHT)
|
||||
.border_style(Style::default().fg(Color::Rgb(48, 48, 48)))
|
||||
.border_style(Style::default().fg(color))
|
||||
.border_type(BorderType::Rounded);
|
||||
frame.render_widget(block, layout[1]);
|
||||
|
||||
self.header.attr(Attribute::Focus, AttrValue::Flag(focus));
|
||||
self.header.view(frame, layout[0]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -225,6 +225,16 @@ where
|
|||
.get_or(Attribute::HighlightedColor, AttrValue::Color(Color::Reset))
|
||||
.unwrap_color();
|
||||
|
||||
let focus = properties
|
||||
.get_or(Attribute::Focus, AttrValue::Flag(false))
|
||||
.unwrap_flag();
|
||||
|
||||
let color = if focus {
|
||||
self.theme.colors.container_border_focus_fg
|
||||
} else {
|
||||
self.theme.colors.container_border_fg
|
||||
};
|
||||
|
||||
let layout = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints(vec![Constraint::Length(3), Constraint::Min(1)])
|
||||
|
|
@ -241,7 +251,7 @@ where
|
|||
.block(
|
||||
Block::default()
|
||||
.borders(BorderSides::BOTTOM | BorderSides::LEFT | BorderSides::RIGHT)
|
||||
.border_style(Style::default().fg(Color::Rgb(48, 48, 48)))
|
||||
.border_style(Style::default().fg(color))
|
||||
.border_type(BorderType::Rounded),
|
||||
)
|
||||
.highlight_style(Style::default().bg(highlight))
|
||||
|
|
@ -253,7 +263,10 @@ where
|
|||
self.widths,
|
||||
self.theme.clone(),
|
||||
));
|
||||
|
||||
header.attr(Attribute::Focus, AttrValue::Flag(focus));
|
||||
header.view(frame, layout[0]);
|
||||
|
||||
frame.render_stateful_widget(table, layout[1], &mut TableState::from(&self.state));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -106,14 +106,19 @@ impl IssueBrowser {
|
|||
}
|
||||
|
||||
impl WidgetComponent for IssueBrowser {
|
||||
fn view(&mut self, _properties: &Props, frame: &mut Frame, area: Rect) {
|
||||
fn view(&mut self, properties: &Props, frame: &mut Frame, area: Rect) {
|
||||
let shortcuts_h = self
|
||||
.shortcuts
|
||||
.query(Attribute::Height)
|
||||
.unwrap_or(AttrValue::Size(0))
|
||||
.unwrap_size();
|
||||
let focus = properties
|
||||
.get_or(Attribute::Focus, AttrValue::Flag(false))
|
||||
.unwrap_flag();
|
||||
|
||||
let layout = layout::root_component(area, shortcuts_h);
|
||||
|
||||
self.table.attr(Attribute::Focus, AttrValue::Flag(focus));
|
||||
self.table.view(frame, layout[0]);
|
||||
self.shortcuts.view(frame, layout[1])
|
||||
}
|
||||
|
|
@ -187,14 +192,19 @@ impl PatchBrowser {
|
|||
}
|
||||
|
||||
impl WidgetComponent for PatchBrowser {
|
||||
fn view(&mut self, _properties: &Props, frame: &mut Frame, area: Rect) {
|
||||
fn view(&mut self, properties: &Props, frame: &mut Frame, area: Rect) {
|
||||
let shortcuts_h = self
|
||||
.shortcuts
|
||||
.query(Attribute::Height)
|
||||
.unwrap_or(AttrValue::Size(0))
|
||||
.unwrap_size();
|
||||
let focus = properties
|
||||
.get_or(Attribute::Focus, AttrValue::Flag(false))
|
||||
.unwrap_flag();
|
||||
|
||||
let layout = layout::root_component(area, shortcuts_h);
|
||||
|
||||
self.table.attr(Attribute::Focus, AttrValue::Flag(focus));
|
||||
self.table.view(frame, layout[0]);
|
||||
self.shortcuts.view(frame, layout[1]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,12 @@ impl LargeList {
|
|||
}
|
||||
|
||||
impl WidgetComponent for LargeList {
|
||||
fn view(&mut self, _properties: &Props, frame: &mut Frame, area: Rect) {
|
||||
fn view(&mut self, properties: &Props, frame: &mut Frame, area: Rect) {
|
||||
let focus = properties
|
||||
.get_or(Attribute::Focus, AttrValue::Flag(false))
|
||||
.unwrap_flag();
|
||||
|
||||
self.list.attr(Attribute::Focus, AttrValue::Flag(focus));
|
||||
self.list.view(frame, area);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue