summaryrefslogtreecommitdiffstats
path: root/src/ui
diff options
context:
space:
mode:
authorChristoph Rüßler <christoph.ruessler@mailbox.org>2023-01-08 12:47:37 +0100
committerGitHub <noreply@github.com>2023-01-08 12:47:37 +0100
commit9fa5fddd93d6688606f78950ac02035212af80c1 (patch)
tree251db589a7b64ad1593b35d7bab56d427a0c13c9 /src/ui
parentf29178d1b307ca536b568e375064ffba4e437ba7 (diff)
Allow to scroll diffs horizontally (#1327)
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/mod.rs2
-rw-r--r--src/ui/reflow.rs18
-rw-r--r--src/ui/scrollbar.rs74
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);
}