aboutsummaryrefslogtreecommitdiff
path: root/helix-view
diff options
context:
space:
mode:
authorGokul Soumya2021-08-21 05:21:20 +0000
committerGitHub2021-08-21 05:21:20 +0000
commitf9375f449c8b7bbf792c88b89903fe38d524f2e5 (patch)
tree71a2313a7a7cebc071dffd9e3423f407eb4192e0 /helix-view
parentac8bc541087f815a026b4c664c069d8806b9c5de (diff)
Refactor new Rect construction (#575)
* Refactor new Rect construction Introduces methods that can be chained to construct new Rects out of pre-existing ones * Clamp x and y to edges in Rect chop methods * Rename Rect clipping functions
Diffstat (limited to 'helix-view')
-rw-r--r--helix-view/src/graphics.rs87
-rw-r--r--helix-view/src/view.rs7
2 files changed, 87 insertions, 7 deletions
diff --git a/helix-view/src/graphics.rs b/helix-view/src/graphics.rs
index 9a7a86c3..66013ee5 100644
--- a/helix-view/src/graphics.rs
+++ b/helix-view/src/graphics.rs
@@ -24,7 +24,7 @@ pub struct Margin {
}
/// A simple rectangle used in the computation of the layout and to give widgets an hint about the
-/// area they are supposed to render to.
+/// area they are supposed to render to. (x, y) = (0, 0) is at the top left corner of the screen.
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct Rect {
pub x: u16,
@@ -92,6 +92,57 @@ impl Rect {
self.y.saturating_add(self.height)
}
+ // Returns a new Rect with width reduced from the left side.
+ // This changes the `x` coordinate and clamps it to the right
+ // edge of the original Rect.
+ pub fn clip_left(self, width: u16) -> Rect {
+ let width = std::cmp::min(width, self.width);
+ Rect {
+ x: self.x.saturating_add(width),
+ width: self.width.saturating_sub(width),
+ ..self
+ }
+ }
+
+ // Returns a new Rect with width reduced from the right side.
+ // This does _not_ change the `x` coordinate.
+ pub fn clip_right(self, width: u16) -> Rect {
+ Rect {
+ width: self.width.saturating_sub(width),
+ ..self
+ }
+ }
+
+ // Returns a new Rect with height reduced from the top.
+ // This changes the `y` coordinate and clamps it to the bottom
+ // edge of the original Rect.
+ pub fn clip_top(self, height: u16) -> Rect {
+ let height = std::cmp::min(height, self.height);
+ Rect {
+ y: self.y.saturating_add(height),
+ height: self.height.saturating_sub(height),
+ ..self
+ }
+ }
+
+ // Returns a new Rect with height reduced from the bottom.
+ // This does _not_ change the `y` coordinate.
+ pub fn clip_bottom(self, height: u16) -> Rect {
+ Rect {
+ height: self.height.saturating_sub(height),
+ ..self
+ }
+ }
+
+ pub fn with_height(self, height: u16) -> Rect {
+ // new height may make area > u16::max_value, so use new()
+ Self::new(self.x, self.y, self.width, height)
+ }
+
+ pub fn with_width(self, width: u16) -> Rect {
+ Self::new(self.x, self.y, width, self.height)
+ }
+
pub fn inner(self, margin: &Margin) -> Rect {
if self.width < 2 * margin.horizontal || self.height < 2 * margin.vertical {
Rect::default()
@@ -495,6 +546,40 @@ mod tests {
assert_eq!(rect.height, 100);
}
+ #[test]
+ fn test_rect_chop_from_left() {
+ let rect = Rect::new(0, 0, 20, 30);
+ assert_eq!(Rect::new(10, 0, 10, 30), rect.clip_left(10));
+ assert_eq!(
+ Rect::new(20, 0, 0, 30),
+ rect.clip_left(40),
+ "x should be clamped to original width if new width is bigger"
+ );
+ }
+
+ #[test]
+ fn test_rect_chop_from_right() {
+ let rect = Rect::new(0, 0, 20, 30);
+ assert_eq!(Rect::new(0, 0, 10, 30), rect.clip_right(10));
+ }
+
+ #[test]
+ fn test_rect_chop_from_top() {
+ let rect = Rect::new(0, 0, 20, 30);
+ assert_eq!(Rect::new(0, 10, 20, 20), rect.clip_top(10));
+ assert_eq!(
+ Rect::new(0, 30, 20, 0),
+ rect.clip_top(50),
+ "y should be clamped to original height if new height is bigger"
+ );
+ }
+
+ #[test]
+ fn test_rect_chop_from_bottom() {
+ let rect = Rect::new(0, 0, 20, 30);
+ assert_eq!(Rect::new(0, 0, 20, 20), rect.clip_bottom(10));
+ }
+
fn styles() -> Vec<Style> {
vec![
Style::default(),
diff --git a/helix-view/src/view.rs b/helix-view/src/view.rs
index b707c092..01f18c71 100644
--- a/helix-view/src/view.rs
+++ b/helix-view/src/view.rs
@@ -83,12 +83,7 @@ impl View {
pub fn inner_area(&self) -> Rect {
// TODO: not ideal
const OFFSET: u16 = 7; // 1 diagnostic + 5 linenr + 1 gutter
- Rect::new(
- self.area.x + OFFSET,
- self.area.y,
- self.area.width - OFFSET,
- self.area.height.saturating_sub(1), // -1 for statusline
- )
+ self.area.clip_left(OFFSET).clip_bottom(1) // -1 for statusline
}
pub fn ensure_cursor_in_view(&mut self, doc: &Document, scrolloff: usize) {