zng_layout/unit/
rect.rs
1use std::{fmt, ops};
2
3use zng_var::{animation::Transitionable, impl_from_and_into_var};
4
5use super::{DipRect, Factor2d, LayoutMask, Length, Point, PxRect, Size, Vector, impl_length_comp_conversions};
6
7#[derive(Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, Transitionable)]
9pub struct Rect {
10 pub origin: Point,
12 pub size: Size,
14}
15impl fmt::Debug for Rect {
16 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17 if f.alternate() {
18 f.debug_struct("Rect")
19 .field("origin", &self.origin)
20 .field("size", &self.size)
21 .finish()
22 } else {
23 write!(f, "{:?}.at{:?}", self.origin, self.size)
24 }
25 }
26}
27impl fmt::Display for Rect {
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 if let Some(p) = f.precision() {
30 write!(f, "{:.p$} {:.p$}", self.origin, self.size, p = p)
31 } else {
32 write!(f, "{} {}", self.origin, self.size)
33 }
34 }
35}
36impl Rect {
37 pub fn new<O: Into<Point>, S: Into<Size>>(origin: O, size: S) -> Self {
42 Rect {
43 origin: origin.into(),
44 size: size.into(),
45 }
46 }
47
48 pub fn from_size<S: Into<Size>>(size: S) -> Self {
50 Self::new(Point::zero(), size)
51 }
52
53 pub fn zero() -> Self {
55 Self::new(Point::zero(), Size::zero())
56 }
57
58 pub fn fill() -> Self {
60 Self::from_size(Size::fill())
61 }
62
63 pub fn min(&self) -> Point {
67 self.origin.clone()
68 }
69
70 pub fn max(&self) -> Point {
75 self.origin.clone() + self.size.clone()
76 }
77
78 pub fn min_x(&self) -> Length {
80 self.origin.x.clone()
81 }
82 pub fn min_y(&self) -> Length {
84 self.origin.y.clone()
85 }
86
87 pub fn max_x(&self) -> Length {
89 self.origin.x.clone() + self.size.width.clone()
90 }
91 pub fn max_y(&self) -> Length {
93 self.origin.y.clone() + self.size.height.clone()
94 }
95
96 pub fn translate(&self, by: impl Into<Vector>) -> Self {
98 let mut r = self.clone();
99 r.origin += by.into();
100 r
101 }
102
103 pub fn is_default(&self) -> bool {
105 self.origin.is_default() && self.size.is_default()
106 }
107
108 pub fn replace_default(&mut self, overwrite: &Rect) {
110 self.origin.replace_default(&overwrite.origin);
111 self.size.replace_default(&overwrite.size);
112 }
113}
114impl super::Layout2d for Rect {
115 type Px = PxRect;
116
117 fn layout_dft(&self, default: Self::Px) -> Self::Px {
118 PxRect {
119 origin: self.origin.layout_dft(default.origin),
120 size: self.size.layout_dft(default.size),
121 }
122 }
123
124 fn affect_mask(&self) -> LayoutMask {
125 self.origin.affect_mask() | self.size.affect_mask()
126 }
127}
128impl_length_comp_conversions! {
129 fn from(x: X, y: Y, width: W, height: H) -> Rect {
130 Rect::new((x, y), (width, height))
131 }
132}
133impl_from_and_into_var! {
134 fn from(rect: PxRect) -> Rect {
136 Rect::new(rect.origin, rect.size)
137 }
138
139 fn from(rect: DipRect) -> Rect {
141 Rect::new(rect.origin, rect.size)
142 }
143
144 fn from(size: Size) -> Rect {
145 Rect::from_size(size)
146 }
147
148 fn from<O: Into<Point>, S: Into<Size>>((origin, size): (O, S)) -> Rect {
150 Rect::new(origin, size)
151 }
152}
153impl<S: Into<Factor2d>> ops::Mul<S> for Rect {
154 type Output = Self;
155
156 fn mul(mut self, rhs: S) -> Self {
157 self *= rhs;
158 self
159 }
160}
161impl<S: Into<Factor2d>> ops::Mul<S> for &Rect {
162 type Output = Rect;
163
164 fn mul(self, rhs: S) -> Self::Output {
165 self.clone() * rhs
166 }
167}
168impl<S: Into<Factor2d>> ops::MulAssign<S> for Rect {
169 fn mul_assign(&mut self, rhs: S) {
170 let rhs = rhs.into();
171 self.origin *= rhs;
172 self.size *= rhs;
173 }
174}
175impl<S: Into<Factor2d>> ops::Div<S> for Rect {
176 type Output = Self;
177
178 fn div(mut self, rhs: S) -> Self {
179 self /= rhs;
180 self
181 }
182}
183impl<S: Into<Factor2d>> ops::Div<S> for &Rect {
184 type Output = Rect;
185
186 fn div(self, rhs: S) -> Self::Output {
187 self.clone() / rhs
188 }
189}
190impl<S: Into<Factor2d>> ops::DivAssign<S> for Rect {
191 fn div_assign(&mut self, rhs: S) {
192 let rhs = rhs.into();
193 self.origin /= rhs;
194 self.size /= rhs;
195 }
196}
197impl ops::Add for Rect {
198 type Output = Self;
199
200 fn add(mut self, rhs: Self) -> Self {
201 self += rhs;
202 self
203 }
204}
205impl ops::AddAssign for Rect {
206 fn add_assign(&mut self, rhs: Self) {
207 self.origin += rhs.origin;
208 self.size += rhs.size;
209 }
210}
211impl ops::Sub for Rect {
212 type Output = Self;
213
214 fn sub(mut self, rhs: Self) -> Self {
215 self -= rhs;
216 self
217 }
218}
219impl ops::SubAssign for Rect {
220 fn sub_assign(&mut self, rhs: Self) {
221 self.origin -= rhs.origin;
222 self.size -= rhs.size;
223 }
224}
225
226pub trait RectFromTuplesBuilder {
236 fn at<X: Into<Length>, Y: Into<Length>>(self, x: X, y: Y) -> Rect;
238}
239impl<W: Into<Length>, H: Into<Length>> RectFromTuplesBuilder for (W, H) {
240 fn at<X: Into<Length>, Y: Into<Length>>(self, x: X, y: Y) -> Rect {
241 Rect::new((x, y), self)
242 }
243}