on master help sign in
ui: menu: Adjust scroll via required_size area caching.
commitddcf5156c0260debc522b0420f93e0c523697eb4 authorBlaž Hrastnik <blaz@mxxn.io> dateMon 8 Mar 2021, 17:13 (6 years ago) parent5ea610c
1 file changed+28−17
helix-term/src/ui/menu.rs+28−17
helix-term/src/ui/menu.rs+28−17
@@ -8,7 +8,6 @@ use tui::{
88};
99
1010use std::borrow::Cow;
11−use std::cell::Cell;
1211
1312use helix_core::Position;
1413use helix_view::Editor;
@@ -24,7 +23,8 @@ pub struct Menu<T> {
2423 format_fn: Box<dyn Fn(&T) -> Cow<str>>,
2524 callback_fn: Box<dyn Fn(&mut Editor, Option<&T>, MenuEvent)>,
2625
27− scroll: Cell<usize>,
26+ scroll: usize,
27+ size: (u16, u16),
2828}
2929
3030impl<T> Menu<T> {
@@ -40,7 +40,8 @@ impl<T> Menu<T> {
4040 cursor: None,
4141 format_fn: Box::new(format_fn),
4242 callback_fn: Box::new(callback_fn),
43− scroll: Cell::new(0),
43+ scroll: 0,
44+ size: (0, 0),
4445 }
4546 }
4647
@@ -48,11 +49,28 @@ impl<T> Menu<T> {
4849 // TODO: wrap around to end
4950 let pos = self.cursor.map(|i| i.saturating_sub(1)).unwrap_or(0) % self.options.len();
5051 self.cursor = Some(pos);
52+ self.adjust_scroll();
5153 }
5254
5355 pub fn move_down(&mut self) {
5456 let pos = self.cursor.map(|i| i + 1).unwrap_or(0) % self.options.len();
5557 self.cursor = Some(pos);
58+ self.adjust_scroll();
59+ }
60+
61+ fn adjust_scroll(&mut self) {
62+ let win_height = self.size.1 as usize;
63+ if let Some(cursor) = self.cursor {
64+ let mut scroll = self.scroll;
65+ if cursor > (win_height + scroll).saturating_sub(1) {
66+ // scroll down
67+ scroll += cursor - (win_height + scroll).saturating_sub(1)
68+ } else if cursor < scroll {
69+ // scroll up
70+ scroll = cursor
71+ }
72+ self.scroll = scroll;
73+ }
5674 }
5775
5876 pub fn selection(&self) -> Option<&T> {
@@ -156,30 +174,23 @@ impl<T> Component for Menu<T> {
156174 let height = std::cmp::min(self.options.len(), MAX);
157175 let height = std::cmp::min(height, viewport.1 as usize);
158176
159− Some((width as u16, height as u16))
177+ self.size = (width as u16, height as u16);
178+
179+ // adjust scroll offsets if size changed
180+ self.adjust_scroll();
181+
182+ Some(self.size)
160183 }
161184
162185 fn render(&self, area: Rect, surface: &mut Surface, cx: &mut Context) {
163186 let style = Style::default().fg(Color::Rgb(164, 160, 232)); // lavender
164187 let selected = Style::default().fg(Color::Rgb(255, 255, 255));
165188
166− // TODO: instead of a cell, all these numbers should be precomputed in handle_event + init
167− let mut scroll = self.scroll.get();
189+ let scroll = self.scroll;
168190 let len = self.options.len();
169191
170192 let win_height = area.height as usize;
171193
172− if let Some(cursor) = self.cursor {
173− if cursor > (win_height + scroll).saturating_sub(1) {
174− // scroll down
175− scroll += cursor - (win_height + scroll).saturating_sub(1)
176− } else if cursor < scroll {
177− // scroll up
178− scroll = cursor
179− }
180− self.scroll.set(scroll);
181− }
182−
183194 fn div_ceil(a: usize, b: usize) -> usize {
184195 (a + b - 1) / a
185196 }