diff options
author | Christoph Rüßler <christoph.ruessler@mailbox.org> | 2023-01-08 12:47:37 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-08 12:47:37 +0100 |
commit | 9fa5fddd93d6688606f78950ac02035212af80c1 (patch) | |
tree | 251db589a7b64ad1593b35d7bab56d427a0c13c9 /src/ui | |
parent | f29178d1b307ca536b568e375064ffba4e437ba7 (diff) |
Allow to scroll diffs horizontally (#1327)
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/mod.rs | 2 | ||||
-rw-r--r-- | src/ui/reflow.rs | 18 | ||||
-rw-r--r-- | src/ui/scrollbar.rs | 74 |
3 files changed, 70 insertions, 24 deletions
diff --git a/src/ui/mod.rs b/src/ui/mod.rs index eac3e3b6..4b1db6eb 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -6,7 +6,7 @@ pub mod style; mod syntax_text; use filetreelist::MoveSelection; -pub use scrollbar::draw_scrollbar; +pub use scrollbar::{draw_scrollbar, Orientation}; pub use scrolllist::{draw_list, draw_list_block}; pub use stateful_paragraph::{ ParagraphState, ScrollPos, StatefulParagraph, diff --git a/src/ui/reflow.rs b/src/ui/reflow.rs index a9937361..81de4b84 100644 --- a/src/ui/reflow.rs +++ b/src/ui/reflow.rs @@ -1,6 +1,6 @@ +use crate::string_utils::trim_offset; use easy_cast::Cast; use tui::text::StyledGrapheme; -use unicode_segmentation::UnicodeSegmentation; use unicode_width::UnicodeWidthStr; const NBSP: &str = "\u{00a0}"; @@ -233,22 +233,6 @@ impl<'a, 'b> LineComposer<'a> for LineTruncator<'a, 'b> { } } -/// This function will return a str slice which start at specified offset. -/// As src is a unicode str, start offset has to be calculated with each character. -fn trim_offset(src: &str, mut offset: usize) -> &str { - let mut start = 0; - for c in UnicodeSegmentation::graphemes(src, true) { - let w = c.width(); - if w <= offset { - offset -= w; - start += c.len(); - } else { - break; - } - } - &src[start..] -} - #[cfg(test)] mod test { use super::*; diff --git a/src/ui/scrollbar.rs b/src/ui/scrollbar.rs index adf4dec1..3a28fe82 100644 --- a/src/ui/scrollbar.rs +++ b/src/ui/scrollbar.rs @@ -6,32 +6,40 @@ use tui::{ buffer::Buffer, layout::{Margin, Rect}, style::Style, - symbols::{block::FULL, line::DOUBLE_VERTICAL}, + symbols::{ + block::FULL, + line::{DOUBLE_HORIZONTAL, DOUBLE_VERTICAL}, + }, widgets::Widget, Frame, }; +pub enum Orientation { + Vertical, + Horizontal, +} + /// struct Scrollbar { max: u16, pos: u16, style_bar: Style, style_pos: Style, + orientation: Orientation, } impl Scrollbar { - fn new(max: usize, pos: usize) -> Self { + fn new(max: usize, pos: usize, orientation: Orientation) -> Self { Self { max: u16::try_from(max).unwrap_or_default(), pos: u16::try_from(pos).unwrap_or_default(), style_pos: Style::default(), style_bar: Style::default(), + orientation, } } -} -impl Widget for Scrollbar { - fn render(self, area: Rect, buf: &mut Buffer) { + fn render_vertical(self, area: Rect, buf: &mut Buffer) { if area.height <= 2 { return; } @@ -67,6 +75,59 @@ impl Widget for Scrollbar { buf.set_string(right, bar_top + pos, FULL, self.style_pos); } + + fn render_horizontal(self, area: Rect, buf: &mut Buffer) { + if area.width <= 2 { + return; + } + + if self.max == 0 { + return; + } + + let bottom = area.bottom().saturating_sub(1); + if bottom <= area.top() { + return; + }; + + let (bar_left, bar_width) = { + let scrollbar_area = area.inner(&Margin { + horizontal: 1, + vertical: 0, + }); + + (scrollbar_area.left(), scrollbar_area.width) + }; + + for x in bar_left..(bar_left + bar_width) { + buf.set_string( + x, + bottom, + DOUBLE_HORIZONTAL, + self.style_bar, + ); + } + + let progress = f32::from(self.pos) / f32::from(self.max); + let progress = if progress > 1.0 { 1.0 } else { progress }; + let pos = f32::from(bar_width) * progress; + + let pos: u16 = pos.cast_nearest(); + let pos = pos.saturating_sub(1); + + buf.set_string(bar_left + pos, bottom, FULL, self.style_pos); + } +} + +impl Widget for Scrollbar { + fn render(self, area: Rect, buf: &mut Buffer) { + match &self.orientation { + Orientation::Vertical => self.render_vertical(area, buf), + Orientation::Horizontal => { + self.render_horizontal(area, buf); + } + } + } } pub fn draw_scrollbar<B: Backend>( @@ -75,8 +136,9 @@ pub fn draw_scrollbar<B: Backend>( theme: &SharedTheme, max: usize, pos: usize, + orientation: Orientation, ) { - let mut widget = Scrollbar::new(max, pos); + let mut widget = Scrollbar::new(max, pos, orientation); widget.style_pos = theme.scroll_bar_pos(); f.render_widget(widget, r); } |