Skip to content

Instantly share code, notes, and snippets.

@airstrike
Created August 6, 2024 21:06
Show Gist options
  • Save airstrike/6e48e042f050a1959939e023ba52e014 to your computer and use it in GitHub Desktop.
Save airstrike/6e48e042f050a1959939e023ba52e014 to your computer and use it in GitHub Desktop.
Smart Rectangles
//! Rectangles of every kind! Assumes negative sizes imply that the Rectangle
//! was drawn from bottom to top, right to left, or both.
use iced::{Point, Rectangle, Size};
/// Creates a `Rectangle` that ensures positive dimensions.
///
/// If the size is negative in either direction, it subtracts it from the
/// top-left coordinates accordingly and flips it to a positive sign. This way,
/// if a rectangle is drawn from bottom-right to top-left, it still results in a
/// valid geometric shape.
///
/// # Parameters
///
/// - `top_left`: The top-left `Point` of the rectangle.
/// - `size`: The `Size` of the rectangle.
///
/// # Returns
///
/// A `Rectangle` with positive dimensions.
pub fn smart_rectangle<T>(top_left: Point<T>, size: Size<T>) -> Rectangle<T>
where
T: Default
+ PartialOrd
+ Copy
+ std::ops::Neg<Output = T>
+ std::ops::Add<Output = T>
+ std::ops::Sub<Output = T>,
{
let mut x = top_left.x;
let mut y = top_left.y;
let mut width = size.width;
let mut height = size.height;
// Adjust x and width if width is negative
if width < T::default() {
x = x + width;
width = -width;
}
// Adjust y and height if height is negative
if height < T::default() {
y = y + height;
height = -height;
}
Rectangle {
x,
y,
width,
height,
}
}
#[cfg(test)]
mod tests {
use super::*;
/// Tests that `smart_rectangle` correctly handles positive sizes.
#[test]
fn test_smart_rectangle_positive_size() {
let top_left = Point { x: 0.0, y: 0.0 };
let size = Size {
width: 10.0,
height: 5.0,
};
let rect = smart_rectangle(top_left, size);
assert_eq!(rect.x, 0.0);
assert_eq!(rect.y, 0.0);
assert_eq!(rect.width, 10.0);
assert_eq!(rect.height, 5.0);
}
/// Tests that `smart_rectangle` correctly handles negative width.
#[test]
fn test_smart_rectangle_negative_width() {
let top_left = Point { x: 10.0, y: 10.0 };
let size = Size {
width: -10.0,
height: 5.0,
};
let rect = smart_rectangle(top_left, size);
assert_eq!(rect.x, 0.0);
assert_eq!(rect.y, 10.0);
assert_eq!(rect.width, 10.0);
assert_eq!(rect.height, 5.0);
}
/// Tests that `smart_rectangle` correctly handles negative height.
#[test]
fn test_smart_rectangle_negative_height() {
let top_left = Point { x: 10.0, y: 10.0 };
let size = Size {
width: 10.0,
height: -5.0,
};
let rect = smart_rectangle(top_left, size);
assert_eq!(rect.x, 10.0);
assert_eq!(rect.y, 5.0);
assert_eq!(rect.width, 10.0);
assert_eq!(rect.height, 5.0);
}
/// Tests that `smart_rectangle` correctly handles both negative width and height.
#[test]
fn test_smart_rectangle_negative_size() {
let top_left = Point { x: 10.0, y: 10.0 };
let size = Size {
width: -10.0,
height: -5.0,
};
let rect = smart_rectangle(top_left, size);
assert_eq!(rect.x, 0.0);
assert_eq!(rect.y, 5.0);
assert_eq!(rect.width, 10.0);
assert_eq!(rect.height, 5.0);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment