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