diff options
-rw-r--r-- | helix-term/src/ui/editor.rs | 3 | ||||
-rw-r--r-- | helix-term/src/ui/info.rs | 36 | ||||
-rw-r--r-- | helix-view/src/graphics.rs | 27 |
3 files changed, 51 insertions, 15 deletions
diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 496edf42..ffe755e6 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -699,7 +699,8 @@ impl Component for EditorView { match event { Event::Resize(width, height) => { // HAXX: offset the render area height by 1 to account for prompt/commandline - cx.editor.resize(Rect::new(0, 0, width, height - 1)); + cx.editor + .resize(Rect::new(0, 0, width, height.saturating_sub(1))); EventResult::Consumed(None) } Event::Key(key) => { diff --git a/helix-term/src/ui/info.rs b/helix-term/src/ui/info.rs index 36b096db..6e810b86 100644 --- a/helix-term/src/ui/info.rs +++ b/helix-term/src/ui/info.rs @@ -7,24 +7,32 @@ use tui::widgets::{Block, Borders, Widget}; impl Component for Info { fn render(&self, viewport: Rect, surface: &mut Surface, cx: &mut Context) { let style = cx.editor.theme.get("ui.popup"); + + // Calculate the area of the terminal to modify. Because we want to + // render at the bottom right, we use the viewport's width and height + // which evaluate to the most bottom right coordinate. + let (width, height) = (self.width + 2, self.height + 2); + let area = viewport.intersection(Rect::new( + viewport.width.saturating_sub(width), + viewport.height.saturating_sub(height + 2), + width, + height, + )); + surface.clear_with(area, style); + let block = Block::default() .title(self.title.as_str()) .borders(Borders::ALL) .border_style(style); - let Info { width, height, .. } = self; - let (w, h) = (*width + 2, *height + 2); - // -2 to subtract command line + statusline. a bit of a hack, because of splits. - let area = viewport.intersection(Rect::new( - viewport.width.saturating_sub(w), - viewport.height.saturating_sub(h + 2), - w, - h, - )); - surface.clear_with(area, style); - let Rect { x, y, .. } = block.inner(area); - for (y, line) in (y..).zip(self.text.lines()) { - surface.set_string(x, y, line, style); - } + let inner = block.inner(area); block.render(area, surface); + + // Only write as many lines as there are rows available. + for (y, line) in (inner.y..) + .zip(self.text.lines()) + .take(inner.height as usize) + { + surface.set_string(inner.x, y, line, style); + } } } diff --git a/helix-view/src/graphics.rs b/helix-view/src/graphics.rs index 5138e923..ed530533 100644 --- a/helix-view/src/graphics.rs +++ b/helix-view/src/graphics.rs @@ -64,22 +64,27 @@ impl Rect { }
}
+ #[inline]
pub fn area(self) -> u16 {
self.width * self.height
}
+ #[inline]
pub fn left(self) -> u16 {
self.x
}
+ #[inline]
pub fn right(self) -> u16 {
self.x.saturating_add(self.width)
}
+ #[inline]
pub fn top(self) -> u16 {
self.y
}
+ #[inline]
pub fn bottom(self) -> u16 {
self.y.saturating_add(self.height)
}
@@ -97,7 +102,18 @@ impl Rect { }
}
+ /// Calculate the union between two [`Rect`]s.
pub fn union(self, other: Rect) -> Rect {
+ // Example:
+ //
+ // If `Rect` A is positioned at `(0, 0)` with a width and height of `5`,
+ // and `Rect` B is positioned at `(5, 0)` with a width and height of `2`,
+ // then this is the resulting union:
+ //
+ // x1 = min(0, 5) => x1 = 0
+ // y1 = min(0, 0) => y1 = 0
+ // x2 = max(0 + 5, 5 + 2) => x2 = 7
+ // y2 = max(0 + 5, 0 + 2) => y2 = 5
let x1 = min(self.x, other.x);
let y1 = min(self.y, other.y);
let x2 = max(self.x + self.width, other.x + other.width);
@@ -110,7 +126,18 @@ impl Rect { }
}
+ /// Calculate the intersection between two [`Rect`]s.
pub fn intersection(self, other: Rect) -> Rect {
+ // Example:
+ //
+ // If `Rect` A is positioned at `(0, 0)` with a width and height of `5`,
+ // and `Rect` B is positioned at `(5, 0)` with a width and height of `2`,
+ // then this is the resulting intersection:
+ //
+ // x1 = max(0, 5) => x1 = 5
+ // y1 = max(0, 0) => y1 = 0
+ // x2 = min(0 + 5, 5 + 2) => x2 = 5
+ // y2 = min(0 + 5, 0 + 2) => y2 = 2
let x1 = max(self.x, other.x);
let y1 = max(self.y, other.y);
let x2 = min(self.x + self.width, other.x + other.width);
|