diff --git a/terminal-tui/src/components.rs b/terminal-tui/src/components.rs index 031a1020..ee735c96 100644 --- a/terminal-tui/src/components.rs +++ b/terminal-tui/src/components.rs @@ -468,3 +468,153 @@ where ) } } + +/// A single-line component, that displays multiple spans containing +/// context information. +pub struct Context { + props: Props, +} + +impl Default for Context { + fn default() -> Self { + Self { + props: Props::default(), + } + .height(1) + } +} + +impl Context { + pub fn context(mut self, context: String) -> Self { + self.attr(Attribute::Custom("context"), AttrValue::String(context)); + self + } + + pub fn id(mut self, id: String) -> Self { + self.attr(Attribute::Custom("id"), AttrValue::String(id)); + self + } + + pub fn title(mut self, title: String) -> Self { + self.attr(Attribute::Custom("title"), AttrValue::String(title)); + self + } + + pub fn author(mut self, author: String) -> Self { + self.attr(Attribute::Custom("author"), AttrValue::String(author)); + self + } + + pub fn count(mut self, count: String) -> Self { + self.attr(Attribute::Custom("count"), AttrValue::String(count)); + self + } + + pub fn height(mut self, h: u16) -> Self { + self.attr(Attribute::Height, AttrValue::Size(h)); + self + } +} + +impl MockComponent for Context { + fn view(&mut self, render: &mut Frame, area: Rect) { + if self.props.get_or(Attribute::Display, AttrValue::Flag(true)) == AttrValue::Flag(true) { + let context = self + .props + .get_or( + Attribute::Custom("context"), + AttrValue::String(String::new()), + ) + .unwrap_string(); + let id = self + .props + .get_or(Attribute::Custom("id"), AttrValue::String(String::new())) + .unwrap_string(); + let title = self + .props + .get_or(Attribute::Custom("title"), AttrValue::String(String::new())) + .unwrap_string(); + let author = self + .props + .get_or( + Attribute::Custom("author"), + AttrValue::String(String::new()), + ) + .unwrap_string(); + let count = self + .props + .get_or(Attribute::Custom("count"), AttrValue::String(String::new())) + .unwrap_string(); + + let context_w = context.len() as u16; + let id_w = id.len() as u16; + let author_w = author.len() as u16; + let count_w = count.len() as u16; + let title_w = area + .width + .saturating_sub(context_w + id_w + count_w + author_w); + + let area = TuiLayout::default() + .direction(LayoutDirection::Horizontal) + .constraints( + [ + Constraint::Length(context_w), + Constraint::Length(id_w), + Constraint::Length(title_w), + Constraint::Length(author_w), + Constraint::Length(count_w), + ] + .as_ref(), + ) + .split(area); + + let context = + Paragraph::new(context).style(Style::default().bg(Color::Rgb(238, 111, 248))); + render.render_widget(context, area[0]); + + let id = Paragraph::new(id).style( + Style::default() + .fg(Color::Rgb(117, 113, 249)) + .bg(Color::Rgb(40, 40, 40)), + ); + render.render_widget(id, area[1]); + + let title = Paragraph::new(title).style( + Style::default() + .fg(Color::Rgb(70, 70, 70)) + .bg(Color::Rgb(40, 40, 40)), + ); + render.render_widget(title, area[2]); + + let author = Paragraph::new(author).style( + Style::default() + .fg(Color::Rgb(117, 113, 249)) + .bg(Color::Rgb(40, 40, 40)), + ); + render.render_widget(author, area[3]); + + let count = Paragraph::new(count).style( + Style::default() + .fg(Color::Rgb(70, 70, 70)) + .bg(Color::Rgb(50, 50, 50)), + ); + render.render_widget(count, area[4]); + } + } + + fn query(&self, attr: Attribute) -> Option { + self.props.get(attr) + } + + fn attr(&mut self, attr: Attribute, value: AttrValue) { + self.props.set(attr, value) + } + + fn state(&self) -> State { + State::None + } + + fn perform(&mut self, _cmd: Cmd) -> CmdResult { + CmdResult::None + } +}