Skip to content

Commit 13b346b

Browse files
author
Stephan Dilly
committed
fix scrolling bounds (#725)
1 parent 6ace7f8 commit 13b346b

File tree

3 files changed

+77
-29
lines changed

3 files changed

+77
-29
lines changed

src/components/revision_files.rs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,8 @@ impl DrawableComponent for RevisionFilesComponent {
193193
)
194194
.split(area);
195195

196-
let tree_height = usize::from(chunks[0].height);
196+
let tree_height =
197+
usize::from(chunks[0].height.saturating_sub(2));
197198

198199
let selection = self.tree.visual_selection();
199200
selection.map_or_else(
@@ -264,16 +265,21 @@ impl Component for RevisionFilesComponent {
264265
.order(1),
265266
);
266267

267-
out.push(
268-
CommandInfo::new(
269-
strings::commands::blame_file(&self.key_config),
270-
self.tree.selected_file().is_some(),
271-
true,
272-
)
273-
.order(order::NAV),
274-
);
275-
276-
tree_nav_cmds(&self.tree, &self.key_config, out);
268+
if matches!(self.focus, Focus::Tree) || force_all {
269+
out.push(
270+
CommandInfo::new(
271+
strings::commands::blame_file(
272+
&self.key_config,
273+
),
274+
self.tree.selected_file().is_some(),
275+
true,
276+
)
277+
.order(order::NAV),
278+
);
279+
tree_nav_cmds(&self.tree, &self.key_config, out);
280+
} else {
281+
self.current_file.commands(out, force_all);
282+
}
277283
}
278284

279285
visibility_blocking(self)

src/components/syntax_text.rs

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use super::{
44
};
55
use crate::{
66
keys::SharedKeyConfig,
7+
strings,
78
ui::{
89
self, style::SharedTheme, AsyncSyntaxJob, ParagraphState,
910
ScrollPos, StatefulParagraph,
@@ -32,7 +33,7 @@ pub struct SyntaxTextComponent {
3233
async_highlighting:
3334
AsyncSingleJob<AsyncSyntaxJob, AsyncNotification>,
3435
key_config: SharedKeyConfig,
35-
scroll_top: Cell<u16>,
36+
paragraph_state: Cell<ParagraphState>,
3637
focused: bool,
3738
theme: SharedTheme,
3839
}
@@ -50,7 +51,7 @@ impl SyntaxTextComponent {
5051
AsyncNotification::SyntaxHighlighting,
5152
),
5253
current_file: None,
53-
scroll_top: Cell::new(0),
54+
paragraph_state: Cell::new(ParagraphState::default()),
5455
focused: false,
5556
key_config,
5657
theme,
@@ -118,6 +119,36 @@ impl SyntaxTextComponent {
118119
}
119120
}
120121
}
122+
123+
fn scroll(&self, down: Option<bool>) {
124+
let mut state = self.paragraph_state.get();
125+
let new_scroll_pos = down.map_or_else(
126+
|| state.scroll().y,
127+
|down| {
128+
if down {
129+
state.scroll().y.saturating_add(1)
130+
} else {
131+
state.scroll().y.saturating_sub(1)
132+
}
133+
},
134+
);
135+
136+
let new_scroll_pos = new_scroll_pos.min(
137+
state
138+
.lines()
139+
.saturating_sub(state.height().saturating_sub(2)),
140+
);
141+
142+
if new_scroll_pos == state.scroll().y {
143+
return;
144+
}
145+
146+
state.set_scroll(ScrollPos {
147+
x: 0,
148+
y: new_scroll_pos,
149+
});
150+
self.paragraph_state.set(state);
151+
}
121152
}
122153

123154
impl DrawableComponent for SyntaxTextComponent {
@@ -148,16 +179,13 @@ impl DrawableComponent for SyntaxTextComponent {
148179
.border_style(self.theme.title(self.focused())),
149180
);
150181

151-
let mut state = ParagraphState::default();
152-
state.set_scroll(ScrollPos::new(0, self.scroll_top.get()));
182+
let mut state = self.paragraph_state.get();
153183

154184
f.render_stateful_widget(content, area, &mut state);
155185

156-
self.scroll_top.set(
157-
self.scroll_top
158-
.get()
159-
.min(state.lines().saturating_sub(area.height)),
160-
);
186+
self.paragraph_state.set(state);
187+
188+
self.scroll(None);
161189

162190
Ok(())
163191
}
@@ -166,10 +194,19 @@ impl DrawableComponent for SyntaxTextComponent {
166194
impl Component for SyntaxTextComponent {
167195
fn commands(
168196
&self,
169-
_out: &mut Vec<CommandInfo>,
170-
_force_all: bool,
197+
out: &mut Vec<CommandInfo>,
198+
force_all: bool,
171199
) -> CommandBlocking {
172-
//TODO: scrolling
200+
if self.focused() || force_all {
201+
out.push(
202+
CommandInfo::new(
203+
strings::commands::scroll(&self.key_config),
204+
true,
205+
true,
206+
)
207+
.order(strings::order::NAV),
208+
);
209+
}
173210
CommandBlocking::PassingOn
174211
}
175212

@@ -179,11 +216,9 @@ impl Component for SyntaxTextComponent {
179216
) -> Result<EventState> {
180217
if let Event::Key(key) = event {
181218
if key == self.key_config.move_down {
182-
self.scroll_top
183-
.set(self.scroll_top.get().saturating_add(1));
219+
self.scroll(Some(true));
184220
} else if key == self.key_config.move_up {
185-
self.scroll_top
186-
.set(self.scroll_top.get().saturating_sub(1));
221+
self.scroll(Some(false));
187222
}
188223
}
189224

src/ui/stateful_paragraph.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ pub struct StatefulParagraph<'a> {
4545

4646
#[derive(Debug, Default, Clone, Copy)]
4747
pub struct ScrollPos {
48-
x: u16,
49-
y: u16,
48+
pub x: u16,
49+
pub y: u16,
5050
}
5151

5252
impl ScrollPos {
@@ -61,13 +61,19 @@ pub struct ParagraphState {
6161
scroll: ScrollPos,
6262
/// after all wrapping this is the amount of lines
6363
lines: u16,
64+
/// last visible height
65+
height: u16,
6466
}
6567

6668
impl ParagraphState {
6769
pub const fn lines(self) -> u16 {
6870
self.lines
6971
}
7072

73+
pub const fn height(self) -> u16 {
74+
self.height
75+
}
76+
7177
pub const fn scroll(self) -> ScrollPos {
7278
self.scroll
7379
}
@@ -202,5 +208,6 @@ impl<'a> StatefulWidget for StatefulParagraph<'a> {
202208
}
203209

204210
state.lines = y;
211+
state.height = area.height;
205212
}
206213
}

0 commit comments

Comments
 (0)