mirror of
https://github.com/gitui-org/gitui
synced 2026-05-22 16:38:28 +00:00
parent
2401293b66
commit
425963ca58
6 changed files with 103 additions and 2 deletions
|
|
@ -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))
|
||||
|
||||

|
||||
|
||||
### Fixed
|
||||
|
||||
|
|
|
|||
BIN
assets/scrollbar.gif
Normal file
BIN
assets/scrollbar.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 392 KiB |
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
77
src/ui/scrollbar.rs
Normal 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)
|
||||
}
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Reference in a new issue