1//! The GPUI geometry module is a collection of types and traits that
2//! can be used to describe common units, concepts, and the relationships
3//! between them.
4
5use core::fmt::Debug;
6use derive_more::{Add, AddAssign, Div, DivAssign, Mul, Neg, Sub, SubAssign};
7use refineable::Refineable;
8use serde_derive::{Deserialize, Serialize};
9use std::{
10 cmp::{self, PartialOrd},
11 fmt,
12 hash::Hash,
13 ops::{Add, Div, Mul, MulAssign, Sub},
14};
15
16use crate::{AppContext, DisplayId};
17
18/// An axis along which a measurement can be made.
19#[derive(Copy, Clone, PartialEq, Eq, Debug)]
20pub enum Axis {
21 /// The y axis, or up and down
22 Vertical,
23 /// The x axis, or left and right
24 Horizontal,
25}
26
27impl Axis {
28 /// Swap this axis to the opposite axis.
29 pub fn invert(self) -> Self {
30 match self {
31 Axis::Vertical => Axis::Horizontal,
32 Axis::Horizontal => Axis::Vertical,
33 }
34 }
35}
36
37/// A trait for accessing the given unit along a certain axis.
38pub trait Along {
39 /// The unit associated with this type
40 type Unit;
41
42 /// Returns the unit along the given axis.
43 fn along(&self, axis: Axis) -> Self::Unit;
44
45 /// Applies the given function to the unit along the given axis and returns a new value.
46 fn apply_along(&self, axis: Axis, f: impl FnOnce(Self::Unit) -> Self::Unit) -> Self;
47}
48
49/// Describes a location in a 2D cartesian coordinate space.
50///
51/// It holds two public fields, `x` and `y`, which represent the coordinates in the space.
52/// The type `T` for the coordinates can be any type that implements `Default`, `Clone`, and `Debug`.
53///
54/// # Examples
55///
56/// ```
57/// # use zed::Point;
58/// let point = Point { x: 10, y: 20 };
59/// println!("{:?}", point); // Outputs: Point { x: 10, y: 20 }
60/// ```
61#[derive(Refineable, Default, Add, AddAssign, Sub, SubAssign, Copy, Debug, PartialEq, Eq, Hash)]
62#[refineable(Debug)]
63#[repr(C)]
64pub struct Point<T: Default + Clone + Debug> {
65 /// The x coordinate of the point.
66 pub x: T,
67 /// The y coordinate of the point.
68 pub y: T,
69}
70
71/// Constructs a new `Point<T>` with the given x and y coordinates.
72///
73/// # Arguments
74///
75/// * `x` - The x coordinate of the point.
76/// * `y` - The y coordinate of the point.
77///
78/// # Returns
79///
80/// Returns a `Point<T>` with the specified coordinates.
81///
82/// # Examples
83///
84/// ```
85/// # use zed::Point;
86/// let p = point(10, 20);
87/// assert_eq!(p.x, 10);
88/// assert_eq!(p.y, 20);
89/// ```
90pub const fn point<T: Clone + Debug + Default>(x: T, y: T) -> Point<T> {
91 Point { x, y }
92}
93
94impl<T: Clone + Debug + Default> Point<T> {
95 /// Creates a new `Point` with the specified `x` and `y` coordinates.
96 ///
97 /// # Arguments
98 ///
99 /// * `x` - The horizontal coordinate of the point.
100 /// * `y` - The vertical coordinate of the point.
101 ///
102 /// # Examples
103 ///
104 /// ```
105 /// let p = Point::new(10, 20);
106 /// assert_eq!(p.x, 10);
107 /// assert_eq!(p.y, 20);
108 /// ```
109 pub const fn new(x: T, y: T) -> Self {
110 Self { x, y }
111 }
112
113 /// Transforms the point to a `Point<U>` by applying the given function to both coordinates.
114 ///
115 /// This method allows for converting a `Point<T>` to a `Point<U>` by specifying a closure
116 /// that defines how to convert between the two types. The closure is applied to both the `x`
117 /// and `y` coordinates, resulting in a new point of the desired type.
118 ///
119 /// # Arguments
120 ///
121 /// * `f` - A closure that takes a value of type `T` and returns a value of type `U`.
122 ///
123 /// # Examples
124 ///
125 /// ```
126 /// # use zed::Point;
127 /// let p = Point { x: 3, y: 4 };
128 /// let p_float = p.map(|coord| coord as f32);
129 /// assert_eq!(p_float, Point { x: 3.0, y: 4.0 });
130 /// ```
131 pub fn map<U: Clone + Default + Debug>(&self, f: impl Fn(T) -> U) -> Point<U> {
132 Point {
133 x: f(self.x.clone()),
134 y: f(self.y.clone()),
135 }
136 }
137}
138
139impl<T: Clone + Debug + Default> Along for Point<T> {
140 type Unit = T;
141
142 fn along(&self, axis: Axis) -> T {
143 match axis {
144 Axis::Horizontal => self.x.clone(),
145 Axis::Vertical => self.y.clone(),
146 }
147 }
148
149 fn apply_along(&self, axis: Axis, f: impl FnOnce(T) -> T) -> Point<T> {
150 match axis {
151 Axis::Horizontal => Point {
152 x: f(self.x.clone()),
153 y: self.y.clone(),
154 },
155 Axis::Vertical => Point {
156 x: self.x.clone(),
157 y: f(self.y.clone()),
158 },
159 }
160 }
161}
162
163impl<T: Clone + Debug + Default + Negate> Negate for Point<T> {
164 fn negate(self) -> Self {
165 self.map(Negate::negate)
166 }
167}
168
169impl Point<Pixels> {
170 /// Scales the point by a given factor, which is typically derived from the resolution
171 /// of a target display to ensure proper sizing of UI elements.
172 ///
173 /// # Arguments
174 ///
175 /// * `factor` - The scaling factor to apply to both the x and y coordinates.
176 ///
177 /// # Examples
178 ///
179 /// ```
180 /// # use zed::{Point, Pixels, ScaledPixels};
181 /// let p = Point { x: Pixels(10.0), y: Pixels(20.0) };
182 /// let scaled_p = p.scale(1.5);
183 /// assert_eq!(scaled_p, Point { x: ScaledPixels(15.0), y: ScaledPixels(30.0) });
184 /// ```
185 pub fn scale(&self, factor: f32) -> Point<ScaledPixels> {
186 Point {
187 x: self.x.scale(factor),
188 y: self.y.scale(factor),
189 }
190 }
191
192 /// Calculates the Euclidean distance from the origin (0, 0) to this point.
193 ///
194 /// # Examples
195 ///
196 /// ```
197 /// # use zed::Point;
198 /// # use zed::Pixels;
199 /// let p = Point { x: Pixels(3.0), y: Pixels(4.0) };
200 /// assert_eq!(p.magnitude(), 5.0);
201 /// ```
202 pub fn magnitude(&self) -> f64 {
203 ((self.x.0.powi(2) + self.y.0.powi(2)) as f64).sqrt()
204 }
205}
206
207impl<T, Rhs> Mul<Rhs> for Point<T>
208where
209 T: Mul<Rhs, Output = T> + Clone + Default + Debug,
210 Rhs: Clone + Debug,
211{
212 type Output = Point<T>;
213
214 fn mul(self, rhs: Rhs) -> Self::Output {
215 Point {
216 x: self.x * rhs.clone(),
217 y: self.y * rhs,
218 }
219 }
220}
221
222impl<T, S> MulAssign<S> for Point<T>
223where
224 T: Clone + Mul<S, Output = T> + Default + Debug,
225 S: Clone,
226{
227 fn mul_assign(&mut self, rhs: S) {
228 self.x = self.x.clone() * rhs.clone();
229 self.y = self.y.clone() * rhs;
230 }
231}
232
233impl<T, S> Div<S> for Point<T>
234where
235 T: Div<S, Output = T> + Clone + Default + Debug,
236 S: Clone,
237{
238 type Output = Self;
239
240 fn div(self, rhs: S) -> Self::Output {
241 Self {
242 x: self.x / rhs.clone(),
243 y: self.y / rhs,
244 }
245 }
246}
247
248impl<T> Point<T>
249where
250 T: PartialOrd + Clone + Default + Debug,
251{
252 /// Returns a new point with the maximum values of each dimension from `self` and `other`.
253 ///
254 /// # Arguments
255 ///
256 /// * `other` - A reference to another `Point` to compare with `self`.
257 ///
258 /// # Examples
259 ///
260 /// ```
261 /// # use zed::Point;
262 /// let p1 = Point { x: 3, y: 7 };
263 /// let p2 = Point { x: 5, y: 2 };
264 /// let max_point = p1.max(&p2);
265 /// assert_eq!(max_point, Point { x: 5, y: 7 });
266 /// ```
267 pub fn max(&self, other: &Self) -> Self {
268 Point {
269 x: if self.x > other.x {
270 self.x.clone()
271 } else {
272 other.x.clone()
273 },
274 y: if self.y > other.y {
275 self.y.clone()
276 } else {
277 other.y.clone()
278 },
279 }
280 }
281
282 /// Returns a new point with the minimum values of each dimension from `self` and `other`.
283 ///
284 /// # Arguments
285 ///
286 /// * `other` - A reference to another `Point` to compare with `self`.
287 ///
288 /// # Examples
289 ///
290 /// ```
291 /// # use zed::Point;
292 /// let p1 = Point { x: 3, y: 7 };
293 /// let p2 = Point { x: 5, y: 2 };
294 /// let min_point = p1.min(&p2);
295 /// assert_eq!(min_point, Point { x: 3, y: 2 });
296 /// ```
297 pub fn min(&self, other: &Self) -> Self {
298 Point {
299 x: if self.x <= other.x {
300 self.x.clone()
301 } else {
302 other.x.clone()
303 },
304 y: if self.y <= other.y {
305 self.y.clone()
306 } else {
307 other.y.clone()
308 },
309 }
310 }
311
312 /// Clamps the point to a specified range.
313 ///
314 /// Given a minimum point and a maximum point, this method constrains the current point
315 /// such that its coordinates do not exceed the range defined by the minimum and maximum points.
316 /// If the current point's coordinates are less than the minimum, they are set to the minimum.
317 /// If they are greater than the maximum, they are set to the maximum.
318 ///
319 /// # Arguments
320 ///
321 /// * `min` - A reference to a `Point` representing the minimum allowable coordinates.
322 /// * `max` - A reference to a `Point` representing the maximum allowable coordinates.
323 ///
324 /// # Examples
325 ///
326 /// ```
327 /// # use zed::Point;
328 /// let p = Point { x: 10, y: 20 };
329 /// let min = Point { x: 0, y: 5 };
330 /// let max = Point { x: 15, y: 25 };
331 /// let clamped_p = p.clamp(&min, &max);
332 /// assert_eq!(clamped_p, Point { x: 10, y: 20 });
333 ///
334 /// let p_out_of_bounds = Point { x: -5, y: 30 };
335 /// let clamped_p_out_of_bounds = p_out_of_bounds.clamp(&min, &max);
336 /// assert_eq!(clamped_p_out_of_bounds, Point { x: 0, y: 25 });
337 /// ```
338 pub fn clamp(&self, min: &Self, max: &Self) -> Self {
339 self.max(min).min(max)
340 }
341}
342
343impl<T: Clone + Default + Debug> Clone for Point<T> {
344 fn clone(&self) -> Self {
345 Self {
346 x: self.x.clone(),
347 y: self.y.clone(),
348 }
349 }
350}
351
352/// A structure representing a two-dimensional size with width and height in a given unit.
353///
354/// This struct is generic over the type `T`, which can be any type that implements `Clone`, `Default`, and `Debug`.
355/// It is commonly used to specify dimensions for elements in a UI, such as a window or element.
356#[derive(Refineable, Default, Clone, Copy, PartialEq, Div, Hash, Serialize, Deserialize)]
357#[refineable(Debug)]
358#[repr(C)]
359pub struct Size<T: Clone + Default + Debug> {
360 /// The width component of the size.
361 pub width: T,
362 /// The height component of the size.
363 pub height: T,
364}
365
366/// Constructs a new `Size<T>` with the provided width and height.
367///
368/// # Arguments
369///
370/// * `width` - The width component of the `Size`.
371/// * `height` - The height component of the `Size`.
372///
373/// # Examples
374///
375/// ```
376/// # use zed::Size;
377/// let my_size = size(10, 20);
378/// assert_eq!(my_size.width, 10);
379/// assert_eq!(my_size.height, 20);
380/// ```
381pub const fn size<T>(width: T, height: T) -> Size<T>
382where
383 T: Clone + Default + Debug,
384{
385 Size { width, height }
386}
387
388impl<T> Size<T>
389where
390 T: Clone + Default + Debug,
391{
392 /// Applies a function to the width and height of the size, producing a new `Size<U>`.
393 ///
394 /// This method allows for converting a `Size<T>` to a `Size<U>` by specifying a closure
395 /// that defines how to convert between the two types. The closure is applied to both the `width`
396 /// and `height`, resulting in a new size of the desired type.
397 ///
398 /// # Arguments
399 ///
400 /// * `f` - A closure that takes a value of type `T` and returns a value of type `U`.
401 ///
402 /// # Examples
403 ///
404 /// ```
405 /// # use zed::Size;
406 /// let my_size = Size { width: 10, height: 20 };
407 /// let my_new_size = my_size.map(|dimension| dimension as f32 * 1.5);
408 /// assert_eq!(my_new_size, Size { width: 15.0, height: 30.0 });
409 /// ```
410 pub fn map<U>(&self, f: impl Fn(T) -> U) -> Size<U>
411 where
412 U: Clone + Default + Debug,
413 {
414 Size {
415 width: f(self.width.clone()),
416 height: f(self.height.clone()),
417 }
418 }
419}
420
421impl<T> Size<T>
422where
423 T: Clone + Default + Debug + Half,
424{
425 /// Compute the center point of the size.g
426 pub fn center(&self) -> Point<T> {
427 Point {
428 x: self.width.half(),
429 y: self.height.half(),
430 }
431 }
432}
433
434impl Size<Pixels> {
435 /// Scales the size by a given factor.
436 ///
437 /// This method multiplies both the width and height by the provided scaling factor,
438 /// resulting in a new `Size<ScaledPixels>` that is proportionally larger or smaller
439 /// depending on the factor.
440 ///
441 /// # Arguments
442 ///
443 /// * `factor` - The scaling factor to apply to the width and height.
444 ///
445 /// # Examples
446 ///
447 /// ```
448 /// # use zed::{Size, Pixels, ScaledPixels};
449 /// let size = Size { width: Pixels(100.0), height: Pixels(50.0) };
450 /// let scaled_size = size.scale(2.0);
451 /// assert_eq!(scaled_size, Size { width: ScaledPixels(200.0), height: ScaledPixels(100.0) });
452 /// ```
453 pub fn scale(&self, factor: f32) -> Size<ScaledPixels> {
454 Size {
455 width: self.width.scale(factor),
456 height: self.height.scale(factor),
457 }
458 }
459}
460
461impl<T> Along for Size<T>
462where
463 T: Clone + Default + Debug,
464{
465 type Unit = T;
466
467 fn along(&self, axis: Axis) -> T {
468 match axis {
469 Axis::Horizontal => self.width.clone(),
470 Axis::Vertical => self.height.clone(),
471 }
472 }
473
474 /// Returns the value of this size along the given axis.
475 fn apply_along(&self, axis: Axis, f: impl FnOnce(T) -> T) -> Self {
476 match axis {
477 Axis::Horizontal => Size {
478 width: f(self.width.clone()),
479 height: self.height.clone(),
480 },
481 Axis::Vertical => Size {
482 width: self.width.clone(),
483 height: f(self.height.clone()),
484 },
485 }
486 }
487}
488
489impl<T> Size<T>
490where
491 T: PartialOrd + Clone + Default + Debug,
492{
493 /// Returns a new `Size` with the maximum width and height from `self` and `other`.
494 ///
495 /// # Arguments
496 ///
497 /// * `other` - A reference to another `Size` to compare with `self`.
498 ///
499 /// # Examples
500 ///
501 /// ```
502 /// # use zed::Size;
503 /// let size1 = Size { width: 30, height: 40 };
504 /// let size2 = Size { width: 50, height: 20 };
505 /// let max_size = size1.max(&size2);
506 /// assert_eq!(max_size, Size { width: 50, height: 40 });
507 /// ```
508 pub fn max(&self, other: &Self) -> Self {
509 Size {
510 width: if self.width >= other.width {
511 self.width.clone()
512 } else {
513 other.width.clone()
514 },
515 height: if self.height >= other.height {
516 self.height.clone()
517 } else {
518 other.height.clone()
519 },
520 }
521 }
522 /// Returns a new `Size` with the minimum width and height from `self` and `other`.
523 ///
524 /// # Arguments
525 ///
526 /// * `other` - A reference to another `Size` to compare with `self`.
527 ///
528 /// # Examples
529 ///
530 /// ```
531 /// # use zed::Size;
532 /// let size1 = Size { width: 30, height: 40 };
533 /// let size2 = Size { width: 50, height: 20 };
534 /// let min_size = size1.min(&size2);
535 /// assert_eq!(min_size, Size { width: 30, height: 20 });
536 /// ```
537 pub fn min(&self, other: &Self) -> Self {
538 Size {
539 width: if self.width >= other.width {
540 other.width.clone()
541 } else {
542 self.width.clone()
543 },
544 height: if self.height >= other.height {
545 other.height.clone()
546 } else {
547 self.height.clone()
548 },
549 }
550 }
551}
552
553impl<T> Sub for Size<T>
554where
555 T: Sub<Output = T> + Clone + Default + Debug,
556{
557 type Output = Size<T>;
558
559 fn sub(self, rhs: Self) -> Self::Output {
560 Size {
561 width: self.width - rhs.width,
562 height: self.height - rhs.height,
563 }
564 }
565}
566
567impl<T> Add for Size<T>
568where
569 T: Add<Output = T> + Clone + Default + Debug,
570{
571 type Output = Size<T>;
572
573 fn add(self, rhs: Self) -> Self::Output {
574 Size {
575 width: self.width + rhs.width,
576 height: self.height + rhs.height,
577 }
578 }
579}
580
581impl<T, Rhs> Mul<Rhs> for Size<T>
582where
583 T: Mul<Rhs, Output = Rhs> + Clone + Default + Debug,
584 Rhs: Clone + Default + Debug,
585{
586 type Output = Size<Rhs>;
587
588 fn mul(self, rhs: Rhs) -> Self::Output {
589 Size {
590 width: self.width * rhs.clone(),
591 height: self.height * rhs,
592 }
593 }
594}
595
596impl<T, S> MulAssign<S> for Size<T>
597where
598 T: Mul<S, Output = T> + Clone + Default + Debug,
599 S: Clone,
600{
601 fn mul_assign(&mut self, rhs: S) {
602 self.width = self.width.clone() * rhs.clone();
603 self.height = self.height.clone() * rhs;
604 }
605}
606
607impl<T> Eq for Size<T> where T: Eq + Default + Debug + Clone {}
608
609impl<T> Debug for Size<T>
610where
611 T: Clone + Default + Debug,
612{
613 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
614 write!(f, "Size {{ {:?} × {:?} }}", self.width, self.height)
615 }
616}
617
618impl<T: Clone + Default + Debug> From<Point<T>> for Size<T> {
619 fn from(point: Point<T>) -> Self {
620 Self {
621 width: point.x,
622 height: point.y,
623 }
624 }
625}
626
627impl From<Size<Pixels>> for Size<DefiniteLength> {
628 fn from(size: Size<Pixels>) -> Self {
629 Size {
630 width: size.width.into(),
631 height: size.height.into(),
632 }
633 }
634}
635
636impl From<Size<Pixels>> for Size<AbsoluteLength> {
637 fn from(size: Size<Pixels>) -> Self {
638 Size {
639 width: size.width.into(),
640 height: size.height.into(),
641 }
642 }
643}
644
645impl Size<Length> {
646 /// Returns a `Size` with both width and height set to fill the available space.
647 ///
648 /// This function creates a `Size` instance where both the width and height are set to `Length::Definite(DefiniteLength::Fraction(1.0))`,
649 /// which represents 100% of the available space in both dimensions.
650 ///
651 /// # Returns
652 ///
653 /// A `Size<Length>` that will fill the available space when used in a layout.
654 pub fn full() -> Self {
655 Self {
656 width: relative(1.).into(),
657 height: relative(1.).into(),
658 }
659 }
660}
661
662impl Size<Length> {
663 /// Returns a `Size` with both width and height set to `auto`, which allows the layout engine to determine the size.
664 ///
665 /// This function creates a `Size` instance where both the width and height are set to `Length::Auto`,
666 /// indicating that their size should be computed based on the layout context, such as the content size or
667 /// available space.
668 ///
669 /// # Returns
670 ///
671 /// A `Size<Length>` with width and height set to `Length::Auto`.
672 pub fn auto() -> Self {
673 Self {
674 width: Length::Auto,
675 height: Length::Auto,
676 }
677 }
678}
679
680/// Represents a rectangular area in a 2D space with an origin point and a size.
681///
682/// The `Bounds` struct is generic over a type `T` which represents the type of the coordinate system.
683/// The origin is represented as a `Point<T>` which defines the upper-left corner of the rectangle,
684/// and the size is represented as a `Size<T>` which defines the width and height of the rectangle.
685///
686/// # Examples
687///
688/// ```
689/// # use zed::{Bounds, Point, Size};
690/// let origin = Point { x: 0, y: 0 };
691/// let size = Size { width: 10, height: 20 };
692/// let bounds = Bounds::new(origin, size);
693///
694/// assert_eq!(bounds.origin, origin);
695/// assert_eq!(bounds.size, size);
696/// ```
697#[derive(Refineable, Clone, Default, Debug, Eq, PartialEq, Hash)]
698#[refineable(Debug)]
699#[repr(C)]
700pub struct Bounds<T: Clone + Default + Debug> {
701 /// The origin point of this area.
702 pub origin: Point<T>,
703 /// The size of the rectangle.
704 pub size: Size<T>,
705}
706
707impl Bounds<Pixels> {
708 /// Generate a centered bounds for the given display or primary display if none is provided
709 pub fn centered(
710 display_id: Option<DisplayId>,
711 size: Size<Pixels>,
712 cx: &mut AppContext,
713 ) -> Self {
714 let display = display_id
715 .and_then(|id| cx.find_display(id))
716 .or_else(|| cx.primary_display());
717
718 display
719 .map(|display| {
720 let center = display.bounds().center();
721 Bounds {
722 origin: point(center.x - size.width / 2., center.y - size.height / 2.),
723 size,
724 }
725 })
726 .unwrap_or_else(|| Bounds {
727 origin: point(px(0.), px(0.)),
728 size,
729 })
730 }
731
732 /// Generate maximized bounds for the given display or primary display if none is provided
733 pub fn maximized(display_id: Option<DisplayId>, cx: &mut AppContext) -> Self {
734 let display = display_id
735 .and_then(|id| cx.find_display(id))
736 .or_else(|| cx.primary_display());
737
738 display
739 .map(|display| display.bounds())
740 .unwrap_or_else(|| Bounds {
741 origin: point(px(0.), px(0.)),
742 size: size(px(1024.), px(768.)),
743 })
744 }
745}
746
747impl<T> Bounds<T>
748where
749 T: Clone + Debug + Sub<Output = T> + Default,
750{
751 /// Constructs a `Bounds` from two corner points: the upper-left and lower-right corners.
752 ///
753 /// This function calculates the origin and size of the `Bounds` based on the provided corner points.
754 /// The origin is set to the upper-left corner, and the size is determined by the difference between
755 /// the x and y coordinates of the lower-right and upper-left points.
756 ///
757 /// # Arguments
758 ///
759 /// * `upper_left` - A `Point<T>` representing the upper-left corner of the rectangle.
760 /// * `lower_right` - A `Point<T>` representing the lower-right corner of the rectangle.
761 ///
762 /// # Returns
763 ///
764 /// Returns a `Bounds<T>` that encompasses the area defined by the two corner points.
765 ///
766 /// # Examples
767 ///
768 /// ```
769 /// # use zed::{Bounds, Point};
770 /// let upper_left = Point { x: 0, y: 0 };
771 /// let lower_right = Point { x: 10, y: 10 };
772 /// let bounds = Bounds::from_corners(upper_left, lower_right);
773 ///
774 /// assert_eq!(bounds.origin, upper_left);
775 /// assert_eq!(bounds.size.width, 10);
776 /// assert_eq!(bounds.size.height, 10);
777 /// ```
778 pub fn from_corners(upper_left: Point<T>, lower_right: Point<T>) -> Self {
779 let origin = Point {
780 x: upper_left.x.clone(),
781 y: upper_left.y.clone(),
782 };
783 let size = Size {
784 width: lower_right.x - upper_left.x,
785 height: lower_right.y - upper_left.y,
786 };
787 Bounds { origin, size }
788 }
789
790 /// Creates a new `Bounds` with the specified origin and size.
791 ///
792 /// # Arguments
793 ///
794 /// * `origin` - A `Point<T>` representing the origin of the bounds.
795 /// * `size` - A `Size<T>` representing the size of the bounds.
796 ///
797 /// # Returns
798 ///
799 /// Returns a `Bounds<T>` that has the given origin and size.
800 pub fn new(origin: Point<T>, size: Size<T>) -> Self {
801 Bounds { origin, size }
802 }
803}
804
805impl<T> Bounds<T>
806where
807 T: Clone + Debug + PartialOrd + Add<T, Output = T> + Sub<Output = T> + Default + Half,
808{
809 /// Checks if this `Bounds` intersects with another `Bounds`.
810 ///
811 /// Two `Bounds` instances intersect if they overlap in the 2D space they occupy.
812 /// This method checks if there is any overlapping area between the two bounds.
813 ///
814 /// # Arguments
815 ///
816 /// * `other` - A reference to another `Bounds` to check for intersection with.
817 ///
818 /// # Returns
819 ///
820 /// Returns `true` if there is any intersection between the two bounds, `false` otherwise.
821 ///
822 /// # Examples
823 ///
824 /// ```
825 /// # use zed::{Bounds, Point, Size};
826 /// let bounds1 = Bounds {
827 /// origin: Point { x: 0, y: 0 },
828 /// size: Size { width: 10, height: 10 },
829 /// };
830 /// let bounds2 = Bounds {
831 /// origin: Point { x: 5, y: 5 },
832 /// size: Size { width: 10, height: 10 },
833 /// };
834 /// let bounds3 = Bounds {
835 /// origin: Point { x: 20, y: 20 },
836 /// size: Size { width: 10, height: 10 },
837 /// };
838 ///
839 /// assert_eq!(bounds1.intersects(&bounds2), true); // Overlapping bounds
840 /// assert_eq!(bounds1.intersects(&bounds3), false); // Non-overlapping bounds
841 /// ```
842 pub fn intersects(&self, other: &Bounds<T>) -> bool {
843 let my_lower_right = self.lower_right();
844 let their_lower_right = other.lower_right();
845
846 self.origin.x < their_lower_right.x
847 && my_lower_right.x > other.origin.x
848 && self.origin.y < their_lower_right.y
849 && my_lower_right.y > other.origin.y
850 }
851
852 /// Dilates the bounds by a specified amount in all directions.
853 ///
854 /// This method expands the bounds by the given `amount`, increasing the size
855 /// and adjusting the origin so that the bounds grow outwards equally in all directions.
856 /// The resulting bounds will have its width and height increased by twice the `amount`
857 /// (since it grows in both directions), and the origin will be moved by `-amount`
858 /// in both the x and y directions.
859 ///
860 /// # Arguments
861 ///
862 /// * `amount` - The amount by which to dilate the bounds.
863 ///
864 /// # Examples
865 ///
866 /// ```
867 /// # use zed::{Bounds, Point, Size};
868 /// let mut bounds = Bounds {
869 /// origin: Point { x: 10, y: 10 },
870 /// size: Size { width: 10, height: 10 },
871 /// };
872 /// bounds.dilate(5);
873 /// assert_eq!(bounds, Bounds {
874 /// origin: Point { x: 5, y: 5 },
875 /// size: Size { width: 20, height: 20 },
876 /// });
877 /// ```
878 pub fn dilate(&mut self, amount: T) {
879 self.origin.x = self.origin.x.clone() - amount.clone();
880 self.origin.y = self.origin.y.clone() - amount.clone();
881 let double_amount = amount.clone() + amount;
882 self.size.width = self.size.width.clone() + double_amount.clone();
883 self.size.height = self.size.height.clone() + double_amount;
884 }
885
886 /// inset the bounds by a specified amount
887 /// Note that this may panic if T does not support negative values
888 pub fn inset(&self, amount: T) -> Self {
889 let mut result = self.clone();
890 result.dilate(T::default() - amount);
891 result
892 }
893
894 /// Returns the center point of the bounds.
895 ///
896 /// Calculates the center by taking the origin's x and y coordinates and adding half the width and height
897 /// of the bounds, respectively. The center is represented as a `Point<T>` where `T` is the type of the
898 /// coordinate system.
899 ///
900 /// # Returns
901 ///
902 /// A `Point<T>` representing the center of the bounds.
903 ///
904 /// # Examples
905 ///
906 /// ```
907 /// # use zed::{Bounds, Point, Size};
908 /// let bounds = Bounds {
909 /// origin: Point { x: 0, y: 0 },
910 /// size: Size { width: 10, height: 20 },
911 /// };
912 /// let center = bounds.center();
913 /// assert_eq!(center, Point { x: 5, y: 10 });
914 /// ```
915 pub fn center(&self) -> Point<T> {
916 Point {
917 x: self.origin.x.clone() + self.size.width.clone().half(),
918 y: self.origin.y.clone() + self.size.height.clone().half(),
919 }
920 }
921
922 /// Calculates the half perimeter of a rectangle defined by the bounds.
923 ///
924 /// The half perimeter is calculated as the sum of the width and the height of the rectangle.
925 /// This method is generic over the type `T` which must implement the `Sub` trait to allow
926 /// calculation of the width and height from the bounds' origin and size, as well as the `Add` trait
927 /// to sum the width and height for the half perimeter.
928 ///
929 /// # Examples
930 ///
931 /// ```
932 /// # use zed::{Bounds, Point, Size};
933 /// let bounds = Bounds {
934 /// origin: Point { x: 0, y: 0 },
935 /// size: Size { width: 10, height: 20 },
936 /// };
937 /// let half_perimeter = bounds.half_perimeter();
938 /// assert_eq!(half_perimeter, 30);
939 /// ```
940 pub fn half_perimeter(&self) -> T {
941 self.size.width.clone() + self.size.height.clone()
942 }
943
944 /// centered_at creates a new bounds centered at the given point.
945 pub fn centered_at(center: Point<T>, size: Size<T>) -> Self {
946 let origin = Point {
947 x: center.x - size.width.half(),
948 y: center.y - size.height.half(),
949 };
950 Self::new(origin, size)
951 }
952}
953
954impl<T: Clone + Default + Debug + PartialOrd + Add<T, Output = T> + Sub<Output = T>> Bounds<T> {
955 /// Calculates the intersection of two `Bounds` objects.
956 ///
957 /// This method computes the overlapping region of two `Bounds`. If the bounds do not intersect,
958 /// the resulting `Bounds` will have a size with width and height of zero.
959 ///
960 /// # Arguments
961 ///
962 /// * `other` - A reference to another `Bounds` to intersect with.
963 ///
964 /// # Returns
965 ///
966 /// Returns a `Bounds` representing the intersection area. If there is no intersection,
967 /// the returned `Bounds` will have a size with width and height of zero.
968 ///
969 /// # Examples
970 ///
971 /// ```
972 /// # use zed::{Bounds, Point, Size};
973 /// let bounds1 = Bounds {
974 /// origin: Point { x: 0, y: 0 },
975 /// size: Size { width: 10, height: 10 },
976 /// };
977 /// let bounds2 = Bounds {
978 /// origin: Point { x: 5, y: 5 },
979 /// size: Size { width: 10, height: 10 },
980 /// };
981 /// let intersection = bounds1.intersect(&bounds2);
982 ///
983 /// assert_eq!(intersection, Bounds {
984 /// origin: Point { x: 5, y: 5 },
985 /// size: Size { width: 5, height: 5 },
986 /// });
987 /// ```
988 pub fn intersect(&self, other: &Self) -> Self {
989 let upper_left = self.origin.max(&other.origin);
990 let lower_right = self.lower_right().min(&other.lower_right());
991 Self::from_corners(upper_left, lower_right)
992 }
993
994 /// Computes the union of two `Bounds`.
995 ///
996 /// This method calculates the smallest `Bounds` that contains both the current `Bounds` and the `other` `Bounds`.
997 /// The resulting `Bounds` will have an origin that is the minimum of the origins of the two `Bounds`,
998 /// and a size that encompasses the furthest extents of both `Bounds`.
999 ///
1000 /// # Arguments
1001 ///
1002 /// * `other` - A reference to another `Bounds` to create a union with.
1003 ///
1004 /// # Returns
1005 ///
1006 /// Returns a `Bounds` representing the union of the two `Bounds`.
1007 ///
1008 /// # Examples
1009 ///
1010 /// ```
1011 /// # use zed::{Bounds, Point, Size};
1012 /// let bounds1 = Bounds {
1013 /// origin: Point { x: 0, y: 0 },
1014 /// size: Size { width: 10, height: 10 },
1015 /// };
1016 /// let bounds2 = Bounds {
1017 /// origin: Point { x: 5, y: 5 },
1018 /// size: Size { width: 15, height: 15 },
1019 /// };
1020 /// let union_bounds = bounds1.union(&bounds2);
1021 ///
1022 /// assert_eq!(union_bounds, Bounds {
1023 /// origin: Point { x: 0, y: 0 },
1024 /// size: Size { width: 20, height: 20 },
1025 /// });
1026 /// ```
1027 pub fn union(&self, other: &Self) -> Self {
1028 let top_left = self.origin.min(&other.origin);
1029 let bottom_right = self.lower_right().max(&other.lower_right());
1030 Bounds::from_corners(top_left, bottom_right)
1031 }
1032}
1033
1034impl<T, Rhs> Mul<Rhs> for Bounds<T>
1035where
1036 T: Mul<Rhs, Output = Rhs> + Clone + Default + Debug,
1037 Point<T>: Mul<Rhs, Output = Point<Rhs>>,
1038 Rhs: Clone + Default + Debug,
1039{
1040 type Output = Bounds<Rhs>;
1041
1042 fn mul(self, rhs: Rhs) -> Self::Output {
1043 Bounds {
1044 origin: self.origin * rhs.clone(),
1045 size: self.size * rhs,
1046 }
1047 }
1048}
1049
1050impl<T, S> MulAssign<S> for Bounds<T>
1051where
1052 T: Mul<S, Output = T> + Clone + Default + Debug,
1053 S: Clone,
1054{
1055 fn mul_assign(&mut self, rhs: S) {
1056 self.origin *= rhs.clone();
1057 self.size *= rhs;
1058 }
1059}
1060
1061impl<T, S> Div<S> for Bounds<T>
1062where
1063 Size<T>: Div<S, Output = Size<T>>,
1064 T: Div<S, Output = T> + Default + Clone + Debug,
1065 S: Clone,
1066{
1067 type Output = Self;
1068
1069 fn div(self, rhs: S) -> Self {
1070 Self {
1071 origin: self.origin / rhs.clone(),
1072 size: self.size / rhs,
1073 }
1074 }
1075}
1076
1077impl<T> Bounds<T>
1078where
1079 T: Add<T, Output = T> + Clone + Default + Debug,
1080{
1081 /// Returns the top edge of the bounds.
1082 ///
1083 /// # Returns
1084 ///
1085 /// A value of type `T` representing the y-coordinate of the top edge of the bounds.
1086 pub fn top(&self) -> T {
1087 self.origin.y.clone()
1088 }
1089
1090 /// Returns the bottom edge of the bounds.
1091 ///
1092 /// # Returns
1093 ///
1094 /// A value of type `T` representing the y-coordinate of the bottom edge of the bounds.
1095 pub fn bottom(&self) -> T {
1096 self.origin.y.clone() + self.size.height.clone()
1097 }
1098
1099 /// Returns the left edge of the bounds.
1100 ///
1101 /// # Returns
1102 ///
1103 /// A value of type `T` representing the x-coordinate of the left edge of the bounds.
1104 pub fn left(&self) -> T {
1105 self.origin.x.clone()
1106 }
1107
1108 /// Returns the right edge of the bounds.
1109 ///
1110 /// # Returns
1111 ///
1112 /// A value of type `T` representing the x-coordinate of the right edge of the bounds.
1113 pub fn right(&self) -> T {
1114 self.origin.x.clone() + self.size.width.clone()
1115 }
1116
1117 /// Returns the upper-right corner point of the bounds.
1118 ///
1119 /// # Returns
1120 ///
1121 /// A `Point<T>` representing the upper-right corner of the bounds.
1122 ///
1123 /// # Examples
1124 ///
1125 /// ```
1126 /// # use zed::{Bounds, Point, Size};
1127 /// let bounds = Bounds {
1128 /// origin: Point { x: 0, y: 0 },
1129 /// size: Size { width: 10, height: 20 },
1130 /// };
1131 /// let upper_right = bounds.upper_right();
1132 /// assert_eq!(upper_right, Point { x: 10, y: 0 });
1133 /// ```
1134 pub fn upper_right(&self) -> Point<T> {
1135 Point {
1136 x: self.origin.x.clone() + self.size.width.clone(),
1137 y: self.origin.y.clone(),
1138 }
1139 }
1140
1141 /// Returns the lower-right corner point of the bounds.
1142 ///
1143 /// # Returns
1144 ///
1145 /// A `Point<T>` representing the lower-right corner of the bounds.
1146 ///
1147 /// # Examples
1148 ///
1149 /// ```
1150 /// # use zed::{Bounds, Point, Size};
1151 /// let bounds = Bounds {
1152 /// origin: Point { x: 0, y: 0 },
1153 /// size: Size { width: 10, height: 20 },
1154 /// };
1155 /// let lower_right = bounds.lower_right();
1156 /// assert_eq!(lower_right, Point { x: 10, y: 20 });
1157 /// ```
1158 pub fn lower_right(&self) -> Point<T> {
1159 Point {
1160 x: self.origin.x.clone() + self.size.width.clone(),
1161 y: self.origin.y.clone() + self.size.height.clone(),
1162 }
1163 }
1164
1165 /// Returns the lower-left corner point of the bounds.
1166 ///
1167 /// # Returns
1168 ///
1169 /// A `Point<T>` representing the lower-left corner of the bounds.
1170 ///
1171 /// # Examples
1172 ///
1173 /// ```
1174 /// # use zed::{Bounds, Point, Size};
1175 /// let bounds = Bounds {
1176 /// origin: Point { x: 0, y: 0 },
1177 /// size: Size { width: 10, height: 20 },
1178 /// };
1179 /// let lower_left = bounds.lower_left();
1180 /// assert_eq!(lower_left, Point { x: 0, y: 20 });
1181 /// ```
1182 pub fn lower_left(&self) -> Point<T> {
1183 Point {
1184 x: self.origin.x.clone(),
1185 y: self.origin.y.clone() + self.size.height.clone(),
1186 }
1187 }
1188}
1189
1190impl<T> Bounds<T>
1191where
1192 T: Add<T, Output = T> + PartialOrd + Clone + Default + Debug,
1193{
1194 /// Checks if the given point is within the bounds.
1195 ///
1196 /// This method determines whether a point lies inside the rectangle defined by the bounds,
1197 /// including the edges. The point is considered inside if its x-coordinate is greater than
1198 /// or equal to the left edge and less than or equal to the right edge, and its y-coordinate
1199 /// is greater than or equal to the top edge and less than or equal to the bottom edge of the bounds.
1200 ///
1201 /// # Arguments
1202 ///
1203 /// * `point` - A reference to a `Point<T>` that represents the point to check.
1204 ///
1205 /// # Returns
1206 ///
1207 /// Returns `true` if the point is within the bounds, `false` otherwise.
1208 ///
1209 /// # Examples
1210 ///
1211 /// ```
1212 /// # use zed::{Point, Bounds};
1213 /// let bounds = Bounds {
1214 /// origin: Point { x: 0, y: 0 },
1215 /// size: Size { width: 10, height: 10 },
1216 /// };
1217 /// let inside_point = Point { x: 5, y: 5 };
1218 /// let outside_point = Point { x: 15, y: 15 };
1219 ///
1220 /// assert!(bounds.contains_point(&inside_point));
1221 /// assert!(!bounds.contains_point(&outside_point));
1222 /// ```
1223 pub fn contains(&self, point: &Point<T>) -> bool {
1224 point.x >= self.origin.x
1225 && point.x <= self.origin.x.clone() + self.size.width.clone()
1226 && point.y >= self.origin.y
1227 && point.y <= self.origin.y.clone() + self.size.height.clone()
1228 }
1229
1230 /// Applies a function to the origin and size of the bounds, producing a new `Bounds<U>`.
1231 ///
1232 /// This method allows for converting a `Bounds<T>` to a `Bounds<U>` by specifying a closure
1233 /// that defines how to convert between the two types. The closure is applied to the `origin` and
1234 /// `size` fields, resulting in new bounds of the desired type.
1235 ///
1236 /// # Arguments
1237 ///
1238 /// * `f` - A closure that takes a value of type `T` and returns a value of type `U`.
1239 ///
1240 /// # Returns
1241 ///
1242 /// Returns a new `Bounds<U>` with the origin and size mapped by the provided function.
1243 ///
1244 /// # Examples
1245 ///
1246 /// ```
1247 /// # use zed::{Bounds, Point, Size};
1248 /// let bounds = Bounds {
1249 /// origin: Point { x: 10.0, y: 10.0 },
1250 /// size: Size { width: 10.0, height: 20.0 },
1251 /// };
1252 /// let new_bounds = bounds.map(|value| value as f64 * 1.5);
1253 ///
1254 /// assert_eq!(new_bounds, Bounds {
1255 /// origin: Point { x: 15.0, y: 15.0 },
1256 /// size: Size { width: 15.0, height: 30.0 },
1257 /// });
1258 /// ```
1259 pub fn map<U>(&self, f: impl Fn(T) -> U) -> Bounds<U>
1260 where
1261 U: Clone + Default + Debug,
1262 {
1263 Bounds {
1264 origin: self.origin.map(&f),
1265 size: self.size.map(f),
1266 }
1267 }
1268
1269 /// Applies a function to the origin of the bounds, producing a new `Bounds` with the new origin
1270 ///
1271 /// # Examples
1272 ///
1273 /// ```
1274 /// # use zed::{Bounds, Point, Size};
1275 /// let bounds = Bounds {
1276 /// origin: Point { x: 10.0, y: 10.0 },
1277 /// size: Size { width: 10.0, height: 20.0 },
1278 /// };
1279 /// let new_bounds = bounds.map_origin(|value| value * 1.5);
1280 ///
1281 /// assert_eq!(new_bounds, Bounds {
1282 /// origin: Point { x: 15.0, y: 15.0 },
1283 /// size: Size { width: 10.0, height: 20.0 },
1284 /// });
1285 /// ```
1286 pub fn map_origin(self, f: impl Fn(T) -> T) -> Bounds<T> {
1287 Bounds {
1288 origin: self.origin.map(f),
1289 size: self.size,
1290 }
1291 }
1292
1293 /// Applies a function to the origin of the bounds, producing a new `Bounds` with the new origin
1294 ///
1295 /// # Examples
1296 ///
1297 /// ```
1298 /// # use zed::{Bounds, Point, Size};
1299 /// let bounds = Bounds {
1300 /// origin: Point { x: 10.0, y: 10.0 },
1301 /// size: Size { width: 10.0, height: 20.0 },
1302 /// };
1303 /// let new_bounds = bounds.map_size(|value| value * 1.5);
1304 ///
1305 /// assert_eq!(new_bounds, Bounds {
1306 /// origin: Point { x: 10.0, y: 10.0 },
1307 /// size: Size { width: 15.0, height: 30.0 },
1308 /// });
1309 /// ```
1310 pub fn map_size(self, f: impl Fn(T) -> T) -> Bounds<T> {
1311 Bounds {
1312 origin: self.origin,
1313 size: self.size.map(f),
1314 }
1315 }
1316}
1317
1318/// Checks if the bounds represent an empty area.
1319///
1320/// # Returns
1321///
1322/// Returns `true` if either the width or the height of the bounds is less than or equal to zero, indicating an empty area.
1323impl<T: PartialOrd + Default + Debug + Clone> Bounds<T> {
1324 /// Checks if the bounds represent an empty area.
1325 ///
1326 /// # Returns
1327 ///
1328 /// Returns `true` if either the width or the height of the bounds is less than or equal to zero, indicating an empty area.
1329 pub fn is_empty(&self) -> bool {
1330 self.size.width <= T::default() || self.size.height <= T::default()
1331 }
1332}
1333
1334impl Size<DevicePixels> {
1335 /// Converts the size from physical to logical pixels.
1336 pub(crate) fn to_pixels(self, scale_factor: f32) -> Size<Pixels> {
1337 size(
1338 px(self.width.0 as f32 / scale_factor),
1339 px(self.height.0 as f32 / scale_factor),
1340 )
1341 }
1342}
1343
1344impl Size<Pixels> {
1345 /// Converts the size from physical to logical pixels.
1346 pub(crate) fn to_device_pixels(self, scale_factor: f32) -> Size<DevicePixels> {
1347 size(
1348 DevicePixels((self.width.0 * scale_factor) as i32),
1349 DevicePixels((self.height.0 * scale_factor) as i32),
1350 )
1351 }
1352}
1353
1354impl Bounds<Pixels> {
1355 /// Scales the bounds by a given factor, typically used to adjust for display scaling.
1356 ///
1357 /// This method multiplies the origin and size of the bounds by the provided scaling factor,
1358 /// resulting in a new `Bounds<ScaledPixels>` that is proportionally larger or smaller
1359 /// depending on the scaling factor. This can be used to ensure that the bounds are properly
1360 /// scaled for different display densities.
1361 ///
1362 /// # Arguments
1363 ///
1364 /// * `factor` - The scaling factor to apply to the origin and size, typically the display's scaling factor.
1365 ///
1366 /// # Returns
1367 ///
1368 /// Returns a new `Bounds<ScaledPixels>` that represents the scaled bounds.
1369 ///
1370 /// # Examples
1371 ///
1372 /// ```
1373 /// # use zed::{Bounds, Point, Size, Pixels};
1374 /// let bounds = Bounds {
1375 /// origin: Point { x: Pixels(10.0), y: Pixels(20.0) },
1376 /// size: Size { width: Pixels(30.0), height: Pixels(40.0) },
1377 /// };
1378 /// let display_scale_factor = 2.0;
1379 /// let scaled_bounds = bounds.scale(display_scale_factor);
1380 /// assert_eq!(scaled_bounds, Bounds {
1381 /// origin: Point { x: ScaledPixels(20.0), y: ScaledPixels(40.0) },
1382 /// size: Size { width: ScaledPixels(60.0), height: ScaledPixels(80.0) },
1383 /// });
1384 /// ```
1385 pub fn scale(&self, factor: f32) -> Bounds<ScaledPixels> {
1386 Bounds {
1387 origin: self.origin.scale(factor),
1388 size: self.size.scale(factor),
1389 }
1390 }
1391
1392 /// Convert the bounds from logical pixels to physical pixels
1393 pub fn to_device_pixels(&self, factor: f32) -> Bounds<DevicePixels> {
1394 Bounds {
1395 origin: point(
1396 DevicePixels((self.origin.x.0 * factor) as i32),
1397 DevicePixels((self.origin.y.0 * factor) as i32),
1398 ),
1399 size: self.size.to_device_pixels(factor),
1400 }
1401 }
1402}
1403
1404impl Bounds<DevicePixels> {
1405 /// Convert the bounds from physical pixels to logical pixels
1406 pub fn to_pixels(self, scale_factor: f32) -> Bounds<Pixels> {
1407 Bounds {
1408 origin: point(
1409 px(self.origin.x.0 as f32 / scale_factor),
1410 px(self.origin.y.0 as f32 / scale_factor),
1411 ),
1412 size: self.size.to_pixels(scale_factor),
1413 }
1414 }
1415}
1416
1417impl<T: Clone + Debug + Copy + Default> Copy for Bounds<T> {}
1418
1419/// Represents the edges of a box in a 2D space, such as padding or margin.
1420///
1421/// Each field represents the size of the edge on one side of the box: `top`, `right`, `bottom`, and `left`.
1422///
1423/// # Examples
1424///
1425/// ```
1426/// # use zed::Edges;
1427/// let edges = Edges {
1428/// top: 10.0,
1429/// right: 20.0,
1430/// bottom: 30.0,
1431/// left: 40.0,
1432/// };
1433///
1434/// assert_eq!(edges.top, 10.0);
1435/// assert_eq!(edges.right, 20.0);
1436/// assert_eq!(edges.bottom, 30.0);
1437/// assert_eq!(edges.left, 40.0);
1438/// ```
1439#[derive(Refineable, Clone, Default, Debug, Eq, PartialEq)]
1440#[refineable(Debug)]
1441#[repr(C)]
1442pub struct Edges<T: Clone + Default + Debug> {
1443 /// The size of the top edge.
1444 pub top: T,
1445 /// The size of the right edge.
1446 pub right: T,
1447 /// The size of the bottom edge.
1448 pub bottom: T,
1449 /// The size of the left edge.
1450 pub left: T,
1451}
1452
1453impl<T> Mul for Edges<T>
1454where
1455 T: Mul<Output = T> + Clone + Default + Debug,
1456{
1457 type Output = Self;
1458
1459 fn mul(self, rhs: Self) -> Self::Output {
1460 Self {
1461 top: self.top.clone() * rhs.top,
1462 right: self.right.clone() * rhs.right,
1463 bottom: self.bottom.clone() * rhs.bottom,
1464 left: self.left.clone() * rhs.left,
1465 }
1466 }
1467}
1468
1469impl<T, S> MulAssign<S> for Edges<T>
1470where
1471 T: Mul<S, Output = T> + Clone + Default + Debug,
1472 S: Clone,
1473{
1474 fn mul_assign(&mut self, rhs: S) {
1475 self.top = self.top.clone() * rhs.clone();
1476 self.right = self.right.clone() * rhs.clone();
1477 self.bottom = self.bottom.clone() * rhs.clone();
1478 self.left = self.left.clone() * rhs;
1479 }
1480}
1481
1482impl<T: Clone + Default + Debug + Copy> Copy for Edges<T> {}
1483
1484impl<T: Clone + Default + Debug> Edges<T> {
1485 /// Constructs `Edges` where all sides are set to the same specified value.
1486 ///
1487 /// This function creates an `Edges` instance with the `top`, `right`, `bottom`, and `left` fields all initialized
1488 /// to the same value provided as an argument. This is useful when you want to have uniform edges around a box,
1489 /// such as padding or margin with the same size on all sides.
1490 ///
1491 /// # Arguments
1492 ///
1493 /// * `value` - The value to set for all four sides of the edges.
1494 ///
1495 /// # Returns
1496 ///
1497 /// An `Edges` instance with all sides set to the given value.
1498 ///
1499 /// # Examples
1500 ///
1501 /// ```
1502 /// # use zed::Edges;
1503 /// let uniform_edges = Edges::all(10.0);
1504 /// assert_eq!(uniform_edges.top, 10.0);
1505 /// assert_eq!(uniform_edges.right, 10.0);
1506 /// assert_eq!(uniform_edges.bottom, 10.0);
1507 /// assert_eq!(uniform_edges.left, 10.0);
1508 /// ```
1509 pub fn all(value: T) -> Self {
1510 Self {
1511 top: value.clone(),
1512 right: value.clone(),
1513 bottom: value.clone(),
1514 left: value,
1515 }
1516 }
1517
1518 /// Applies a function to each field of the `Edges`, producing a new `Edges<U>`.
1519 ///
1520 /// This method allows for converting an `Edges<T>` to an `Edges<U>` by specifying a closure
1521 /// that defines how to convert between the two types. The closure is applied to each field
1522 /// (`top`, `right`, `bottom`, `left`), resulting in new edges of the desired type.
1523 ///
1524 /// # Arguments
1525 ///
1526 /// * `f` - A closure that takes a reference to a value of type `T` and returns a value of type `U`.
1527 ///
1528 /// # Returns
1529 ///
1530 /// Returns a new `Edges<U>` with each field mapped by the provided function.
1531 ///
1532 /// # Examples
1533 ///
1534 /// ```
1535 /// # use zed::Edges;
1536 /// let edges = Edges { top: 10, right: 20, bottom: 30, left: 40 };
1537 /// let edges_float = edges.map(|&value| value as f32 * 1.1);
1538 /// assert_eq!(edges_float, Edges { top: 11.0, right: 22.0, bottom: 33.0, left: 44.0 });
1539 /// ```
1540 pub fn map<U>(&self, f: impl Fn(&T) -> U) -> Edges<U>
1541 where
1542 U: Clone + Default + Debug,
1543 {
1544 Edges {
1545 top: f(&self.top),
1546 right: f(&self.right),
1547 bottom: f(&self.bottom),
1548 left: f(&self.left),
1549 }
1550 }
1551
1552 /// Checks if any of the edges satisfy a given predicate.
1553 ///
1554 /// This method applies a predicate function to each field of the `Edges` and returns `true` if any field satisfies the predicate.
1555 ///
1556 /// # Arguments
1557 ///
1558 /// * `predicate` - A closure that takes a reference to a value of type `T` and returns a `bool`.
1559 ///
1560 /// # Returns
1561 ///
1562 /// Returns `true` if the predicate returns `true` for any of the edge values, `false` otherwise.
1563 ///
1564 /// # Examples
1565 ///
1566 /// ```
1567 /// # use zed::Edges;
1568 /// let edges = Edges {
1569 /// top: 10,
1570 /// right: 0,
1571 /// bottom: 5,
1572 /// left: 0,
1573 /// };
1574 ///
1575 /// assert!(edges.any(|value| *value == 0));
1576 /// assert!(edges.any(|value| *value > 0));
1577 /// assert!(!edges.any(|value| *value > 10));
1578 /// ```
1579 pub fn any<F: Fn(&T) -> bool>(&self, predicate: F) -> bool {
1580 predicate(&self.top)
1581 || predicate(&self.right)
1582 || predicate(&self.bottom)
1583 || predicate(&self.left)
1584 }
1585}
1586
1587impl Edges<Length> {
1588 /// Sets the edges of the `Edges` struct to `auto`, which is a special value that allows the layout engine to automatically determine the size of the edges.
1589 ///
1590 /// This is typically used in layout contexts where the exact size of the edges is not important, or when the size should be calculated based on the content or container.
1591 ///
1592 /// # Returns
1593 ///
1594 /// Returns an `Edges<Length>` with all edges set to `Length::Auto`.
1595 ///
1596 /// # Examples
1597 ///
1598 /// ```
1599 /// # use zed::Edges;
1600 /// let auto_edges = Edges::auto();
1601 /// assert_eq!(auto_edges.top, Length::Auto);
1602 /// assert_eq!(auto_edges.right, Length::Auto);
1603 /// assert_eq!(auto_edges.bottom, Length::Auto);
1604 /// assert_eq!(auto_edges.left, Length::Auto);
1605 /// ```
1606 pub fn auto() -> Self {
1607 Self {
1608 top: Length::Auto,
1609 right: Length::Auto,
1610 bottom: Length::Auto,
1611 left: Length::Auto,
1612 }
1613 }
1614
1615 /// Sets the edges of the `Edges` struct to zero, which means no size or thickness.
1616 ///
1617 /// This is typically used when you want to specify that a box (like a padding or margin area)
1618 /// should have no edges, effectively making it non-existent or invisible in layout calculations.
1619 ///
1620 /// # Returns
1621 ///
1622 /// Returns an `Edges<Length>` with all edges set to zero length.
1623 ///
1624 /// # Examples
1625 ///
1626 /// ```
1627 /// # use zed::Edges;
1628 /// let no_edges = Edges::zero();
1629 /// assert_eq!(no_edges.top, Length::Definite(DefiniteLength::from(Pixels(0.))));
1630 /// assert_eq!(no_edges.right, Length::Definite(DefiniteLength::from(Pixels(0.))));
1631 /// assert_eq!(no_edges.bottom, Length::Definite(DefiniteLength::from(Pixels(0.))));
1632 /// assert_eq!(no_edges.left, Length::Definite(DefiniteLength::from(Pixels(0.))));
1633 /// ```
1634 pub fn zero() -> Self {
1635 Self {
1636 top: px(0.).into(),
1637 right: px(0.).into(),
1638 bottom: px(0.).into(),
1639 left: px(0.).into(),
1640 }
1641 }
1642}
1643
1644impl Edges<DefiniteLength> {
1645 /// Sets the edges of the `Edges` struct to zero, which means no size or thickness.
1646 ///
1647 /// This is typically used when you want to specify that a box (like a padding or margin area)
1648 /// should have no edges, effectively making it non-existent or invisible in layout calculations.
1649 ///
1650 /// # Returns
1651 ///
1652 /// Returns an `Edges<DefiniteLength>` with all edges set to zero length.
1653 ///
1654 /// # Examples
1655 ///
1656 /// ```
1657 /// # use zed::Edges;
1658 /// let no_edges = Edges::zero();
1659 /// assert_eq!(no_edges.top, DefiniteLength::from(zed::px(0.)));
1660 /// assert_eq!(no_edges.right, DefiniteLength::from(zed::px(0.)));
1661 /// assert_eq!(no_edges.bottom, DefiniteLength::from(zed::px(0.)));
1662 /// assert_eq!(no_edges.left, DefiniteLength::from(zed::px(0.)));
1663 /// ```
1664 pub fn zero() -> Self {
1665 Self {
1666 top: px(0.).into(),
1667 right: px(0.).into(),
1668 bottom: px(0.).into(),
1669 left: px(0.).into(),
1670 }
1671 }
1672
1673 /// Converts the `DefiniteLength` to `Pixels` based on the parent size and the REM size.
1674 ///
1675 /// This method allows for a `DefiniteLength` value to be converted into pixels, taking into account
1676 /// the size of the parent element (for percentage-based lengths) and the size of a rem unit (for rem-based lengths).
1677 ///
1678 /// # Arguments
1679 ///
1680 /// * `parent_size` - `Size<AbsoluteLength>` representing the size of the parent element.
1681 /// * `rem_size` - `Pixels` representing the size of one REM unit.
1682 ///
1683 /// # Returns
1684 ///
1685 /// Returns an `Edges<Pixels>` representing the edges with lengths converted to pixels.
1686 ///
1687 /// # Examples
1688 ///
1689 /// ```
1690 /// # use zed::{Edges, DefiniteLength, px, AbsoluteLength, Size};
1691 /// let edges = Edges {
1692 /// top: DefiniteLength::Absolute(AbsoluteLength::Pixels(px(10.0))),
1693 /// right: DefiniteLength::Fraction(0.5),
1694 /// bottom: DefiniteLength::Absolute(AbsoluteLength::Rems(rems(2.0))),
1695 /// left: DefiniteLength::Fraction(0.25),
1696 /// };
1697 /// let parent_size = Size {
1698 /// width: AbsoluteLength::Pixels(px(200.0)),
1699 /// height: AbsoluteLength::Pixels(px(100.0)),
1700 /// };
1701 /// let rem_size = px(16.0);
1702 /// let edges_in_pixels = edges.to_pixels(parent_size, rem_size);
1703 ///
1704 /// assert_eq!(edges_in_pixels.top, px(10.0)); // Absolute length in pixels
1705 /// assert_eq!(edges_in_pixels.right, px(100.0)); // 50% of parent width
1706 /// assert_eq!(edges_in_pixels.bottom, px(32.0)); // 2 rems
1707 /// assert_eq!(edges_in_pixels.left, px(50.0)); // 25% of parent width
1708 /// ```
1709 pub fn to_pixels(&self, parent_size: Size<AbsoluteLength>, rem_size: Pixels) -> Edges<Pixels> {
1710 Edges {
1711 top: self.top.to_pixels(parent_size.height, rem_size),
1712 right: self.right.to_pixels(parent_size.width, rem_size),
1713 bottom: self.bottom.to_pixels(parent_size.height, rem_size),
1714 left: self.left.to_pixels(parent_size.width, rem_size),
1715 }
1716 }
1717}
1718
1719impl Edges<AbsoluteLength> {
1720 /// Sets the edges of the `Edges` struct to zero, which means no size or thickness.
1721 ///
1722 /// This is typically used when you want to specify that a box (like a padding or margin area)
1723 /// should have no edges, effectively making it non-existent or invisible in layout calculations.
1724 ///
1725 /// # Returns
1726 ///
1727 /// Returns an `Edges<AbsoluteLength>` with all edges set to zero length.
1728 ///
1729 /// # Examples
1730 ///
1731 /// ```
1732 /// # use zed::Edges;
1733 /// let no_edges = Edges::zero();
1734 /// assert_eq!(no_edges.top, AbsoluteLength::Pixels(Pixels(0.0)));
1735 /// assert_eq!(no_edges.right, AbsoluteLength::Pixels(Pixels(0.0)));
1736 /// assert_eq!(no_edges.bottom, AbsoluteLength::Pixels(Pixels(0.0)));
1737 /// assert_eq!(no_edges.left, AbsoluteLength::Pixels(Pixels(0.0)));
1738 /// ```
1739 pub fn zero() -> Self {
1740 Self {
1741 top: px(0.).into(),
1742 right: px(0.).into(),
1743 bottom: px(0.).into(),
1744 left: px(0.).into(),
1745 }
1746 }
1747
1748 /// Converts the `AbsoluteLength` to `Pixels` based on the `rem_size`.
1749 ///
1750 /// If the `AbsoluteLength` is already in pixels, it simply returns the corresponding `Pixels` value.
1751 /// If the `AbsoluteLength` is in rems, it multiplies the number of rems by the `rem_size` to convert it to pixels.
1752 ///
1753 /// # Arguments
1754 ///
1755 /// * `rem_size` - The size of one rem unit in pixels.
1756 ///
1757 /// # Returns
1758 ///
1759 /// Returns an `Edges<Pixels>` representing the edges with lengths converted to pixels.
1760 ///
1761 /// # Examples
1762 ///
1763 /// ```
1764 /// # use zed::{Edges, AbsoluteLength, Pixels, px};
1765 /// let edges = Edges {
1766 /// top: AbsoluteLength::Pixels(px(10.0)),
1767 /// right: AbsoluteLength::Rems(rems(1.0)),
1768 /// bottom: AbsoluteLength::Pixels(px(20.0)),
1769 /// left: AbsoluteLength::Rems(rems(2.0)),
1770 /// };
1771 /// let rem_size = px(16.0);
1772 /// let edges_in_pixels = edges.to_pixels(rem_size);
1773 ///
1774 /// assert_eq!(edges_in_pixels.top, px(10.0)); // Already in pixels
1775 /// assert_eq!(edges_in_pixels.right, px(16.0)); // 1 rem converted to pixels
1776 /// assert_eq!(edges_in_pixels.bottom, px(20.0)); // Already in pixels
1777 /// assert_eq!(edges_in_pixels.left, px(32.0)); // 2 rems converted to pixels
1778 /// ```
1779 pub fn to_pixels(&self, rem_size: Pixels) -> Edges<Pixels> {
1780 Edges {
1781 top: self.top.to_pixels(rem_size),
1782 right: self.right.to_pixels(rem_size),
1783 bottom: self.bottom.to_pixels(rem_size),
1784 left: self.left.to_pixels(rem_size),
1785 }
1786 }
1787}
1788
1789impl Edges<Pixels> {
1790 /// Scales the `Edges<Pixels>` by a given factor, returning `Edges<ScaledPixels>`.
1791 ///
1792 /// This method is typically used for adjusting the edge sizes for different display densities or scaling factors.
1793 ///
1794 /// # Arguments
1795 ///
1796 /// * `factor` - The scaling factor to apply to each edge.
1797 ///
1798 /// # Returns
1799 ///
1800 /// Returns a new `Edges<ScaledPixels>` where each edge is the result of scaling the original edge by the given factor.
1801 ///
1802 /// # Examples
1803 ///
1804 /// ```
1805 /// # use zed::{Edges, Pixels};
1806 /// let edges = Edges {
1807 /// top: Pixels(10.0),
1808 /// right: Pixels(20.0),
1809 /// bottom: Pixels(30.0),
1810 /// left: Pixels(40.0),
1811 /// };
1812 /// let scaled_edges = edges.scale(2.0);
1813 /// assert_eq!(scaled_edges.top, ScaledPixels(20.0));
1814 /// assert_eq!(scaled_edges.right, ScaledPixels(40.0));
1815 /// assert_eq!(scaled_edges.bottom, ScaledPixels(60.0));
1816 /// assert_eq!(scaled_edges.left, ScaledPixels(80.0));
1817 /// ```
1818 pub fn scale(&self, factor: f32) -> Edges<ScaledPixels> {
1819 Edges {
1820 top: self.top.scale(factor),
1821 right: self.right.scale(factor),
1822 bottom: self.bottom.scale(factor),
1823 left: self.left.scale(factor),
1824 }
1825 }
1826
1827 /// Returns the maximum value of any edge.
1828 ///
1829 /// # Returns
1830 ///
1831 /// The maximum `Pixels` value among all four edges.
1832 pub fn max(&self) -> Pixels {
1833 self.top.max(self.right).max(self.bottom).max(self.left)
1834 }
1835}
1836
1837impl From<f32> for Edges<Pixels> {
1838 fn from(val: f32) -> Self {
1839 Edges {
1840 top: val.into(),
1841 right: val.into(),
1842 bottom: val.into(),
1843 left: val.into(),
1844 }
1845 }
1846}
1847
1848/// Represents the corners of a box in a 2D space, such as border radius.
1849///
1850/// Each field represents the size of the corner on one side of the box: `top_left`, `top_right`, `bottom_right`, and `bottom_left`.
1851#[derive(Refineable, Clone, Default, Debug, Eq, PartialEq)]
1852#[refineable(Debug)]
1853#[repr(C)]
1854pub struct Corners<T: Clone + Default + Debug> {
1855 /// The value associated with the top left corner.
1856 pub top_left: T,
1857 /// The value associated with the top right corner.
1858 pub top_right: T,
1859 /// The value associated with the bottom right corner.
1860 pub bottom_right: T,
1861 /// The value associated with the bottom left corner.
1862 pub bottom_left: T,
1863}
1864
1865impl<T> Corners<T>
1866where
1867 T: Clone + Default + Debug,
1868{
1869 /// Constructs `Corners` where all sides are set to the same specified value.
1870 ///
1871 /// This function creates a `Corners` instance with the `top_left`, `top_right`, `bottom_right`, and `bottom_left` fields all initialized
1872 /// to the same value provided as an argument. This is useful when you want to have uniform corners around a box,
1873 /// such as a uniform border radius on a rectangle.
1874 ///
1875 /// # Arguments
1876 ///
1877 /// * `value` - The value to set for all four corners.
1878 ///
1879 /// # Returns
1880 ///
1881 /// An `Corners` instance with all corners set to the given value.
1882 ///
1883 /// # Examples
1884 ///
1885 /// ```
1886 /// # use zed::Corners;
1887 /// let uniform_corners = Corners::all(5.0);
1888 /// assert_eq!(uniform_corners.top_left, 5.0);
1889 /// assert_eq!(uniform_corners.top_right, 5.0);
1890 /// assert_eq!(uniform_corners.bottom_right, 5.0);
1891 /// assert_eq!(uniform_corners.bottom_left, 5.0);
1892 /// ```
1893 pub fn all(value: T) -> Self {
1894 Self {
1895 top_left: value.clone(),
1896 top_right: value.clone(),
1897 bottom_right: value.clone(),
1898 bottom_left: value,
1899 }
1900 }
1901}
1902
1903impl Corners<AbsoluteLength> {
1904 /// Converts the `AbsoluteLength` to `Pixels` based on the provided size and rem size, ensuring the resulting
1905 /// `Pixels` do not exceed half of the minimum of the provided size's width and height.
1906 ///
1907 /// This method is particularly useful when dealing with corner radii, where the radius in pixels should not
1908 /// exceed half the size of the box it applies to, to avoid the corners overlapping.
1909 ///
1910 /// # Arguments
1911 ///
1912 /// * `size` - The `Size<Pixels>` against which the minimum allowable radius is determined.
1913 /// * `rem_size` - The size of one REM unit in pixels, used for conversion if the `AbsoluteLength` is in REMs.
1914 ///
1915 /// # Returns
1916 ///
1917 /// Returns a `Corners<Pixels>` instance with each corner's length converted to pixels and clamped to the
1918 /// minimum allowable radius based on the provided size.
1919 ///
1920 /// # Examples
1921 ///
1922 /// ```
1923 /// # use zed::{Corners, AbsoluteLength, Pixels, Size};
1924 /// let corners = Corners {
1925 /// top_left: AbsoluteLength::Pixels(Pixels(15.0)),
1926 /// top_right: AbsoluteLength::Rems(Rems(1.0)),
1927 /// bottom_right: AbsoluteLength::Pixels(Pixels(30.0)),
1928 /// bottom_left: AbsoluteLength::Rems(Rems(2.0)),
1929 /// };
1930 /// let size = Size { width: Pixels(100.0), height: Pixels(50.0) };
1931 /// let rem_size = Pixels(16.0);
1932 /// let corners_in_pixels = corners.to_pixels(size, rem_size);
1933 ///
1934 /// // The resulting corners should not exceed half the size of the smallest dimension (50.0 / 2.0 = 25.0).
1935 /// assert_eq!(corners_in_pixels.top_left, Pixels(15.0));
1936 /// assert_eq!(corners_in_pixels.top_right, Pixels(16.0)); // 1 rem converted to pixels
1937 /// assert_eq!(corners_in_pixels.bottom_right, Pixels(30.0).min(Pixels(25.0))); // Clamped to 25.0
1938 /// assert_eq!(corners_in_pixels.bottom_left, Pixels(32.0).min(Pixels(25.0))); // 2 rems converted to pixels and clamped to 25.0
1939 /// ```
1940 pub fn to_pixels(&self, size: Size<Pixels>, rem_size: Pixels) -> Corners<Pixels> {
1941 let max = size.width.min(size.height) / 2.;
1942 Corners {
1943 top_left: self.top_left.to_pixels(rem_size).min(max),
1944 top_right: self.top_right.to_pixels(rem_size).min(max),
1945 bottom_right: self.bottom_right.to_pixels(rem_size).min(max),
1946 bottom_left: self.bottom_left.to_pixels(rem_size).min(max),
1947 }
1948 }
1949}
1950
1951impl Corners<Pixels> {
1952 /// Scales the `Corners<Pixels>` by a given factor, returning `Corners<ScaledPixels>`.
1953 ///
1954 /// This method is typically used for adjusting the corner sizes for different display densities or scaling factors.
1955 ///
1956 /// # Arguments
1957 ///
1958 /// * `factor` - The scaling factor to apply to each corner.
1959 ///
1960 /// # Returns
1961 ///
1962 /// Returns a new `Corners<ScaledPixels>` where each corner is the result of scaling the original corner by the given factor.
1963 ///
1964 /// # Examples
1965 ///
1966 /// ```
1967 /// # use zed::{Corners, Pixels};
1968 /// let corners = Corners {
1969 /// top_left: Pixels(10.0),
1970 /// top_right: Pixels(20.0),
1971 /// bottom_right: Pixels(30.0),
1972 /// bottom_left: Pixels(40.0),
1973 /// };
1974 /// let scaled_corners = corners.scale(2.0);
1975 /// assert_eq!(scaled_corners.top_left, ScaledPixels(20.0));
1976 /// assert_eq!(scaled_corners.top_right, ScaledPixels(40.0));
1977 /// assert_eq!(scaled_corners.bottom_right, ScaledPixels(60.0));
1978 /// assert_eq!(scaled_corners.bottom_left, ScaledPixels(80.0));
1979 /// ```
1980 pub fn scale(&self, factor: f32) -> Corners<ScaledPixels> {
1981 Corners {
1982 top_left: self.top_left.scale(factor),
1983 top_right: self.top_right.scale(factor),
1984 bottom_right: self.bottom_right.scale(factor),
1985 bottom_left: self.bottom_left.scale(factor),
1986 }
1987 }
1988
1989 /// Returns the maximum value of any corner.
1990 ///
1991 /// # Returns
1992 ///
1993 /// The maximum `Pixels` value among all four corners.
1994 pub fn max(&self) -> Pixels {
1995 self.top_left
1996 .max(self.top_right)
1997 .max(self.bottom_right)
1998 .max(self.bottom_left)
1999 }
2000}
2001
2002impl<T: Clone + Default + Debug> Corners<T> {
2003 /// Applies a function to each field of the `Corners`, producing a new `Corners<U>`.
2004 ///
2005 /// This method allows for converting a `Corners<T>` to a `Corners<U>` by specifying a closure
2006 /// that defines how to convert between the two types. The closure is applied to each field
2007 /// (`top_left`, `top_right`, `bottom_right`, `bottom_left`), resulting in new corners of the desired type.
2008 ///
2009 /// # Arguments
2010 ///
2011 /// * `f` - A closure that takes a reference to a value of type `T` and returns a value of type `U`.
2012 ///
2013 /// # Returns
2014 ///
2015 /// Returns a new `Corners<U>` with each field mapped by the provided function.
2016 ///
2017 /// # Examples
2018 ///
2019 /// ```
2020 /// # use zed::{Corners, Pixels};
2021 /// let corners = Corners {
2022 /// top_left: Pixels(10.0),
2023 /// top_right: Pixels(20.0),
2024 /// bottom_right: Pixels(30.0),
2025 /// bottom_left: Pixels(40.0),
2026 /// };
2027 /// let corners_in_rems = corners.map(|&px| Rems(px.0 / 16.0));
2028 /// assert_eq!(corners_in_rems, Corners {
2029 /// top_left: Rems(0.625),
2030 /// top_right: Rems(1.25),
2031 /// bottom_right: Rems(1.875),
2032 /// bottom_left: Rems(2.5),
2033 /// });
2034 /// ```
2035 pub fn map<U>(&self, f: impl Fn(&T) -> U) -> Corners<U>
2036 where
2037 U: Clone + Default + Debug,
2038 {
2039 Corners {
2040 top_left: f(&self.top_left),
2041 top_right: f(&self.top_right),
2042 bottom_right: f(&self.bottom_right),
2043 bottom_left: f(&self.bottom_left),
2044 }
2045 }
2046}
2047
2048impl<T> Mul for Corners<T>
2049where
2050 T: Mul<Output = T> + Clone + Default + Debug,
2051{
2052 type Output = Self;
2053
2054 fn mul(self, rhs: Self) -> Self::Output {
2055 Self {
2056 top_left: self.top_left.clone() * rhs.top_left,
2057 top_right: self.top_right.clone() * rhs.top_right,
2058 bottom_right: self.bottom_right.clone() * rhs.bottom_right,
2059 bottom_left: self.bottom_left.clone() * rhs.bottom_left,
2060 }
2061 }
2062}
2063
2064impl<T, S> MulAssign<S> for Corners<T>
2065where
2066 T: Mul<S, Output = T> + Clone + Default + Debug,
2067 S: Clone,
2068{
2069 fn mul_assign(&mut self, rhs: S) {
2070 self.top_left = self.top_left.clone() * rhs.clone();
2071 self.top_right = self.top_right.clone() * rhs.clone();
2072 self.bottom_right = self.bottom_right.clone() * rhs.clone();
2073 self.bottom_left = self.bottom_left.clone() * rhs;
2074 }
2075}
2076
2077impl<T> Copy for Corners<T> where T: Copy + Clone + Default + Debug {}
2078
2079impl From<f32> for Corners<Pixels> {
2080 fn from(val: f32) -> Self {
2081 Corners {
2082 top_left: val.into(),
2083 top_right: val.into(),
2084 bottom_right: val.into(),
2085 bottom_left: val.into(),
2086 }
2087 }
2088}
2089
2090impl From<Pixels> for Corners<Pixels> {
2091 fn from(val: Pixels) -> Self {
2092 Corners {
2093 top_left: val,
2094 top_right: val,
2095 bottom_right: val,
2096 bottom_left: val,
2097 }
2098 }
2099}
2100
2101/// Represents an angle in Radians
2102#[derive(
2103 Clone,
2104 Copy,
2105 Default,
2106 Add,
2107 AddAssign,
2108 Sub,
2109 SubAssign,
2110 Neg,
2111 Div,
2112 DivAssign,
2113 PartialEq,
2114 Serialize,
2115 Deserialize,
2116 Debug,
2117)]
2118#[repr(transparent)]
2119pub struct Radians(pub f32);
2120
2121/// Create a `Radian` from a raw value
2122pub fn radians(value: f32) -> Radians {
2123 Radians(value)
2124}
2125
2126/// A type representing a percentage value.
2127#[derive(
2128 Clone,
2129 Copy,
2130 Default,
2131 Add,
2132 AddAssign,
2133 Sub,
2134 SubAssign,
2135 Neg,
2136 Div,
2137 DivAssign,
2138 PartialEq,
2139 Serialize,
2140 Deserialize,
2141 Debug,
2142)]
2143#[repr(transparent)]
2144pub struct Percentage(pub f32);
2145
2146/// Generate a `Radian` from a percentage of a full circle.
2147pub fn percentage(value: f32) -> Percentage {
2148 debug_assert!(
2149 value >= 0.0 && value <= 1.0,
2150 "Percentage must be between 0 and 1"
2151 );
2152 Percentage(value)
2153}
2154
2155impl From<Percentage> for Radians {
2156 fn from(value: Percentage) -> Self {
2157 radians(value.0 * std::f32::consts::PI * 2.0)
2158 }
2159}
2160
2161/// Represents a length in pixels, the base unit of measurement in the UI framework.
2162///
2163/// `Pixels` is a value type that represents an absolute length in pixels, which is used
2164/// for specifying sizes, positions, and distances in the UI. It is the fundamental unit
2165/// of measurement for all visual elements and layout calculations.
2166///
2167/// The inner value is an `f32`, allowing for sub-pixel precision which can be useful for
2168/// anti-aliasing and animations. However, when applied to actual pixel grids, the value
2169/// is typically rounded to the nearest integer.
2170///
2171/// # Examples
2172///
2173/// ```
2174/// use zed::Pixels;
2175///
2176/// // Define a length of 10 pixels
2177/// let length = Pixels(10.0);
2178///
2179/// // Define a length and scale it by a factor of 2
2180/// let scaled_length = length.scale(2.0);
2181/// assert_eq!(scaled_length, Pixels(20.0));
2182/// ```
2183#[derive(
2184 Clone,
2185 Copy,
2186 Default,
2187 Add,
2188 AddAssign,
2189 Sub,
2190 SubAssign,
2191 Neg,
2192 Div,
2193 DivAssign,
2194 PartialEq,
2195 Serialize,
2196 Deserialize,
2197)]
2198#[repr(transparent)]
2199pub struct Pixels(pub f32);
2200
2201impl std::fmt::Display for Pixels {
2202 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2203 f.write_fmt(format_args!("{}px", self.0))
2204 }
2205}
2206
2207impl std::ops::Div for Pixels {
2208 type Output = f32;
2209
2210 fn div(self, rhs: Self) -> Self::Output {
2211 self.0 / rhs.0
2212 }
2213}
2214
2215impl std::ops::DivAssign for Pixels {
2216 fn div_assign(&mut self, rhs: Self) {
2217 *self = Self(self.0 / rhs.0);
2218 }
2219}
2220
2221impl std::ops::RemAssign for Pixels {
2222 fn rem_assign(&mut self, rhs: Self) {
2223 self.0 %= rhs.0;
2224 }
2225}
2226
2227impl std::ops::Rem for Pixels {
2228 type Output = Self;
2229
2230 fn rem(self, rhs: Self) -> Self {
2231 Self(self.0 % rhs.0)
2232 }
2233}
2234
2235impl Mul<f32> for Pixels {
2236 type Output = Pixels;
2237
2238 fn mul(self, other: f32) -> Pixels {
2239 Pixels(self.0 * other)
2240 }
2241}
2242
2243impl Mul<usize> for Pixels {
2244 type Output = Pixels;
2245
2246 fn mul(self, other: usize) -> Pixels {
2247 Pixels(self.0 * other as f32)
2248 }
2249}
2250
2251impl Mul<Pixels> for f32 {
2252 type Output = Pixels;
2253
2254 fn mul(self, rhs: Pixels) -> Self::Output {
2255 Pixels(self * rhs.0)
2256 }
2257}
2258
2259impl MulAssign<f32> for Pixels {
2260 fn mul_assign(&mut self, other: f32) {
2261 self.0 *= other;
2262 }
2263}
2264
2265impl Pixels {
2266 /// Represents zero pixels.
2267 pub const ZERO: Pixels = Pixels(0.0);
2268 /// The maximum value that can be represented by `Pixels`.
2269 pub const MAX: Pixels = Pixels(f32::MAX);
2270
2271 /// Floors the `Pixels` value to the nearest whole number.
2272 ///
2273 /// # Returns
2274 ///
2275 /// Returns a new `Pixels` instance with the floored value.
2276 pub fn floor(&self) -> Self {
2277 Self(self.0.floor())
2278 }
2279
2280 /// Rounds the `Pixels` value to the nearest whole number.
2281 ///
2282 /// # Returns
2283 ///
2284 /// Returns a new `Pixels` instance with the rounded value.
2285 pub fn round(&self) -> Self {
2286 Self(self.0.round())
2287 }
2288
2289 /// Returns the ceiling of the `Pixels` value to the nearest whole number.
2290 ///
2291 /// # Returns
2292 ///
2293 /// Returns a new `Pixels` instance with the ceiling value.
2294 pub fn ceil(&self) -> Self {
2295 Self(self.0.ceil())
2296 }
2297
2298 /// Scales the `Pixels` value by a given factor, producing `ScaledPixels`.
2299 ///
2300 /// This method is used when adjusting pixel values for display scaling factors,
2301 /// such as high DPI (dots per inch) or Retina displays, where the pixel density is higher and
2302 /// thus requires scaling to maintain visual consistency and readability.
2303 ///
2304 /// The resulting `ScaledPixels` represent the scaled value which can be used for rendering
2305 /// calculations where display scaling is considered.
2306 pub fn scale(&self, factor: f32) -> ScaledPixels {
2307 ScaledPixels(self.0 * factor)
2308 }
2309
2310 /// Raises the `Pixels` value to a given power.
2311 ///
2312 /// # Arguments
2313 ///
2314 /// * `exponent` - The exponent to raise the `Pixels` value by.
2315 ///
2316 /// # Returns
2317 ///
2318 /// Returns a new `Pixels` instance with the value raised to the given exponent.
2319 pub fn pow(&self, exponent: f32) -> Self {
2320 Self(self.0.powf(exponent))
2321 }
2322
2323 /// Returns the absolute value of the `Pixels`.
2324 ///
2325 /// # Returns
2326 ///
2327 /// A new `Pixels` instance with the absolute value of the original `Pixels`.
2328 pub fn abs(&self) -> Self {
2329 Self(self.0.abs())
2330 }
2331
2332 /// Returns the sign of the `Pixels` value.
2333 ///
2334 /// # Returns
2335 ///
2336 /// Returns:
2337 /// * `1.0` if the value is positive
2338 /// * `-1.0` if the value is negative
2339 /// * `0.0` if the value is zero
2340 pub fn signum(&self) -> f32 {
2341 self.0.signum()
2342 }
2343
2344 /// Returns the f64 value of `Pixels`.
2345 ///
2346 /// # Returns
2347 ///
2348 /// A f64 value of the `Pixels`.
2349 pub fn to_f64(self) -> f64 {
2350 self.0 as f64
2351 }
2352}
2353
2354impl Mul<Pixels> for Pixels {
2355 type Output = Pixels;
2356
2357 fn mul(self, rhs: Pixels) -> Self::Output {
2358 Pixels(self.0 * rhs.0)
2359 }
2360}
2361
2362impl Eq for Pixels {}
2363
2364impl PartialOrd for Pixels {
2365 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
2366 Some(self.cmp(other))
2367 }
2368}
2369
2370impl Ord for Pixels {
2371 fn cmp(&self, other: &Self) -> cmp::Ordering {
2372 self.0.total_cmp(&other.0)
2373 }
2374}
2375
2376impl std::hash::Hash for Pixels {
2377 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2378 self.0.to_bits().hash(state);
2379 }
2380}
2381
2382impl From<f64> for Pixels {
2383 fn from(pixels: f64) -> Self {
2384 Pixels(pixels as f32)
2385 }
2386}
2387
2388impl From<f32> for Pixels {
2389 fn from(pixels: f32) -> Self {
2390 Pixels(pixels)
2391 }
2392}
2393
2394impl Debug for Pixels {
2395 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2396 write!(f, "{} px", self.0)
2397 }
2398}
2399
2400impl From<Pixels> for f32 {
2401 fn from(pixels: Pixels) -> Self {
2402 pixels.0
2403 }
2404}
2405
2406impl From<&Pixels> for f32 {
2407 fn from(pixels: &Pixels) -> Self {
2408 pixels.0
2409 }
2410}
2411
2412impl From<Pixels> for f64 {
2413 fn from(pixels: Pixels) -> Self {
2414 pixels.0 as f64
2415 }
2416}
2417
2418impl From<Pixels> for u32 {
2419 fn from(pixels: Pixels) -> Self {
2420 pixels.0 as u32
2421 }
2422}
2423
2424impl From<u32> for Pixels {
2425 fn from(pixels: u32) -> Self {
2426 Pixels(pixels as f32)
2427 }
2428}
2429
2430impl From<Pixels> for usize {
2431 fn from(pixels: Pixels) -> Self {
2432 pixels.0 as usize
2433 }
2434}
2435
2436impl From<usize> for Pixels {
2437 fn from(pixels: usize) -> Self {
2438 Pixels(pixels as f32)
2439 }
2440}
2441
2442/// Represents physical pixels on the display.
2443///
2444/// `DevicePixels` is a unit of measurement that refers to the actual pixels on a device's screen.
2445/// This type is used when precise pixel manipulation is required, such as rendering graphics or
2446/// interfacing with hardware that operates on the pixel level. Unlike logical pixels that may be
2447/// affected by the device's scale factor, `DevicePixels` always correspond to real pixels on the
2448/// display.
2449#[derive(
2450 Add,
2451 AddAssign,
2452 Clone,
2453 Copy,
2454 Default,
2455 Div,
2456 Eq,
2457 Hash,
2458 Ord,
2459 PartialEq,
2460 PartialOrd,
2461 Sub,
2462 SubAssign,
2463 Serialize,
2464 Deserialize,
2465)]
2466#[repr(transparent)]
2467pub struct DevicePixels(pub i32);
2468
2469impl DevicePixels {
2470 /// Converts the `DevicePixels` value to the number of bytes needed to represent it in memory.
2471 ///
2472 /// This function is useful when working with graphical data that needs to be stored in a buffer,
2473 /// such as images or framebuffers, where each pixel may be represented by a specific number of bytes.
2474 ///
2475 /// # Arguments
2476 ///
2477 /// * `bytes_per_pixel` - The number of bytes used to represent a single pixel.
2478 ///
2479 /// # Returns
2480 ///
2481 /// The number of bytes required to represent the `DevicePixels` value in memory.
2482 ///
2483 /// # Examples
2484 ///
2485 /// ```
2486 /// # use zed::DevicePixels;
2487 /// let pixels = DevicePixels(10); // 10 device pixels
2488 /// let bytes_per_pixel = 4; // Assume each pixel is represented by 4 bytes (e.g., RGBA)
2489 /// let total_bytes = pixels.to_bytes(bytes_per_pixel);
2490 /// assert_eq!(total_bytes, 40); // 10 pixels * 4 bytes/pixel = 40 bytes
2491 /// ```
2492 pub fn to_bytes(&self, bytes_per_pixel: u8) -> u32 {
2493 self.0 as u32 * bytes_per_pixel as u32
2494 }
2495}
2496
2497impl fmt::Debug for DevicePixels {
2498 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2499 write!(f, "{} px (device)", self.0)
2500 }
2501}
2502
2503impl From<DevicePixels> for i32 {
2504 fn from(device_pixels: DevicePixels) -> Self {
2505 device_pixels.0
2506 }
2507}
2508
2509impl From<i32> for DevicePixels {
2510 fn from(device_pixels: i32) -> Self {
2511 DevicePixels(device_pixels)
2512 }
2513}
2514
2515impl From<u32> for DevicePixels {
2516 fn from(device_pixels: u32) -> Self {
2517 DevicePixels(device_pixels as i32)
2518 }
2519}
2520
2521impl From<DevicePixels> for u32 {
2522 fn from(device_pixels: DevicePixels) -> Self {
2523 device_pixels.0 as u32
2524 }
2525}
2526
2527impl From<DevicePixels> for u64 {
2528 fn from(device_pixels: DevicePixels) -> Self {
2529 device_pixels.0 as u64
2530 }
2531}
2532
2533impl From<u64> for DevicePixels {
2534 fn from(device_pixels: u64) -> Self {
2535 DevicePixels(device_pixels as i32)
2536 }
2537}
2538
2539impl From<DevicePixels> for usize {
2540 fn from(device_pixels: DevicePixels) -> Self {
2541 device_pixels.0 as usize
2542 }
2543}
2544
2545impl From<usize> for DevicePixels {
2546 fn from(device_pixels: usize) -> Self {
2547 DevicePixels(device_pixels as i32)
2548 }
2549}
2550
2551/// Represents scaled pixels that take into account the device's scale factor.
2552///
2553/// `ScaledPixels` are used to ensure that UI elements appear at the correct size on devices
2554/// with different pixel densities. When a device has a higher scale factor (such as Retina displays),
2555/// a single logical pixel may correspond to multiple physical pixels. By using `ScaledPixels`,
2556/// dimensions and positions can be specified in a way that scales appropriately across different
2557/// display resolutions.
2558#[derive(Clone, Copy, Default, Add, AddAssign, Sub, SubAssign, Div, PartialEq, PartialOrd)]
2559#[repr(transparent)]
2560pub struct ScaledPixels(pub(crate) f32);
2561
2562impl ScaledPixels {
2563 /// Floors the `ScaledPixels` value to the nearest whole number.
2564 ///
2565 /// # Returns
2566 ///
2567 /// Returns a new `ScaledPixels` instance with the floored value.
2568 pub fn floor(&self) -> Self {
2569 Self(self.0.floor())
2570 }
2571
2572 /// Rounds the `ScaledPixels` value to the nearest whole number.
2573 ///
2574 /// # Returns
2575 ///
2576 /// Returns a new `ScaledPixels` instance with the rounded value.
2577 pub fn ceil(&self) -> Self {
2578 Self(self.0.ceil())
2579 }
2580}
2581
2582impl Eq for ScaledPixels {}
2583
2584impl Debug for ScaledPixels {
2585 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2586 write!(f, "{} px (scaled)", self.0)
2587 }
2588}
2589
2590impl From<ScaledPixels> for DevicePixels {
2591 fn from(scaled: ScaledPixels) -> Self {
2592 DevicePixels(scaled.0.ceil() as i32)
2593 }
2594}
2595
2596impl From<DevicePixels> for ScaledPixels {
2597 fn from(device: DevicePixels) -> Self {
2598 ScaledPixels(device.0 as f32)
2599 }
2600}
2601
2602impl From<ScaledPixels> for f64 {
2603 fn from(scaled_pixels: ScaledPixels) -> Self {
2604 scaled_pixels.0 as f64
2605 }
2606}
2607
2608/// Represents a length in rems, a unit based on the font-size of the window, which can be assigned with [`WindowContext::set_rem_size`][set_rem_size].
2609///
2610/// Rems are used for defining lengths that are scalable and consistent across different UI elements.
2611/// The value of `1rem` is typically equal to the font-size of the root element (often the `<html>` element in browsers),
2612/// making it a flexible unit that adapts to the user's text size preferences. In this framework, `rems` serve a similar
2613/// purpose, allowing for scalable and accessible design that can adjust to different display settings or user preferences.
2614///
2615/// For example, if the root element's font-size is `16px`, then `1rem` equals `16px`. A length of `2rems` would then be `32px`.
2616///
2617/// [set_rem_size]: crate::WindowContext::set_rem_size
2618#[derive(Clone, Copy, Default, Add, Sub, Mul, Div, Neg, PartialEq)]
2619pub struct Rems(pub f32);
2620
2621impl Rems {
2622 /// Convert this Rem value to pixels.
2623 pub fn to_pixels(&self, rem_size: Pixels) -> Pixels {
2624 *self * rem_size
2625 }
2626}
2627
2628impl Mul<Pixels> for Rems {
2629 type Output = Pixels;
2630
2631 fn mul(self, other: Pixels) -> Pixels {
2632 Pixels(self.0 * other.0)
2633 }
2634}
2635
2636impl Debug for Rems {
2637 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2638 write!(f, "{} rem", self.0)
2639 }
2640}
2641
2642/// Represents an absolute length in pixels or rems.
2643///
2644/// `AbsoluteLength` can be either a fixed number of pixels, which is an absolute measurement not
2645/// affected by the current font size, or a number of rems, which is relative to the font size of
2646/// the root element. It is used for specifying dimensions that are either independent of or
2647/// related to the typographic scale.
2648#[derive(Clone, Copy, Debug, Neg, PartialEq)]
2649pub enum AbsoluteLength {
2650 /// A length in pixels.
2651 Pixels(Pixels),
2652 /// A length in rems.
2653 Rems(Rems),
2654}
2655
2656impl AbsoluteLength {
2657 /// Checks if the absolute length is zero.
2658 pub fn is_zero(&self) -> bool {
2659 match self {
2660 AbsoluteLength::Pixels(px) => px.0 == 0.0,
2661 AbsoluteLength::Rems(rems) => rems.0 == 0.0,
2662 }
2663 }
2664}
2665
2666impl From<Pixels> for AbsoluteLength {
2667 fn from(pixels: Pixels) -> Self {
2668 AbsoluteLength::Pixels(pixels)
2669 }
2670}
2671
2672impl From<Rems> for AbsoluteLength {
2673 fn from(rems: Rems) -> Self {
2674 AbsoluteLength::Rems(rems)
2675 }
2676}
2677
2678impl AbsoluteLength {
2679 /// Converts an `AbsoluteLength` to `Pixels` based on a given `rem_size`.
2680 ///
2681 /// # Arguments
2682 ///
2683 /// * `rem_size` - The size of one rem in pixels.
2684 ///
2685 /// # Returns
2686 ///
2687 /// Returns the `AbsoluteLength` as `Pixels`.
2688 ///
2689 /// # Examples
2690 ///
2691 /// ```
2692 /// # use zed::{AbsoluteLength, Pixels};
2693 /// let length_in_pixels = AbsoluteLength::Pixels(Pixels(42.0));
2694 /// let length_in_rems = AbsoluteLength::Rems(Rems(2.0));
2695 /// let rem_size = Pixels(16.0);
2696 ///
2697 /// assert_eq!(length_in_pixels.to_pixels(rem_size), Pixels(42.0));
2698 /// assert_eq!(length_in_rems.to_pixels(rem_size), Pixels(32.0));
2699 /// ```
2700 pub fn to_pixels(&self, rem_size: Pixels) -> Pixels {
2701 match self {
2702 AbsoluteLength::Pixels(pixels) => *pixels,
2703 AbsoluteLength::Rems(rems) => rems.to_pixels(rem_size),
2704 }
2705 }
2706}
2707
2708impl Default for AbsoluteLength {
2709 fn default() -> Self {
2710 px(0.).into()
2711 }
2712}
2713
2714/// A non-auto length that can be defined in pixels, rems, or percent of parent.
2715///
2716/// This enum represents lengths that have a specific value, as opposed to lengths that are automatically
2717/// determined by the context. It includes absolute lengths in pixels or rems, and relative lengths as a
2718/// fraction of the parent's size.
2719#[derive(Clone, Copy, Neg, PartialEq)]
2720pub enum DefiniteLength {
2721 /// An absolute length specified in pixels or rems.
2722 Absolute(AbsoluteLength),
2723 /// A relative length specified as a fraction of the parent's size, between 0 and 1.
2724 Fraction(f32),
2725}
2726
2727impl DefiniteLength {
2728 /// Converts the `DefiniteLength` to `Pixels` based on a given `base_size` and `rem_size`.
2729 ///
2730 /// If the `DefiniteLength` is an absolute length, it will be directly converted to `Pixels`.
2731 /// If it is a fraction, the fraction will be multiplied by the `base_size` to get the length in pixels.
2732 ///
2733 /// # Arguments
2734 ///
2735 /// * `base_size` - The base size in `AbsoluteLength` to which the fraction will be applied.
2736 /// * `rem_size` - The size of one rem in pixels, used to convert rems to pixels.
2737 ///
2738 /// # Returns
2739 ///
2740 /// Returns the `DefiniteLength` as `Pixels`.
2741 ///
2742 /// # Examples
2743 ///
2744 /// ```
2745 /// # use zed::{DefiniteLength, AbsoluteLength, Pixels, px, rems};
2746 /// let length_in_pixels = DefiniteLength::Absolute(AbsoluteLength::Pixels(px(42.0)));
2747 /// let length_in_rems = DefiniteLength::Absolute(AbsoluteLength::Rems(rems(2.0)));
2748 /// let length_as_fraction = DefiniteLength::Fraction(0.5);
2749 /// let base_size = AbsoluteLength::Pixels(px(100.0));
2750 /// let rem_size = px(16.0);
2751 ///
2752 /// assert_eq!(length_in_pixels.to_pixels(base_size, rem_size), Pixels(42.0));
2753 /// assert_eq!(length_in_rems.to_pixels(base_size, rem_size), Pixels(32.0));
2754 /// assert_eq!(length_as_fraction.to_pixels(base_size, rem_size), Pixels(50.0));
2755 /// ```
2756 pub fn to_pixels(&self, base_size: AbsoluteLength, rem_size: Pixels) -> Pixels {
2757 match self {
2758 DefiniteLength::Absolute(size) => size.to_pixels(rem_size),
2759 DefiniteLength::Fraction(fraction) => match base_size {
2760 AbsoluteLength::Pixels(px) => px * *fraction,
2761 AbsoluteLength::Rems(rems) => rems * rem_size * *fraction,
2762 },
2763 }
2764 }
2765}
2766
2767impl Debug for DefiniteLength {
2768 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2769 match self {
2770 DefiniteLength::Absolute(length) => Debug::fmt(length, f),
2771 DefiniteLength::Fraction(fract) => write!(f, "{}%", (fract * 100.0) as i32),
2772 }
2773 }
2774}
2775
2776impl From<Pixels> for DefiniteLength {
2777 fn from(pixels: Pixels) -> Self {
2778 Self::Absolute(pixels.into())
2779 }
2780}
2781
2782impl From<Rems> for DefiniteLength {
2783 fn from(rems: Rems) -> Self {
2784 Self::Absolute(rems.into())
2785 }
2786}
2787
2788impl From<AbsoluteLength> for DefiniteLength {
2789 fn from(length: AbsoluteLength) -> Self {
2790 Self::Absolute(length)
2791 }
2792}
2793
2794impl Default for DefiniteLength {
2795 fn default() -> Self {
2796 Self::Absolute(AbsoluteLength::default())
2797 }
2798}
2799
2800/// A length that can be defined in pixels, rems, percent of parent, or auto.
2801#[derive(Clone, Copy)]
2802pub enum Length {
2803 /// A definite length specified either in pixels, rems, or as a fraction of the parent's size.
2804 Definite(DefiniteLength),
2805 /// An automatic length that is determined by the context in which it is used.
2806 Auto,
2807}
2808
2809impl Debug for Length {
2810 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2811 match self {
2812 Length::Definite(definite_length) => write!(f, "{:?}", definite_length),
2813 Length::Auto => write!(f, "auto"),
2814 }
2815 }
2816}
2817
2818/// Constructs a `DefiniteLength` representing a relative fraction of a parent size.
2819///
2820/// This function creates a `DefiniteLength` that is a specified fraction of a parent's dimension.
2821/// The fraction should be a floating-point number between 0.0 and 1.0, where 1.0 represents 100% of the parent's size.
2822///
2823/// # Arguments
2824///
2825/// * `fraction` - The fraction of the parent's size, between 0.0 and 1.0.
2826///
2827/// # Returns
2828///
2829/// A `DefiniteLength` representing the relative length as a fraction of the parent's size.
2830pub fn relative(fraction: f32) -> DefiniteLength {
2831 DefiniteLength::Fraction(fraction)
2832}
2833
2834/// Returns the Golden Ratio, i.e. `~(1.0 + sqrt(5.0)) / 2.0`.
2835pub fn phi() -> DefiniteLength {
2836 relative(1.618_034)
2837}
2838
2839/// Constructs a `Rems` value representing a length in rems.
2840///
2841/// # Arguments
2842///
2843/// * `rems` - The number of rems for the length.
2844///
2845/// # Returns
2846///
2847/// A `Rems` representing the specified number of rems.
2848pub fn rems(rems: f32) -> Rems {
2849 Rems(rems)
2850}
2851
2852/// Constructs a `Pixels` value representing a length in pixels.
2853///
2854/// # Arguments
2855///
2856/// * `pixels` - The number of pixels for the length.
2857///
2858/// # Returns
2859///
2860/// A `Pixels` representing the specified number of pixels.
2861pub const fn px(pixels: f32) -> Pixels {
2862 Pixels(pixels)
2863}
2864
2865/// Returns a `Length` representing an automatic length.
2866///
2867/// The `auto` length is often used in layout calculations where the length should be determined
2868/// by the layout context itself rather than being explicitly set. This is commonly used in CSS
2869/// for properties like `width`, `height`, `margin`, `padding`, etc., where `auto` can be used
2870/// to instruct the layout engine to calculate the size based on other factors like the size of the
2871/// container or the intrinsic size of the content.
2872///
2873/// # Returns
2874///
2875/// A `Length` variant set to `Auto`.
2876pub fn auto() -> Length {
2877 Length::Auto
2878}
2879
2880impl From<Pixels> for Length {
2881 fn from(pixels: Pixels) -> Self {
2882 Self::Definite(pixels.into())
2883 }
2884}
2885
2886impl From<Rems> for Length {
2887 fn from(rems: Rems) -> Self {
2888 Self::Definite(rems.into())
2889 }
2890}
2891
2892impl From<DefiniteLength> for Length {
2893 fn from(length: DefiniteLength) -> Self {
2894 Self::Definite(length)
2895 }
2896}
2897
2898impl From<AbsoluteLength> for Length {
2899 fn from(length: AbsoluteLength) -> Self {
2900 Self::Definite(length.into())
2901 }
2902}
2903
2904impl Default for Length {
2905 fn default() -> Self {
2906 Self::Definite(DefiniteLength::default())
2907 }
2908}
2909
2910impl From<()> for Length {
2911 fn from(_: ()) -> Self {
2912 Self::Definite(DefiniteLength::default())
2913 }
2914}
2915
2916/// Provides a trait for types that can calculate half of their value.
2917///
2918/// The `Half` trait is used for types that can be evenly divided, returning a new instance of the same type
2919/// representing half of the original value. This is commonly used for types that represent measurements or sizes,
2920/// such as lengths or pixels, where halving is a frequent operation during layout calculations or animations.
2921pub trait Half {
2922 /// Returns half of the current value.
2923 ///
2924 /// # Returns
2925 ///
2926 /// A new instance of the implementing type, representing half of the original value.
2927 fn half(&self) -> Self;
2928}
2929
2930impl Half for i32 {
2931 fn half(&self) -> Self {
2932 self / 2
2933 }
2934}
2935
2936impl Half for f32 {
2937 fn half(&self) -> Self {
2938 self / 2.
2939 }
2940}
2941
2942impl Half for DevicePixels {
2943 fn half(&self) -> Self {
2944 Self(self.0 / 2)
2945 }
2946}
2947
2948impl Half for ScaledPixels {
2949 fn half(&self) -> Self {
2950 Self(self.0 / 2.)
2951 }
2952}
2953
2954impl Half for Pixels {
2955 fn half(&self) -> Self {
2956 Self(self.0 / 2.)
2957 }
2958}
2959
2960impl Half for Rems {
2961 fn half(&self) -> Self {
2962 Self(self.0 / 2.)
2963 }
2964}
2965
2966/// Provides a trait for types that can negate their values.
2967pub trait Negate {
2968 /// Returns the negation of the given value
2969 fn negate(self) -> Self;
2970}
2971
2972impl Negate for i32 {
2973 fn negate(self) -> Self {
2974 -self
2975 }
2976}
2977
2978impl Negate for f32 {
2979 fn negate(self) -> Self {
2980 -self
2981 }
2982}
2983
2984impl Negate for DevicePixels {
2985 fn negate(self) -> Self {
2986 Self(-self.0)
2987 }
2988}
2989
2990impl Negate for ScaledPixels {
2991 fn negate(self) -> Self {
2992 Self(-self.0)
2993 }
2994}
2995
2996impl Negate for Pixels {
2997 fn negate(self) -> Self {
2998 Self(-self.0)
2999 }
3000}
3001
3002impl Negate for Rems {
3003 fn negate(self) -> Self {
3004 Self(-self.0)
3005 }
3006}
3007
3008/// A trait for checking if a value is zero.
3009///
3010/// This trait provides a method to determine if a value is considered to be zero.
3011/// It is implemented for various numeric and length-related types where the concept
3012/// of zero is applicable. This can be useful for comparisons, optimizations, or
3013/// determining if an operation has a neutral effect.
3014pub trait IsZero {
3015 /// Determines if the value is zero.
3016 ///
3017 /// # Returns
3018 ///
3019 /// Returns `true` if the value is zero, `false` otherwise.
3020 fn is_zero(&self) -> bool;
3021}
3022
3023impl IsZero for DevicePixels {
3024 fn is_zero(&self) -> bool {
3025 self.0 == 0
3026 }
3027}
3028
3029impl IsZero for ScaledPixels {
3030 fn is_zero(&self) -> bool {
3031 self.0 == 0.
3032 }
3033}
3034
3035impl IsZero for Pixels {
3036 fn is_zero(&self) -> bool {
3037 self.0 == 0.
3038 }
3039}
3040
3041impl IsZero for Rems {
3042 fn is_zero(&self) -> bool {
3043 self.0 == 0.
3044 }
3045}
3046
3047impl IsZero for AbsoluteLength {
3048 fn is_zero(&self) -> bool {
3049 match self {
3050 AbsoluteLength::Pixels(pixels) => pixels.is_zero(),
3051 AbsoluteLength::Rems(rems) => rems.is_zero(),
3052 }
3053 }
3054}
3055
3056impl IsZero for DefiniteLength {
3057 fn is_zero(&self) -> bool {
3058 match self {
3059 DefiniteLength::Absolute(length) => length.is_zero(),
3060 DefiniteLength::Fraction(fraction) => *fraction == 0.,
3061 }
3062 }
3063}
3064
3065impl IsZero for Length {
3066 fn is_zero(&self) -> bool {
3067 match self {
3068 Length::Definite(length) => length.is_zero(),
3069 Length::Auto => false,
3070 }
3071 }
3072}
3073
3074impl<T: IsZero + Debug + Clone + Default> IsZero for Point<T> {
3075 fn is_zero(&self) -> bool {
3076 self.x.is_zero() && self.y.is_zero()
3077 }
3078}
3079
3080impl<T> IsZero for Size<T>
3081where
3082 T: IsZero + Default + Debug + Clone,
3083{
3084 fn is_zero(&self) -> bool {
3085 self.width.is_zero() || self.height.is_zero()
3086 }
3087}
3088
3089impl<T: IsZero + Debug + Clone + Default> IsZero for Bounds<T> {
3090 fn is_zero(&self) -> bool {
3091 self.size.is_zero()
3092 }
3093}
3094
3095impl<T> IsZero for Corners<T>
3096where
3097 T: IsZero + Clone + Default + Debug,
3098{
3099 fn is_zero(&self) -> bool {
3100 self.top_left.is_zero()
3101 && self.top_right.is_zero()
3102 && self.bottom_right.is_zero()
3103 && self.bottom_left.is_zero()
3104 }
3105}
3106
3107#[cfg(test)]
3108mod tests {
3109 use super::*;
3110
3111 #[test]
3112 fn test_bounds_intersects() {
3113 let bounds1 = Bounds {
3114 origin: Point { x: 0.0, y: 0.0 },
3115 size: Size {
3116 width: 5.0,
3117 height: 5.0,
3118 },
3119 };
3120 let bounds2 = Bounds {
3121 origin: Point { x: 4.0, y: 4.0 },
3122 size: Size {
3123 width: 5.0,
3124 height: 5.0,
3125 },
3126 };
3127 let bounds3 = Bounds {
3128 origin: Point { x: 10.0, y: 10.0 },
3129 size: Size {
3130 width: 5.0,
3131 height: 5.0,
3132 },
3133 };
3134
3135 // Test Case 1: Intersecting bounds
3136 assert_eq!(bounds1.intersects(&bounds2), true);
3137
3138 // Test Case 2: Non-Intersecting bounds
3139 assert_eq!(bounds1.intersects(&bounds3), false);
3140
3141 // Test Case 3: Bounds intersecting with themselves
3142 assert_eq!(bounds1.intersects(&bounds1), true);
3143 }
3144}