Scrollbar in diff (#251)

closes #204
This commit is contained in:
Stephan Dilly 2020-08-28 18:19:44 +02:00 committed by GitHub
parent 2401293b66
commit 425963ca58
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 103 additions and 2 deletions

View file

@ -12,6 +12,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- fully **customizable key bindings** (see [KEY_CONFIG.md](KEY_CONFIG.md)) [[@yanganto](https://github.com/yanganto)] ([#109](https://github.com/extrawurst/gitui/issues/109)) ([#57](https://github.com/extrawurst/gitui/issues/57))
- support scrolling in long commit messages [[@cruessler](https://github.com/cruessler)]([#208](https://github.com/extrawurst/gitui/issues/208))
- copy lines from diffs to clipboard [[@cruessler](https://github.com/cruessler)]([#229](https://github.com/extrawurst/gitui/issues/229))
- scrollbar in long diffs ([#204](https://github.com/extrawurst/gitui/issues/204))
![scrollbar](assets/scrollbar.gif)
### Fixed

BIN
assets/scrollbar.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

View file

@ -6,7 +6,7 @@ use crate::{
keys::SharedKeyConfig,
queue::{Action, InternalEvent, NeedsUpdate, Queue, ResetItem},
strings, try_or_popup,
ui::{calc_scroll_top, style::SharedTheme},
ui::{self, calc_scroll_top, style::SharedTheme},
};
use asyncgit::{hash, sync, DiffLine, DiffLineType, FileDiff, CWD};
use bytesize::ByteSize;
@ -224,12 +224,18 @@ impl DiffComponent {
Ok(())
}
fn lines_count(&self) -> usize {
self.diff
.as_ref()
.map_or(0, |diff| diff.lines.saturating_sub(1))
}
fn modify_selection(
&mut self,
direction: Direction,
) -> Result<()> {
if let Some(diff) = &self.diff {
let max = diff.lines.saturating_sub(1) as usize;
let max = diff.lines.saturating_sub(1);
self.selection.modify(direction, max);
}
@ -583,6 +589,15 @@ impl DrawableComponent for DiffComponent {
),
r,
);
if self.focused {
ui::draw_scrollbar(
f,
r,
&self.theme,
self.lines_count(),
self.selection.get_end(),
);
}
Ok(())
}

View file

@ -1,6 +1,8 @@
mod scrollbar;
mod scrolllist;
pub mod style;
pub use scrollbar::draw_scrollbar;
pub use scrolllist::draw_list;
use tui::layout::{Constraint, Direction, Layout, Rect};

77
src/ui/scrollbar.rs Normal file
View file

@ -0,0 +1,77 @@
use super::style::SharedTheme;
use std::convert::TryFrom;
use tui::{
backend::Backend,
buffer::Buffer,
layout::{Margin, Rect},
style::Style,
symbols::{block::FULL, line::THICK_VERTICAL},
widgets::Widget,
Frame,
};
///
struct Scrollbar {
max: u16,
pos: u16,
style_bar: Style,
style_pos: Style,
}
impl Scrollbar {
fn new(max: usize, pos: usize) -> 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(),
}
}
}
impl Widget for Scrollbar {
fn render(self, area: Rect, buf: &mut Buffer) {
let right = area.right().saturating_sub(1);
if right <= area.left() {
return;
};
let area = area.inner(&Margin {
horizontal: 0,
vertical: 1,
});
if area.height <= 4 {
return;
}
if area.height > self.max {
return;
}
for y in area.top()..area.bottom() {
buf.set_string(right, y, THICK_VERTICAL, self.style_bar);
}
let progress = f32::from(self.pos) / f32::from(self.max);
let pos = f32::from(area.height.saturating_sub(1)) * progress;
//TODO: any better way for this?
#[allow(clippy::cast_sign_loss)]
#[allow(clippy::cast_possible_truncation)]
let pos = pos as u16;
buf.set_string(right, area.top() + pos, FULL, self.style_pos);
}
}
pub fn draw_scrollbar<B: Backend>(
f: &mut Frame<B>,
r: Rect,
theme: &SharedTheme,
max: usize,
pos: usize,
) {
let mut widget = Scrollbar::new(max, pos);
widget.style_pos = theme.scroll_bar_pos();
f.render_widget(widget, r)
}

View file

@ -51,6 +51,10 @@ pub struct Theme {
}
impl Theme {
pub fn scroll_bar_pos(&self) -> Style {
Style::default().fg(self.selection_bg)
}
pub fn block(&self, focus: bool) -> Style {
if focus {
Style::default()