diff --git a/radicle-tui/src/ui.rs b/radicle-tui/src/ui.rs index 35861e75..10b9f833 100644 --- a/radicle-tui/src/ui.rs +++ b/radicle-tui/src/ui.rs @@ -1,5 +1,6 @@ pub mod cob; pub mod components; +pub mod ext; pub mod layout; pub mod state; pub mod theme; diff --git a/radicle-tui/src/ui/ext.rs b/radicle-tui/src/ui/ext.rs new file mode 100644 index 00000000..549ee2a1 --- /dev/null +++ b/radicle-tui/src/ui/ext.rs @@ -0,0 +1,113 @@ +use tuirealm::tui::buffer::Buffer; +use tuirealm::tui::layout::Rect; +use tuirealm::tui::style::Style; +use tuirealm::tui::widgets::{BorderType, Borders, Widget}; + +pub struct HeaderBlock { + /// Visible borders + borders: Borders, + /// Border style + border_style: Style, + /// Type of the border. The default is plain lines but one can choose to have rounded corners + /// or doubled lines instead. + border_type: BorderType, + /// Widget style + style: Style, +} + +impl Default for HeaderBlock { + fn default() -> HeaderBlock { + HeaderBlock { + borders: Borders::NONE, + border_style: Default::default(), + border_type: BorderType::Plain, + style: Default::default(), + } + } +} + +impl HeaderBlock { + pub fn border_style(mut self, style: Style) -> HeaderBlock { + self.border_style = style; + self + } + + pub fn style(mut self, style: Style) -> HeaderBlock { + self.style = style; + self + } + + pub fn borders(mut self, flag: Borders) -> HeaderBlock { + self.borders = flag; + self + } + + pub fn border_type(mut self, border_type: BorderType) -> HeaderBlock { + self.border_type = border_type; + self + } +} + +impl Widget for HeaderBlock { + fn render(self, area: Rect, buf: &mut Buffer) { + if area.area() == 0 { + return; + } + buf.set_style(area, self.style); + let symbols = BorderType::line_symbols(self.border_type); + + // Sides + if self.borders.intersects(Borders::LEFT) { + for y in area.top()..area.bottom() { + buf.get_mut(area.left(), y) + .set_symbol(symbols.vertical) + .set_style(self.border_style); + } + } + if self.borders.intersects(Borders::TOP) { + for x in area.left()..area.right() { + buf.get_mut(x, area.top()) + .set_symbol(symbols.horizontal) + .set_style(self.border_style); + } + } + if self.borders.intersects(Borders::RIGHT) { + let x = area.right() - 1; + for y in area.top()..area.bottom() { + buf.get_mut(x, y) + .set_symbol(symbols.vertical) + .set_style(self.border_style); + } + } + if self.borders.intersects(Borders::BOTTOM) { + let y = area.bottom() - 1; + for x in area.left()..area.right() { + buf.get_mut(x, y) + .set_symbol(symbols.horizontal) + .set_style(self.border_style); + } + } + + // Corners + if self.borders.contains(Borders::RIGHT | Borders::BOTTOM) { + buf.get_mut(area.right() - 1, area.bottom() - 1) + .set_symbol(symbols.vertical_left) + .set_style(self.border_style); + } + if self.borders.contains(Borders::RIGHT | Borders::TOP) { + buf.get_mut(area.right() - 1, area.top()) + .set_symbol(symbols.top_right) + .set_style(self.border_style); + } + if self.borders.contains(Borders::LEFT | Borders::BOTTOM) { + buf.get_mut(area.left(), area.bottom() - 1) + .set_symbol(symbols.vertical_right) + .set_style(self.border_style); + } + if self.borders.contains(Borders::LEFT | Borders::TOP) { + buf.get_mut(area.left(), area.top()) + .set_symbol(symbols.top_left) + .set_style(self.border_style); + } + } +}