on master help sign in
ui: Calculate popup rendering and sizing.
11c4e0bBlaž Hrastnik
helix-term/src/commands.rs−1
@@ -1181,7 +1181,6 @@ pub fn hover(cx: &mut Context) {
1181 cx.callback = Some(Box::new(
1181 cx.callback = Some(Box::new(
1182 move |compositor: &mut Compositor, editor: &mut Editor| {
1182 move |compositor: &mut Compositor, editor: &mut Editor| {
1183 if let Some(mut pos) = editor.cursor_position() {
1183 if let Some(mut pos) = editor.cursor_position() {
1184− pos.row += 1; // shift down by one row
1185 popup.set_position(pos);
1184 popup.set_position(pos);
1186 };
1185 };
1187
1186
helix-term/src/ui/popup.rs+29−8
@@ -12,6 +12,9 @@ use std::borrow::Cow;
12use helix_core::Position;
12use helix_core::Position;
13use helix_view::Editor;
13use helix_view::Editor;
14
14
15+// TODO: share logic with Menu, it's essentially Popup(render_fn), but render fn needs to return
16+// a width/height hint. maybe Popup(Box<Component>)
17+
15pub struct Popup {
18pub struct Popup {
16 contents: String,
19 contents: String,
17 position: Position,
20 position: Position,
@@ -64,11 +67,31 @@ impl Component for Popup {
64 // EventResult::Consumed(None)
67 // EventResult::Consumed(None)
65 EventResult::Consumed(None)
68 EventResult::Consumed(None)
66 }
69 }
67− fn render(&self, area: Rect, surface: &mut Surface, cx: &mut Context) {
70+ fn render(&self, viewport: Rect, surface: &mut Surface, cx: &mut Context) {
68− // render a box at x, y. Width equal to max width of item.
71+ use tui::text::Text;
69− const MAX: usize = 15;
72+ use tui::widgets::{Paragraph, Widget, Wrap};
70− let rows = std::cmp::min(self.contents.lines().count(), MAX) as u16; // inefficient
73+
74+ let contents = Text::from(self.contents.clone());
75+
76+ let width = contents.width().min(150) as u16;
77+ let height = contents.height().min(13) as u16;
78+
79+ // -- make sure frame doesn't stick out of bounds
71− let area = Rect::new(self.position.col as u16, self.position.row as u16, 80, rows);
80+ let mut rel_x = self.position.col as u16;
81+ let mut rel_y = self.position.row as u16;
82+ if viewport.width <= rel_x + width {
83+ rel_x -= ((rel_x + width) - viewport.width)
84+ };
85+
86+ if height <= rel_y {
87+ rel_y -= height // position above point
88+ } else {
89+ rel_y += 1 // position below point
90+ }
91+
92+ let area = Rect::new(rel_x, rel_y, width, height);
93+ // clip to viewport
94+ let area = viewport.intersection(Rect::new(rel_x, rel_y, width, height));
72
95
73 // clear area
96 // clear area
74 let background = cx.editor.theme.get("ui.popup");
97 let background = cx.editor.theme.get("ui.popup");
@@ -85,10 +108,8 @@ impl Component for Popup {
85
108
86 let style = Style::default().fg(Color::Rgb(164, 160, 232)); // lavender
109 let style = Style::default().fg(Color::Rgb(164, 160, 232)); // lavender
87
110
88− use tui::text::Text;
89− use tui::widgets::{Paragraph, Widget, Wrap};
90− let contents = Text::from(self.contents.clone());
91 let par = Paragraph::new(contents).wrap(Wrap { trim: false });
111 let par = Paragraph::new(contents).wrap(Wrap { trim: false });
112+ // .scroll(x, y) offsets
92
113
93 par.render(area, surface);
114 par.render(area, surface);
94 }
115 }