on master help sign in
fix small terminal size panic with info popup (#563)

* fix small terminal size panic with info popup * remove unused enumerator * fix subtraction overflow panic

commit815ee9e334da0b973510e1b956eb75fe437038da authorKirawi <67773714+kirawi@users.noreply.github.com> dateMon 9 Aug 2021, 02:46 (5 years ago) parentb522361
3 files changed+51−15
helix-term/src/ui/editor.rs+2−1 helix-term/src/ui/info.rs+22−14 helix-view/src/graphics.rs+27
helix-term/src/ui/editor.rs+2−1
@@ -699,7 +699,8 @@ impl Component for EditorView {
699699 match event {
700700 Event::Resize(width, height) => {
701701 // HAXX: offset the render area height by 1 to account for prompt/commandline
702− cx.editor.resize(Rect::new(0, 0, width, height - 1));
702+ cx.editor
703+ .resize(Rect::new(0, 0, width, height.saturating_sub(1)));
703704 EventResult::Consumed(None)
704705 }
705706 Event::Key(key) => {
helix-term/src/ui/info.rs+22−14
@@ -7,24 +7,32 @@ use tui::widgets::{Block, Borders, Widget};
77impl Component for Info {
88 fn render(&self, viewport: Rect, surface: &mut Surface, cx: &mut Context) {
99 let style = cx.editor.theme.get("ui.popup");
10+
11+ // Calculate the area of the terminal to modify. Because we want to
12+ // render at the bottom right, we use the viewport's width and height
13+ // which evaluate to the most bottom right coordinate.
14+ let (width, height) = (self.width + 2, self.height + 2);
15+ let area = viewport.intersection(Rect::new(
16+ viewport.width.saturating_sub(width),
17+ viewport.height.saturating_sub(height + 2),
18+ width,
19+ height,
20+ ));
21+ surface.clear_with(area, style);
22+
1023 let block = Block::default()
1124 .title(self.title.as_str())
1225 .borders(Borders::ALL)
1326 .border_style(style);
14− let Info { width, height, .. } = self;
15− let (w, h) = (*width + 2, *height + 2);
16− // -2 to subtract command line + statusline. a bit of a hack, because of splits.
17− let area = viewport.intersection(Rect::new(
18− viewport.width.saturating_sub(w),
19− viewport.height.saturating_sub(h + 2),
20− w,
21− h,
22− ));
23− surface.clear_with(area, style);
24− let Rect { x, y, .. } = block.inner(area);
25− for (y, line) in (y..).zip(self.text.lines()) {
26− surface.set_string(x, y, line, style);
27− }
27+ let inner = block.inner(area);
2828 block.render(area, surface);
29+
30+ // Only write as many lines as there are rows available.
31+ for (y, line) in (inner.y..)
32+ .zip(self.text.lines())
33+ .take(inner.height as usize)
34+ {
35+ surface.set_string(inner.x, y, line, style);
36+ }
2937 }
3038}
helix-view/src/graphics.rs+27
@@ -64,22 +64,27 @@ impl Rect {
6464 }
6565 }
6666
67+ #[inline]
6768 pub fn area(self) -> u16 {
6869 self.width * self.height
6970 }
7071
72+ #[inline]
7173 pub fn left(self) -> u16 {
7274 self.x
7375 }
7476
77+ #[inline]
7578 pub fn right(self) -> u16 {
7679 self.x.saturating_add(self.width)
7780 }
7881
82+ #[inline]
7983 pub fn top(self) -> u16 {
8084 self.y
8185 }
8286
87+ #[inline]
8388 pub fn bottom(self) -> u16 {
8489 self.y.saturating_add(self.height)
8590 }
@@ -97,7 +102,18 @@ impl Rect {
97102 }
98103 }
99104
105+ /// Calculate the union between two [`Rect`]s.
100106 pub fn union(self, other: Rect) -> Rect {
107+ // Example:
108+ //
109+ // If `Rect` A is positioned at `(0, 0)` with a width and height of `5`,
110+ // and `Rect` B is positioned at `(5, 0)` with a width and height of `2`,
111+ // then this is the resulting union:
112+ //
113+ // x1 = min(0, 5) => x1 = 0
114+ // y1 = min(0, 0) => y1 = 0
115+ // x2 = max(0 + 5, 5 + 2) => x2 = 7
116+ // y2 = max(0 + 5, 0 + 2) => y2 = 5
101117 let x1 = min(self.x, other.x);
102118 let y1 = min(self.y, other.y);
103119 let x2 = max(self.x + self.width, other.x + other.width);
@@ -110,7 +126,18 @@ impl Rect {
110126 }
111127 }
112128
129+ /// Calculate the intersection between two [`Rect`]s.
113130 pub fn intersection(self, other: Rect) -> Rect {
131+ // Example:
132+ //
133+ // If `Rect` A is positioned at `(0, 0)` with a width and height of `5`,
134+ // and `Rect` B is positioned at `(5, 0)` with a width and height of `2`,
135+ // then this is the resulting intersection:
136+ //
137+ // x1 = max(0, 5) => x1 = 5
138+ // y1 = max(0, 0) => y1 = 0
139+ // x2 = min(0 + 5, 5 + 2) => x2 = 5
140+ // y2 = min(0 + 5, 0 + 2) => y2 = 2
114141 let x1 = max(self.x, other.x);
115142 let y1 = max(self.y, other.y);
116143 let x2 = min(self.x + self.width, other.x + other.width);