diff options
author | Manos Mertzianis | 2022-11-15 14:15:52 +0000 |
---|---|---|
committer | GitHub | 2022-11-15 14:15:52 +0000 |
commit | 77be98c78321cc2643f23f0b16889417ea9b0596 (patch) | |
tree | 2c3706d6dc56da5d6336f95c6ad72ccf49d1a1c6 /helix-term/src/ui/popup.rs | |
parent | 3b7760dfb0cdb547ff8c94f7685554f59d16bf0a (diff) |
Popup scrollbar (#4449)
* init
* cargo fmt
* optimisation of the scrollbar render both for Menu and Popup. Toggling off scrollbar for Popup<Menu>, since Menu has its own
* rendering scroll track
* removed unnecessary cast
* improve memory allocation
* small correction
Diffstat (limited to 'helix-term/src/ui/popup.rs')
-rw-r--r-- | helix-term/src/ui/popup.rs | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/helix-term/src/ui/popup.rs b/helix-term/src/ui/popup.rs index 3c140da4..62a6785a 100644 --- a/helix-term/src/ui/popup.rs +++ b/helix-term/src/ui/popup.rs @@ -22,6 +22,7 @@ pub struct Popup<T: Component> { auto_close: bool, ignore_escape_key: bool, id: &'static str, + has_scrollbar: bool, } impl<T: Component> Popup<T> { @@ -37,6 +38,7 @@ impl<T: Component> Popup<T> { auto_close: false, ignore_escape_key: false, id, + has_scrollbar: true, } } @@ -128,6 +130,14 @@ impl<T: Component> Popup<T> { } } + /// Toggles the Popup's scrollbar. + /// Consider disabling the scrollbar in case the child + /// already has its own. + pub fn with_scrollbar(mut self, enable_scrollbar: bool) -> Self { + self.has_scrollbar = enable_scrollbar; + self + } + pub fn contents(&self) -> &T { &self.contents } @@ -228,6 +238,40 @@ impl<T: Component> Component for Popup<T> { let inner = area.inner(&self.margin); self.contents.render(inner, surface, cx); + + // render scrollbar if contents do not fit + if self.has_scrollbar { + let win_height = inner.height as usize; + let len = self.child_size.1 as usize; + let fits = len <= win_height; + let scroll = self.scroll; + let scroll_style = cx.editor.theme.get("ui.menu.scroll"); + + const fn div_ceil(a: usize, b: usize) -> usize { + (a + b - 1) / b + } + + if !fits { + let scroll_height = div_ceil(win_height.pow(2), len).min(win_height); + let scroll_line = (win_height - scroll_height) * scroll + / std::cmp::max(1, len.saturating_sub(win_height)); + + let mut cell; + for i in 0..win_height { + cell = &mut surface[(inner.right() - 1, inner.top() + i as u16)]; + + cell.set_symbol("▐"); // right half block + + if scroll_line <= i && i < scroll_line + scroll_height { + // Draw scroll thumb + cell.set_fg(scroll_style.fg.unwrap_or(helix_view::theme::Color::Reset)); + } else { + // Draw scroll track + cell.set_fg(scroll_style.bg.unwrap_or(helix_view::theme::Color::Reset)); + } + } + } + } } fn id(&self) -> Option<&'static str> { |