bear_lib_terminal/
geometry.rs

1//! Helper `struct`s for abstracting on-screen geometry.
2
3
4use std::fmt;
5
6
7/// Represents a single on-screen point/coordinate pair.
8#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
9pub struct Point {
10	pub x: i32,
11	pub y: i32,
12}
13
14impl Point {
15	/// Creates a new point on the specified non-negative coordinates
16	pub fn new(x: i32, y: i32) -> Point {
17		assert!(x >= 0);
18		assert!(y >= 0);
19
20		Point{
21			x: x,
22			y: y
23		}
24	}
25}
26
27
28/// A 2D size representation.
29#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
30pub struct Size {
31	pub width: i32,
32	pub height: i32,
33}
34
35impl Size {
36	/// Creates a new non-negative size.
37	pub fn new(width: i32, height: i32) -> Size {
38		assert!(width >= 0);
39		assert!(height >= 0);
40
41		Size{
42			width: width,
43			height: height,
44		}
45	}
46}
47
48impl fmt::Display for Size {
49	fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
50		write!(formatter, "{}x{}", self.width, self.height)
51	}
52}
53
54
55/// A rectangle, described by its four corners and a size.
56#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
57pub struct Rect {
58	/// The top-left corner.
59	pub top_left: Point,
60	/// The top-right corner.
61	pub top_right: Point,
62	/// The bottom-right corner.
63	pub bottom_right: Point,
64	/// The bottom-left corner.
65	pub bottom_left: Point,
66	/// The `Rect`angle's size.
67	pub size: Size,
68}
69
70impl Rect {
71	/// Construct a `Rect` from its top-left corner and its size.
72	///
73	/// # Examples
74	///
75	/// ```
76	/// # use bear_lib_terminal::geometry::{Rect, Point, Size};
77	/// let rect = Rect::from_size(Point::new(10, 20), Size::new(30, 40));
78	/// assert_eq!(rect.top_left, Point::new(10, 20));
79	/// assert_eq!(rect.top_right, Point::new(40, 20));
80	/// assert_eq!(rect.bottom_left, Point::new(10, 60));
81	/// assert_eq!(rect.bottom_right, Point::new(40, 60));
82	/// assert_eq!(rect.size, Size::new(30, 40));
83	/// ```
84	pub fn from_size(origin: Point, size: Size) -> Rect {
85		let top_right    = Point::new(origin.x + size.width, origin.y);
86		let bottom_left  = Point::new(origin.x, origin.y + size.height);
87		let bottom_right = Point::new(top_right.x, bottom_left.y);
88
89		Rect{
90			top_left: origin,
91			top_right: top_right,
92			bottom_left: bottom_left,
93			bottom_right: bottom_right,
94			size: size
95		}
96	}
97
98	/// Construct a `Rect` from its top-left and bottom-right corners.
99	///
100	/// # Examples
101	///
102	/// ```
103	/// # use bear_lib_terminal::geometry::{Rect, Point, Size};
104	/// let rect = Rect::from_points(Point::new(10, 20), Point::new(30, 40));
105	/// assert_eq!(rect.top_left, Point::new(10, 20));
106	/// assert_eq!(rect.top_right, Point::new(30, 20));
107	/// assert_eq!(rect.bottom_left, Point::new(10, 40));
108	/// assert_eq!(rect.bottom_right, Point::new(30, 40));
109	/// assert_eq!(rect.size, Size::new(20, 20));
110	/// ```
111	pub fn from_points(top_left: Point, bottom_right: Point) -> Rect {
112		assert!(bottom_right.x >= top_left.x);
113		assert!(bottom_right.y >= top_left.y);
114
115		let size = Size::new(bottom_right.x - top_left.x, bottom_right.y - top_left.y);
116		Rect::from_size(top_left, size)
117	}
118
119	/// Construct a `Rect` from its top-left corner and its size, values unwrapped.
120	///
121	/// # Examples
122	///
123	/// ```
124	/// # use bear_lib_terminal::geometry::{Rect, Point, Size};
125	/// assert_eq!(Rect::from_values(10, 20, 30, 40), Rect::from_size(Point::new(10, 20), Size::new(30, 40)));
126	/// ```
127	pub fn from_values(x: i32, y: i32, width: i32, height: i32) -> Rect {
128		let origin = Point::new(x, y);
129		let size = Size::new(width, height);
130		Rect::from_size(origin, size)
131	}
132
133
134	/// Construct a `Rect` from its top-left and bottom-right corners, values unwrapped.
135	///
136	/// # Examples
137	///
138	/// ```
139	/// # use bear_lib_terminal::geometry::{Rect, Point, Size};
140	/// assert_eq!(Rect::from_point_values(10, 20, 30, 40), Rect::from_points(Point::new(10, 20), Point::new(30, 40)));
141	/// ```
142	pub fn from_point_values(top_left_x: i32, top_left_y: i32, bottom_right_x: i32, bottom_right_y: i32) -> Rect {
143		let top_left = Point::new(top_left_x, top_left_y);
144		let bottom_right = Point::new(bottom_right_x, bottom_right_y);
145		Rect::from_points(top_left, bottom_right)
146	}
147}