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