Skip to content

Commit 112b5c8

Browse files
author
Stephan Dilly
committed
better scrolling in diff (closes #52)
1 parent dd69d9b commit 112b5c8

File tree

2 files changed

+61
-45
lines changed

2 files changed

+61
-45
lines changed

Diff for: CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88

99
### Changed
1010
- file trees: `arrow-right` on expanded folder moves down into folder
11+
- better scrolling in diff ([#52](https://github.com/extrawurst/gitui/issues/52))
1112

1213
### Fixed
1314
- reset file inside folder failed when running `gitui` in a subfolder too ([#118](https://github.com/extrawurst/gitui/issues/118))

Diff for: src/components/diff.rs

+60-45
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::{
44
keys,
55
queue::{InternalEvent, Queue},
66
strings,
7-
ui::style::Theme,
7+
ui::{calc_scroll_top, style::Theme},
88
};
99
use asyncgit::{hash, DiffLine, DiffLineType, FileDiff};
1010
use crossterm::event::Event;
@@ -30,11 +30,12 @@ struct Current {
3030
///
3131
pub struct DiffComponent {
3232
diff: FileDiff,
33-
scroll: usize,
34-
current_height: u16,
33+
selection: usize,
34+
selected_hunk: Option<usize>,
35+
current_size: (u16, u16),
3536
focused: bool,
3637
current: Current,
37-
selected_hunk: Option<usize>,
38+
scroll_top: usize,
3839
queue: Option<Queue>,
3940
theme: Theme,
4041
}
@@ -48,8 +49,9 @@ impl DiffComponent {
4849
current: Current::default(),
4950
selected_hunk: None,
5051
diff: FileDiff::default(),
51-
scroll: 0,
52-
current_height: 0,
52+
current_size: (0, 0),
53+
selection: 0,
54+
scroll_top: 0,
5355
theme: *theme,
5456
}
5557
}
@@ -65,10 +67,9 @@ impl DiffComponent {
6567
pub fn clear(&mut self) -> Result<()> {
6668
self.current = Current::default();
6769
self.diff = FileDiff::default();
68-
self.scroll = 0;
69-
70-
self.selected_hunk =
71-
Self::find_selected_hunk(&self.diff, self.scroll)?;
70+
self.scroll_top = 0;
71+
self.selection = 0;
72+
self.selected_hunk = None;
7273

7374
Ok(())
7475
}
@@ -88,38 +89,42 @@ impl DiffComponent {
8889
hash,
8990
};
9091
self.diff = diff;
91-
self.scroll = 0;
92+
self.scroll_top = 0;
93+
self.selection = 0;
9294

9395
self.selected_hunk =
94-
Self::find_selected_hunk(&self.diff, self.scroll)?;
96+
Self::find_selected_hunk(&self.diff, self.selection)?;
9597
}
9698

9799
Ok(())
98100
}
99101

100-
fn scroll(&mut self, scroll: ScrollType) -> Result<()> {
101-
let old = self.scroll;
102+
fn move_selection(
103+
&mut self,
104+
move_type: ScrollType,
105+
) -> Result<()> {
106+
let old = self.selection;
102107

103-
let scroll_max = self.diff.lines.saturating_sub(1) as usize;
108+
let max = self.diff.lines.saturating_sub(1) as usize;
104109

105-
self.scroll = match scroll {
106-
ScrollType::Down => self.scroll.saturating_add(1),
107-
ScrollType::Up => self.scroll.saturating_sub(1),
110+
self.selection = match move_type {
111+
ScrollType::Down => old.saturating_add(1),
112+
ScrollType::Up => old.saturating_sub(1),
108113
ScrollType::Home => 0,
109-
ScrollType::End => scroll_max,
110-
ScrollType::PageDown => self.scroll.saturating_add(
111-
self.current_height.saturating_sub(1) as usize,
114+
ScrollType::End => max,
115+
ScrollType::PageDown => self.selection.saturating_add(
116+
self.current_size.1.saturating_sub(1) as usize,
112117
),
113-
ScrollType::PageUp => self.scroll.saturating_sub(
114-
self.current_height.saturating_sub(1) as usize,
118+
ScrollType::PageUp => self.selection.saturating_sub(
119+
self.current_size.1.saturating_sub(1) as usize,
115120
),
116121
};
117122

118-
self.scroll = cmp::min(scroll_max, self.scroll);
123+
self.selection = cmp::min(max, self.selection);
119124

120-
if old != self.scroll {
125+
if old != self.selection {
121126
self.selected_hunk =
122-
Self::find_selected_hunk(&self.diff, self.scroll)?;
127+
Self::find_selected_hunk(&self.diff, self.selection)?;
123128
}
124129

125130
Ok(())
@@ -149,9 +154,9 @@ impl DiffComponent {
149154
}
150155

151156
fn get_text(&self, width: u16, height: u16) -> Result<Vec<Text>> {
152-
let selection = self.scroll;
153-
let height_d2 = (height / 2) as usize;
154-
let min = self.scroll.saturating_sub(height_d2);
157+
let selection = self.selection;
158+
159+
let min = self.scroll_top;
155160
let max = min + height as usize;
156161

157162
let mut res = Vec::new();
@@ -290,19 +295,29 @@ impl DrawableComponent for DiffComponent {
290295
f: &mut Frame<B>,
291296
r: Rect,
292297
) -> Result<()> {
293-
self.current_height = r.height.saturating_sub(2);
298+
self.current_size =
299+
(r.width.saturating_sub(2), r.height.saturating_sub(2));
300+
301+
self.scroll_top = calc_scroll_top(
302+
self.scroll_top,
303+
self.current_size.1 as usize,
304+
self.selection,
305+
);
306+
294307
let title =
295308
format!("{}{}", strings::TITLE_DIFF, self.current.path);
296309
f.render_widget(
297-
Paragraph::new(self.get_text(r.width, r.height)?.iter())
298-
.block(
299-
Block::default()
300-
.title(title.as_str())
301-
.borders(Borders::ALL)
302-
.border_style(self.theme.block(self.focused))
303-
.title_style(self.theme.title(self.focused)),
304-
)
305-
.alignment(Alignment::Left),
310+
Paragraph::new(
311+
self.get_text(r.width, self.current_size.1)?.iter(),
312+
)
313+
.block(
314+
Block::default()
315+
.title(title.as_str())
316+
.borders(Borders::ALL)
317+
.border_style(self.theme.block(self.focused))
318+
.title_style(self.theme.title(self.focused)),
319+
)
320+
.alignment(Alignment::Left),
306321
r,
307322
);
308323

@@ -352,27 +367,27 @@ impl Component for DiffComponent {
352367
if let Event::Key(e) = ev {
353368
return match e {
354369
keys::MOVE_DOWN => {
355-
self.scroll(ScrollType::Down)?;
370+
self.move_selection(ScrollType::Down)?;
356371
Ok(true)
357372
}
358373
keys::SHIFT_DOWN | keys::END => {
359-
self.scroll(ScrollType::End)?;
374+
self.move_selection(ScrollType::End)?;
360375
Ok(true)
361376
}
362377
keys::HOME | keys::SHIFT_UP => {
363-
self.scroll(ScrollType::Home)?;
378+
self.move_selection(ScrollType::Home)?;
364379
Ok(true)
365380
}
366381
keys::MOVE_UP => {
367-
self.scroll(ScrollType::Up)?;
382+
self.move_selection(ScrollType::Up)?;
368383
Ok(true)
369384
}
370385
keys::PAGE_UP => {
371-
self.scroll(ScrollType::PageUp)?;
386+
self.move_selection(ScrollType::PageUp)?;
372387
Ok(true)
373388
}
374389
keys::PAGE_DOWN => {
375-
self.scroll(ScrollType::PageDown)?;
390+
self.move_selection(ScrollType::PageDown)?;
376391
Ok(true)
377392
}
378393
keys::ENTER if !self.is_immutable() => {

0 commit comments

Comments
 (0)