aboutsummaryrefslogtreecommitdiff
path: root/helix-term/src/ui/popup.rs
diff options
context:
space:
mode:
Diffstat (limited to 'helix-term/src/ui/popup.rs')
-rw-r--r--helix-term/src/ui/popup.rs61
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");