diff options
author | Dmitry Sharshakov | 2021-09-25 20:14:59 +0000 |
---|---|---|
committer | Dmitry Sharshakov | 2021-09-25 20:14:59 +0000 |
commit | bf53aff27d2d90b41bab01f4d628f0bd9fbcd589 (patch) | |
tree | 568d745540acd05ae7526e8a3eed7ee8e31e3cea /helix-term/src/ui/popup.rs | |
parent | 413e477dc2d4792596f99979140d2879ec3d4f4f (diff) | |
parent | df55eaae69d0388de26448e82f9ded483fca2f44 (diff) |
Merge branch 'master' into debug
Diffstat (limited to 'helix-term/src/ui/popup.rs')
-rw-r--r-- | helix-term/src/ui/popup.rs | 61 |
1 files changed, 38 insertions, 23 deletions
diff --git a/helix-term/src/ui/popup.rs b/helix-term/src/ui/popup.rs index e126c845..1bab1eae 100644 --- a/helix-term/src/ui/popup.rs +++ b/helix-term/src/ui/popup.rs @@ -16,8 +16,6 @@ pub struct Popup<T: Component> { } impl<T: Component> Popup<T> { - // TODO: it's like a slimmed down picker, share code? (picker = menu + prompt with different - // rendering) pub fn new(contents: T) -> Self { Self { contents, @@ -31,6 +29,39 @@ impl<T: Component> Popup<T> { self.position = pos; } + pub fn get_rel_position(&mut self, viewport: Rect, cx: &Context) -> (u16, u16) { + let position = self + .position + .get_or_insert_with(|| cx.editor.cursor().0.unwrap_or_default()); + + let (width, height) = self.size; + + // if there's a orientation preference, use that + // if we're on the top part of the screen, do below + // if we're on the bottom part, do above + + // -- make sure frame doesn't stick out of bounds + let mut rel_x = position.col as u16; + let mut rel_y = position.row as u16; + if viewport.width <= rel_x + width { + rel_x = rel_x.saturating_sub((rel_x + width).saturating_sub(viewport.width)); + } + + // TODO: be able to specify orientation preference. We want above for most popups, below + // for menus/autocomplete. + if viewport.height > rel_y + height { + rel_y += 1 // position below point + } else { + rel_y = rel_y.saturating_sub(height) // position above point + } + + (rel_x, rel_y) + } + + pub fn get_size(&self) -> (u16, u16) { + (self.size.0, self.size.1) + } + pub fn scroll(&mut self, offset: usize, direction: bool) { if direction { self.scroll += offset; @@ -106,31 +137,15 @@ impl<T: Component> Component for Popup<T> { } fn render(&mut self, viewport: Rect, surface: &mut Surface, cx: &mut Context) { - cx.scroll = Some(self.scroll); + // trigger required_size so we recalculate if the child changed + self.required_size((viewport.width, viewport.height)); - let position = self - .position - .get_or_insert_with(|| cx.editor.cursor().0.unwrap_or_default()); - - let (width, height) = self.size; - - // -- make sure frame doesn't stick out of bounds - let mut rel_x = position.col as u16; - let mut rel_y = position.row as u16; - if viewport.width <= rel_x + width { - rel_x = rel_x.saturating_sub((rel_x + width).saturating_sub(viewport.width)); - }; + cx.scroll = Some(self.scroll); - // TODO: be able to specify orientation preference. We want above for most popups, below - // for menus/autocomplete. - if height <= rel_y { - rel_y = rel_y.saturating_sub(height) // position above point - } else { - rel_y += 1 // position below point - } + let (rel_x, rel_y) = self.get_rel_position(viewport, cx); // clip to viewport - let area = viewport.intersection(Rect::new(rel_x, rel_y, width, height)); + let area = viewport.intersection(Rect::new(rel_x, rel_y, self.size.0, self.size.1)); // clear area let background = cx.editor.theme.get("ui.popup"); |