Skip to content

Commit 1229b96

Browse files
authored
feat(Rect): add offset method (#533)
The offset method creates a new Rect that is moved by the amount specified in the x and y direction. These values can be positive or negative. This is useful for manual layout tasks. ```rust let rect = area.offset(Offset { x: 10, y -10 }); ```
1 parent fe632d7 commit 1229b96

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

src/layout/rect.rs

+57
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ use std::{
66

77
use crate::prelude::*;
88

9+
mod offset;
10+
11+
pub use offset::*;
12+
913
/// A simple rectangle used in the computation of the layout and to give widgets a hint about the
1014
/// area they are supposed to render to.
1115
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash)]
@@ -106,6 +110,26 @@ impl Rect {
106110
}
107111
}
108112

113+
/// Moves the `Rect` without modifying its size.
114+
///
115+
/// Moves the `Rect` according to the given offset without modifying its [`width`](Rect::width)
116+
/// or [`height`](Rect::height).
117+
/// - Positive `x` moves the whole `Rect` to the right, negative to the left.
118+
/// - Positive `y` moves the whole `Rect` to the bottom, negative to the top.
119+
///
120+
/// See [`Offset`] for details.
121+
pub fn offset(self, offset: Offset) -> Rect {
122+
Rect {
123+
x: i32::from(self.x)
124+
.saturating_add(offset.x)
125+
.clamp(0, (u16::MAX - self.width) as i32) as u16,
126+
y: i32::from(self.y)
127+
.saturating_add(offset.y)
128+
.clamp(0, (u16::MAX - self.height) as i32) as u16,
129+
..self
130+
}
131+
}
132+
109133
/// Returns a new rect that contains both the current one and the given one.
110134
pub fn union(self, other: Rect) -> Rect {
111135
let x1 = min(self.x, other.x);
@@ -207,6 +231,39 @@ mod tests {
207231
);
208232
}
209233

234+
#[test]
235+
fn offset() {
236+
assert_eq!(
237+
Rect::new(1, 2, 3, 4).offset(Offset { x: 5, y: 6 }),
238+
Rect::new(6, 8, 3, 4),
239+
);
240+
}
241+
242+
#[test]
243+
fn negative_offset() {
244+
assert_eq!(
245+
Rect::new(4, 3, 3, 4).offset(Offset { x: -2, y: -1 }),
246+
Rect::new(2, 2, 3, 4),
247+
);
248+
}
249+
250+
#[test]
251+
fn negative_offset_saturate() {
252+
assert_eq!(
253+
Rect::new(1, 2, 3, 4).offset(Offset { x: -5, y: -6 }),
254+
Rect::new(0, 0, 3, 4),
255+
);
256+
}
257+
258+
/// Offsets a [`Rect`] making it go outside [`u16::MAX`], it should keep its size.
259+
#[test]
260+
fn offset_saturate_max() {
261+
assert_eq!(
262+
Rect::new(u16::MAX - 500, u16::MAX - 500, 100, 100).offset(Offset { x: 1000, y: 1000 }),
263+
Rect::new(u16::MAX - 100, u16::MAX - 100, 100, 100),
264+
);
265+
}
266+
210267
#[test]
211268
fn union() {
212269
assert_eq!(

src/layout/rect/offset.rs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/// Amounts by which to move a [`Rect`](super::Rect).
2+
///
3+
/// Positive numbers move to the right/bottom and negative to the left/top.
4+
///
5+
/// See [`Rect::offset`](super::Rect::offset)
6+
#[derive(Debug, Default, Clone, Copy)]
7+
pub struct Offset {
8+
/// How much to move on the X axis
9+
pub x: i32,
10+
/// How much to move on the Y axis
11+
pub y: i32,
12+
}

0 commit comments

Comments
 (0)