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