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, Copy, 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
1116 .bottom_right()
1117 .min(&other.bottom_right())
1118 .max(&upper_left);
1119 Self::from_corners(upper_left, bottom_right)
1120 }
1121
1122 /// Computes the union of two `Bounds`.
1123 ///
1124 /// This method calculates the smallest `Bounds` that contains both the current `Bounds` and the `other` `Bounds`.
1125 /// The resulting `Bounds` will have an origin that is the minimum of the origins of the two `Bounds`,
1126 /// and a size that encompasses the furthest extents of both `Bounds`.
1127 ///
1128 /// # Arguments
1129 ///
1130 /// * `other` - A reference to another `Bounds` to create a union with.
1131 ///
1132 /// # Returns
1133 ///
1134 /// Returns a `Bounds` representing the union of the two `Bounds`.
1135 ///
1136 /// # Examples
1137 ///
1138 /// ```
1139 /// # use gpui::{Bounds, Point, Size};
1140 /// let bounds1 = Bounds {
1141 /// origin: Point { x: 0, y: 0 },
1142 /// size: Size { width: 10, height: 10 },
1143 /// };
1144 /// let bounds2 = Bounds {
1145 /// origin: Point { x: 5, y: 5 },
1146 /// size: Size { width: 15, height: 15 },
1147 /// };
1148 /// let union_bounds = bounds1.union(&bounds2);
1149 ///
1150 /// assert_eq!(union_bounds, Bounds {
1151 /// origin: Point { x: 0, y: 0 },
1152 /// size: Size { width: 20, height: 20 },
1153 /// });
1154 /// ```
1155 pub fn union(&self, other: &Self) -> Self {
1156 let top_left = self.origin.min(&other.origin);
1157 let bottom_right = self.bottom_right().max(&other.bottom_right());
1158 Bounds::from_corners(top_left, bottom_right)
1159 }
1160}
1161
1162impl<T> Bounds<T>
1163where
1164 T: Add<T, Output = T> + Sub<T, Output = T> + Clone + Debug + Default + PartialEq,
1165{
1166 /// Computes the space available within outer bounds.
1167 pub fn space_within(&self, outer: &Self) -> Edges<T> {
1168 Edges {
1169 top: self.top() - outer.top(),
1170 right: outer.right() - self.right(),
1171 bottom: outer.bottom() - self.bottom(),
1172 left: self.left() - outer.left(),
1173 }
1174 }
1175}
1176
1177impl<T, Rhs> Mul<Rhs> for Bounds<T>
1178where
1179 T: Mul<Rhs, Output = Rhs> + Clone + Debug + Default + PartialEq,
1180 Point<T>: Mul<Rhs, Output = Point<Rhs>>,
1181 Rhs: Clone + Debug + Default + PartialEq,
1182{
1183 type Output = Bounds<Rhs>;
1184
1185 fn mul(self, rhs: Rhs) -> Self::Output {
1186 Bounds {
1187 origin: self.origin * rhs.clone(),
1188 size: self.size * rhs,
1189 }
1190 }
1191}
1192
1193impl<T, S> MulAssign<S> for Bounds<T>
1194where
1195 T: Mul<S, Output = T> + Clone + Debug + Default + PartialEq,
1196 S: Clone,
1197{
1198 fn mul_assign(&mut self, rhs: S) {
1199 self.origin *= rhs.clone();
1200 self.size *= rhs;
1201 }
1202}
1203
1204impl<T, S> Div<S> for Bounds<T>
1205where
1206 Size<T>: Div<S, Output = Size<T>>,
1207 T: Div<S, Output = T> + Clone + Debug + Default + PartialEq,
1208 S: Clone,
1209{
1210 type Output = Self;
1211
1212 fn div(self, rhs: S) -> Self {
1213 Self {
1214 origin: self.origin / rhs.clone(),
1215 size: self.size / rhs,
1216 }
1217 }
1218}
1219
1220impl<T> Add<Point<T>> for Bounds<T>
1221where
1222 T: Add<T, Output = T> + Clone + Debug + Default + PartialEq,
1223{
1224 type Output = Self;
1225
1226 fn add(self, rhs: Point<T>) -> Self {
1227 Self {
1228 origin: self.origin + rhs,
1229 size: self.size,
1230 }
1231 }
1232}
1233
1234impl<T> Sub<Point<T>> for Bounds<T>
1235where
1236 T: Sub<T, Output = T> + Clone + Debug + Default + PartialEq,
1237{
1238 type Output = Self;
1239
1240 fn sub(self, rhs: Point<T>) -> Self {
1241 Self {
1242 origin: self.origin - rhs,
1243 size: self.size,
1244 }
1245 }
1246}
1247
1248impl<T> Bounds<T>
1249where
1250 T: Add<T, Output = T> + Clone + Debug + Default + PartialEq,
1251{
1252 /// Returns the top edge of the bounds.
1253 ///
1254 /// # Returns
1255 ///
1256 /// A value of type `T` representing the y-coordinate of the top edge of the bounds.
1257 pub fn top(&self) -> T {
1258 self.origin.y.clone()
1259 }
1260
1261 /// Returns the bottom edge of the bounds.
1262 ///
1263 /// # Returns
1264 ///
1265 /// A value of type `T` representing the y-coordinate of the bottom edge of the bounds.
1266 pub fn bottom(&self) -> T {
1267 self.origin.y.clone() + self.size.height.clone()
1268 }
1269
1270 /// Returns the left edge of the bounds.
1271 ///
1272 /// # Returns
1273 ///
1274 /// A value of type `T` representing the x-coordinate of the left edge of the bounds.
1275 pub fn left(&self) -> T {
1276 self.origin.x.clone()
1277 }
1278
1279 /// Returns the right edge of the bounds.
1280 ///
1281 /// # Returns
1282 ///
1283 /// A value of type `T` representing the x-coordinate of the right edge of the bounds.
1284 pub fn right(&self) -> T {
1285 self.origin.x.clone() + self.size.width.clone()
1286 }
1287
1288 /// Returns the top right corner point of the bounds.
1289 ///
1290 /// # Returns
1291 ///
1292 /// A `Point<T>` representing the top right corner of the bounds.
1293 ///
1294 /// # Examples
1295 ///
1296 /// ```
1297 /// # use gpui::{Bounds, Point, Size};
1298 /// let bounds = Bounds {
1299 /// origin: Point { x: 0, y: 0 },
1300 /// size: Size { width: 10, height: 20 },
1301 /// };
1302 /// let top_right = bounds.top_right();
1303 /// assert_eq!(top_right, Point { x: 10, y: 0 });
1304 /// ```
1305 pub fn top_right(&self) -> Point<T> {
1306 Point {
1307 x: self.origin.x.clone() + self.size.width.clone(),
1308 y: self.origin.y.clone(),
1309 }
1310 }
1311
1312 /// Returns the bottom right corner point of the bounds.
1313 ///
1314 /// # Returns
1315 ///
1316 /// A `Point<T>` representing the bottom right corner of the bounds.
1317 ///
1318 /// # Examples
1319 ///
1320 /// ```
1321 /// # use gpui::{Bounds, Point, Size};
1322 /// let bounds = Bounds {
1323 /// origin: Point { x: 0, y: 0 },
1324 /// size: Size { width: 10, height: 20 },
1325 /// };
1326 /// let bottom_right = bounds.bottom_right();
1327 /// assert_eq!(bottom_right, Point { x: 10, y: 20 });
1328 /// ```
1329 pub fn bottom_right(&self) -> Point<T> {
1330 Point {
1331 x: self.origin.x.clone() + self.size.width.clone(),
1332 y: self.origin.y.clone() + self.size.height.clone(),
1333 }
1334 }
1335
1336 /// Returns the bottom left corner point of the bounds.
1337 ///
1338 /// # Returns
1339 ///
1340 /// A `Point<T>` representing the bottom left corner of the bounds.
1341 ///
1342 /// # Examples
1343 ///
1344 /// ```
1345 /// # use gpui::{Bounds, Point, Size};
1346 /// let bounds = Bounds {
1347 /// origin: Point { x: 0, y: 0 },
1348 /// size: Size { width: 10, height: 20 },
1349 /// };
1350 /// let bottom_left = bounds.bottom_left();
1351 /// assert_eq!(bottom_left, Point { x: 0, y: 20 });
1352 /// ```
1353 pub fn bottom_left(&self) -> Point<T> {
1354 Point {
1355 x: self.origin.x.clone(),
1356 y: self.origin.y.clone() + self.size.height.clone(),
1357 }
1358 }
1359
1360 /// Returns the requested corner point of the bounds.
1361 ///
1362 /// # Returns
1363 ///
1364 /// A `Point<T>` representing the corner of the bounds requested by the parameter.
1365 ///
1366 /// # Examples
1367 ///
1368 /// ```
1369 /// use gpui::{Bounds, Corner, Point, Size};
1370 /// let bounds = Bounds {
1371 /// origin: Point { x: 0, y: 0 },
1372 /// size: Size { width: 10, height: 20 },
1373 /// };
1374 /// let bottom_left = bounds.corner(Corner::BottomLeft);
1375 /// assert_eq!(bottom_left, Point { x: 0, y: 20 });
1376 /// ```
1377 pub fn corner(&self, corner: Corner) -> Point<T> {
1378 match corner {
1379 Corner::TopLeft => self.origin.clone(),
1380 Corner::TopRight => self.top_right(),
1381 Corner::BottomLeft => self.bottom_left(),
1382 Corner::BottomRight => self.bottom_right(),
1383 }
1384 }
1385}
1386
1387impl<T> Bounds<T>
1388where
1389 T: Add<T, Output = T> + PartialOrd + Clone + Debug + Default + PartialEq,
1390{
1391 /// Checks if the given point is within the bounds.
1392 ///
1393 /// This method determines whether a point lies inside the rectangle defined by the bounds,
1394 /// including the edges. The point is considered inside if its x-coordinate is greater than
1395 /// or equal to the left edge and less than or equal to the right edge, and its y-coordinate
1396 /// is greater than or equal to the top edge and less than or equal to the bottom edge of the bounds.
1397 ///
1398 /// # Arguments
1399 ///
1400 /// * `point` - A reference to a `Point<T>` that represents the point to check.
1401 ///
1402 /// # Returns
1403 ///
1404 /// Returns `true` if the point is within the bounds, `false` otherwise.
1405 ///
1406 /// # Examples
1407 ///
1408 /// ```
1409 /// # use gpui::{Point, Bounds, Size};
1410 /// let bounds = Bounds {
1411 /// origin: Point { x: 0, y: 0 },
1412 /// size: Size { width: 10, height: 10 },
1413 /// };
1414 /// let inside_point = Point { x: 5, y: 5 };
1415 /// let outside_point = Point { x: 15, y: 15 };
1416 ///
1417 /// assert!(bounds.contains(&inside_point));
1418 /// assert!(!bounds.contains(&outside_point));
1419 /// ```
1420 pub fn contains(&self, point: &Point<T>) -> bool {
1421 point.x >= self.origin.x
1422 && point.x < self.origin.x.clone() + self.size.width.clone()
1423 && point.y >= self.origin.y
1424 && point.y < self.origin.y.clone() + self.size.height.clone()
1425 }
1426
1427 /// Checks if this bounds is completely contained within another bounds.
1428 ///
1429 /// This method determines whether the current bounds is entirely enclosed by the given bounds.
1430 /// A bounds is considered to be contained within another if its origin (top-left corner) and
1431 /// its bottom-right corner are both contained within the other bounds.
1432 ///
1433 /// # Arguments
1434 ///
1435 /// * `other` - A reference to another `Bounds` that might contain this bounds.
1436 ///
1437 /// # Returns
1438 ///
1439 /// Returns `true` if this bounds is completely inside the other bounds, `false` otherwise.
1440 ///
1441 /// # Examples
1442 ///
1443 /// ```
1444 /// # use gpui::{Bounds, Point, Size};
1445 /// let outer_bounds = Bounds {
1446 /// origin: Point { x: 0, y: 0 },
1447 /// size: Size { width: 20, height: 20 },
1448 /// };
1449 /// let inner_bounds = Bounds {
1450 /// origin: Point { x: 5, y: 5 },
1451 /// size: Size { width: 10, height: 10 },
1452 /// };
1453 /// let overlapping_bounds = Bounds {
1454 /// origin: Point { x: 15, y: 15 },
1455 /// size: Size { width: 10, height: 10 },
1456 /// };
1457 ///
1458 /// assert!(inner_bounds.is_contained_within(&outer_bounds));
1459 /// assert!(!overlapping_bounds.is_contained_within(&outer_bounds));
1460 /// ```
1461 pub fn is_contained_within(&self, other: &Self) -> bool {
1462 other.contains(&self.origin) && other.contains(&self.bottom_right())
1463 }
1464
1465 /// Applies a function to the origin and size of the bounds, producing a new `Bounds<U>`.
1466 ///
1467 /// This method allows for converting a `Bounds<T>` to a `Bounds<U>` by specifying a closure
1468 /// that defines how to convert between the two types. The closure is applied to the `origin` and
1469 /// `size` fields, resulting in new bounds of the desired type.
1470 ///
1471 /// # Arguments
1472 ///
1473 /// * `f` - A closure that takes a value of type `T` and returns a value of type `U`.
1474 ///
1475 /// # Returns
1476 ///
1477 /// Returns a new `Bounds<U>` with the origin and size mapped by the provided function.
1478 ///
1479 /// # Examples
1480 ///
1481 /// ```
1482 /// # use gpui::{Bounds, Point, Size};
1483 /// let bounds = Bounds {
1484 /// origin: Point { x: 10.0, y: 10.0 },
1485 /// size: Size { width: 10.0, height: 20.0 },
1486 /// };
1487 /// let new_bounds = bounds.map(|value| value as f64 * 1.5);
1488 ///
1489 /// assert_eq!(new_bounds, Bounds {
1490 /// origin: Point { x: 15.0, y: 15.0 },
1491 /// size: Size { width: 15.0, height: 30.0 },
1492 /// });
1493 /// ```
1494 pub fn map<U>(&self, f: impl Fn(T) -> U) -> Bounds<U>
1495 where
1496 U: Clone + Debug + Default + PartialEq,
1497 {
1498 Bounds {
1499 origin: self.origin.map(&f),
1500 size: self.size.map(f),
1501 }
1502 }
1503
1504 /// Applies a function to the origin of the bounds, producing a new `Bounds` with the new origin
1505 ///
1506 /// # Examples
1507 ///
1508 /// ```
1509 /// # use gpui::{Bounds, Point, Size};
1510 /// let bounds = Bounds {
1511 /// origin: Point { x: 10.0, y: 10.0 },
1512 /// size: Size { width: 10.0, height: 20.0 },
1513 /// };
1514 /// let new_bounds = bounds.map_origin(|value| value * 1.5);
1515 ///
1516 /// assert_eq!(new_bounds, Bounds {
1517 /// origin: Point { x: 15.0, y: 15.0 },
1518 /// size: Size { width: 10.0, height: 20.0 },
1519 /// });
1520 /// ```
1521 pub fn map_origin(self, f: impl Fn(T) -> T) -> Bounds<T> {
1522 Bounds {
1523 origin: self.origin.map(f),
1524 size: self.size,
1525 }
1526 }
1527
1528 /// Applies a function to the origin of the bounds, producing a new `Bounds` with the new origin
1529 ///
1530 /// # Examples
1531 ///
1532 /// ```
1533 /// # use gpui::{Bounds, Point, Size};
1534 /// let bounds = Bounds {
1535 /// origin: Point { x: 10.0, y: 10.0 },
1536 /// size: Size { width: 10.0, height: 20.0 },
1537 /// };
1538 /// let new_bounds = bounds.map_size(|value| value * 1.5);
1539 ///
1540 /// assert_eq!(new_bounds, Bounds {
1541 /// origin: Point { x: 10.0, y: 10.0 },
1542 /// size: Size { width: 15.0, height: 30.0 },
1543 /// });
1544 /// ```
1545 pub fn map_size(self, f: impl Fn(T) -> T) -> Bounds<T> {
1546 Bounds {
1547 origin: self.origin,
1548 size: self.size.map(f),
1549 }
1550 }
1551}
1552
1553impl<T> Bounds<T>
1554where
1555 T: Add<T, Output = T> + Sub<T, Output = T> + PartialOrd + Clone + Debug + Default + PartialEq,
1556{
1557 /// Convert a point to the coordinate space defined by this Bounds
1558 pub fn localize(&self, point: &Point<T>) -> Option<Point<T>> {
1559 self.contains(point)
1560 .then(|| point.relative_to(&self.origin))
1561 }
1562}
1563
1564/// Checks if the bounds represent an empty area.
1565///
1566/// # Returns
1567///
1568/// Returns `true` if either the width or the height of the bounds is less than or equal to zero, indicating an empty area.
1569impl<T: PartialOrd + Clone + Debug + Default + PartialEq> Bounds<T> {
1570 /// Checks if the bounds represent an empty area.
1571 ///
1572 /// # Returns
1573 ///
1574 /// Returns `true` if either the width or the height of the bounds is less than or equal to zero, indicating an empty area.
1575 #[must_use]
1576 pub fn is_empty(&self) -> bool {
1577 self.size.width <= T::default() || self.size.height <= T::default()
1578 }
1579}
1580
1581impl<T: Clone + Debug + Default + PartialEq + Display + Add<T, Output = T>> Display for Bounds<T> {
1582 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1583 write!(
1584 f,
1585 "{} - {} (size {})",
1586 self.origin,
1587 self.bottom_right(),
1588 self.size
1589 )
1590 }
1591}
1592
1593impl Size<DevicePixels> {
1594 /// Converts the size from physical to logical pixels.
1595 pub(crate) fn to_pixels(self, scale_factor: f32) -> Size<Pixels> {
1596 size(
1597 px(self.width.0 as f32 / scale_factor),
1598 px(self.height.0 as f32 / scale_factor),
1599 )
1600 }
1601}
1602
1603impl Size<Pixels> {
1604 /// Converts the size from logical to physical pixels.
1605 pub(crate) fn to_device_pixels(self, scale_factor: f32) -> Size<DevicePixels> {
1606 size(
1607 DevicePixels((self.width.0 * scale_factor).round() as i32),
1608 DevicePixels((self.height.0 * scale_factor).round() as i32),
1609 )
1610 }
1611}
1612
1613impl Bounds<Pixels> {
1614 /// Scales the bounds by a given factor, typically used to adjust for display scaling.
1615 ///
1616 /// This method multiplies the origin and size of the bounds by the provided scaling factor,
1617 /// resulting in a new `Bounds<ScaledPixels>` that is proportionally larger or smaller
1618 /// depending on the scaling factor. This can be used to ensure that the bounds are properly
1619 /// scaled for different display densities.
1620 ///
1621 /// # Arguments
1622 ///
1623 /// * `factor` - The scaling factor to apply to the origin and size, typically the display's scaling factor.
1624 ///
1625 /// # Returns
1626 ///
1627 /// Returns a new `Bounds<ScaledPixels>` that represents the scaled bounds.
1628 ///
1629 /// # Examples
1630 ///
1631 /// ```
1632 /// # use gpui::{Bounds, Point, Size, Pixels, ScaledPixels, DevicePixels};
1633 /// let bounds = Bounds {
1634 /// origin: Point { x: Pixels::from(10.0), y: Pixels::from(20.0) },
1635 /// size: Size { width: Pixels::from(30.0), height: Pixels::from(40.0) },
1636 /// };
1637 /// let display_scale_factor = 2.0;
1638 /// let scaled_bounds = bounds.scale(display_scale_factor);
1639 /// assert_eq!(scaled_bounds, Bounds {
1640 /// origin: Point {
1641 /// x: ScaledPixels::from(20.0),
1642 /// y: ScaledPixels::from(40.0),
1643 /// },
1644 /// size: Size {
1645 /// width: ScaledPixels::from(60.0),
1646 /// height: ScaledPixels::from(80.0)
1647 /// },
1648 /// });
1649 /// ```
1650 pub fn scale(&self, factor: f32) -> Bounds<ScaledPixels> {
1651 Bounds {
1652 origin: self.origin.scale(factor),
1653 size: self.size.scale(factor),
1654 }
1655 }
1656
1657 /// Convert the bounds from logical pixels to physical pixels
1658 pub fn to_device_pixels(self, factor: f32) -> Bounds<DevicePixels> {
1659 Bounds {
1660 origin: point(
1661 DevicePixels((self.origin.x.0 * factor).round() as i32),
1662 DevicePixels((self.origin.y.0 * factor).round() as i32),
1663 ),
1664 size: self.size.to_device_pixels(factor),
1665 }
1666 }
1667}
1668
1669impl Bounds<DevicePixels> {
1670 /// Convert the bounds from physical pixels to logical pixels
1671 pub fn to_pixels(self, scale_factor: f32) -> Bounds<Pixels> {
1672 Bounds {
1673 origin: point(
1674 px(self.origin.x.0 as f32 / scale_factor),
1675 px(self.origin.y.0 as f32 / scale_factor),
1676 ),
1677 size: self.size.to_pixels(scale_factor),
1678 }
1679 }
1680}
1681
1682/// Represents the edges of a box in a 2D space, such as padding or margin.
1683///
1684/// Each field represents the size of the edge on one side of the box: `top`, `right`, `bottom`, and `left`.
1685///
1686/// # Examples
1687///
1688/// ```
1689/// # use gpui::Edges;
1690/// let edges = Edges {
1691/// top: 10.0,
1692/// right: 20.0,
1693/// bottom: 30.0,
1694/// left: 40.0,
1695/// };
1696///
1697/// assert_eq!(edges.top, 10.0);
1698/// assert_eq!(edges.right, 20.0);
1699/// assert_eq!(edges.bottom, 30.0);
1700/// assert_eq!(edges.left, 40.0);
1701/// ```
1702#[derive(Refineable, Clone, Default, Debug, Eq, PartialEq)]
1703#[refineable(Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
1704#[repr(C)]
1705pub struct Edges<T: Clone + Debug + Default + PartialEq> {
1706 /// The size of the top edge.
1707 pub top: T,
1708 /// The size of the right edge.
1709 pub right: T,
1710 /// The size of the bottom edge.
1711 pub bottom: T,
1712 /// The size of the left edge.
1713 pub left: T,
1714}
1715
1716impl<T> Mul for Edges<T>
1717where
1718 T: Mul<Output = T> + Clone + Debug + Default + PartialEq,
1719{
1720 type Output = Self;
1721
1722 fn mul(self, rhs: Self) -> Self::Output {
1723 Self {
1724 top: self.top.clone() * rhs.top,
1725 right: self.right.clone() * rhs.right,
1726 bottom: self.bottom.clone() * rhs.bottom,
1727 left: self.left * rhs.left,
1728 }
1729 }
1730}
1731
1732impl<T, S> MulAssign<S> for Edges<T>
1733where
1734 T: Mul<S, Output = T> + Clone + Debug + Default + PartialEq,
1735 S: Clone,
1736{
1737 fn mul_assign(&mut self, rhs: S) {
1738 self.top = self.top.clone() * rhs.clone();
1739 self.right = self.right.clone() * rhs.clone();
1740 self.bottom = self.bottom.clone() * rhs.clone();
1741 self.left = self.left.clone() * rhs;
1742 }
1743}
1744
1745impl<T: Clone + Debug + Default + PartialEq + Copy> Copy for Edges<T> {}
1746
1747impl<T: Clone + Debug + Default + PartialEq> Edges<T> {
1748 /// Constructs `Edges` where all sides are set to the same specified value.
1749 ///
1750 /// This function creates an `Edges` instance with the `top`, `right`, `bottom`, and `left` fields all initialized
1751 /// to the same value provided as an argument. This is useful when you want to have uniform edges around a box,
1752 /// such as padding or margin with the same size on all sides.
1753 ///
1754 /// # Arguments
1755 ///
1756 /// * `value` - The value to set for all four sides of the edges.
1757 ///
1758 /// # Returns
1759 ///
1760 /// An `Edges` instance with all sides set to the given value.
1761 ///
1762 /// # Examples
1763 ///
1764 /// ```
1765 /// # use gpui::Edges;
1766 /// let uniform_edges = Edges::all(10.0);
1767 /// assert_eq!(uniform_edges.top, 10.0);
1768 /// assert_eq!(uniform_edges.right, 10.0);
1769 /// assert_eq!(uniform_edges.bottom, 10.0);
1770 /// assert_eq!(uniform_edges.left, 10.0);
1771 /// ```
1772 pub fn all(value: T) -> Self {
1773 Self {
1774 top: value.clone(),
1775 right: value.clone(),
1776 bottom: value.clone(),
1777 left: value,
1778 }
1779 }
1780
1781 /// Applies a function to each field of the `Edges`, producing a new `Edges<U>`.
1782 ///
1783 /// This method allows for converting an `Edges<T>` to an `Edges<U>` by specifying a closure
1784 /// that defines how to convert between the two types. The closure is applied to each field
1785 /// (`top`, `right`, `bottom`, `left`), resulting in new edges of the desired type.
1786 ///
1787 /// # Arguments
1788 ///
1789 /// * `f` - A closure that takes a reference to a value of type `T` and returns a value of type `U`.
1790 ///
1791 /// # Returns
1792 ///
1793 /// Returns a new `Edges<U>` with each field mapped by the provided function.
1794 ///
1795 /// # Examples
1796 ///
1797 /// ```
1798 /// # use gpui::Edges;
1799 /// let edges = Edges { top: 10, right: 20, bottom: 30, left: 40 };
1800 /// let edges_float = edges.map(|&value| value as f32 * 1.1);
1801 /// assert_eq!(edges_float, Edges { top: 11.0, right: 22.0, bottom: 33.0, left: 44.0 });
1802 /// ```
1803 pub fn map<U>(&self, f: impl Fn(&T) -> U) -> Edges<U>
1804 where
1805 U: Clone + Debug + Default + PartialEq,
1806 {
1807 Edges {
1808 top: f(&self.top),
1809 right: f(&self.right),
1810 bottom: f(&self.bottom),
1811 left: f(&self.left),
1812 }
1813 }
1814
1815 /// Checks if any of the edges satisfy a given predicate.
1816 ///
1817 /// This method applies a predicate function to each field of the `Edges` and returns `true` if any field satisfies the predicate.
1818 ///
1819 /// # Arguments
1820 ///
1821 /// * `predicate` - A closure that takes a reference to a value of type `T` and returns a `bool`.
1822 ///
1823 /// # Returns
1824 ///
1825 /// Returns `true` if the predicate returns `true` for any of the edge values, `false` otherwise.
1826 ///
1827 /// # Examples
1828 ///
1829 /// ```
1830 /// # use gpui::Edges;
1831 /// let edges = Edges {
1832 /// top: 10,
1833 /// right: 0,
1834 /// bottom: 5,
1835 /// left: 0,
1836 /// };
1837 ///
1838 /// assert!(edges.any(|value| *value == 0));
1839 /// assert!(edges.any(|value| *value > 0));
1840 /// assert!(!edges.any(|value| *value > 10));
1841 /// ```
1842 pub fn any<F: Fn(&T) -> bool>(&self, predicate: F) -> bool {
1843 predicate(&self.top)
1844 || predicate(&self.right)
1845 || predicate(&self.bottom)
1846 || predicate(&self.left)
1847 }
1848}
1849
1850impl Edges<Length> {
1851 /// 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.
1852 ///
1853 /// 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.
1854 ///
1855 /// # Returns
1856 ///
1857 /// Returns an `Edges<Length>` with all edges set to `Length::Auto`.
1858 ///
1859 /// # Examples
1860 ///
1861 /// ```
1862 /// # use gpui::{Edges, Length};
1863 /// let auto_edges = Edges::auto();
1864 /// assert_eq!(auto_edges.top, Length::Auto);
1865 /// assert_eq!(auto_edges.right, Length::Auto);
1866 /// assert_eq!(auto_edges.bottom, Length::Auto);
1867 /// assert_eq!(auto_edges.left, Length::Auto);
1868 /// ```
1869 pub fn auto() -> Self {
1870 Self {
1871 top: Length::Auto,
1872 right: Length::Auto,
1873 bottom: Length::Auto,
1874 left: Length::Auto,
1875 }
1876 }
1877
1878 /// Sets the edges of the `Edges` struct to zero, which means no size or thickness.
1879 ///
1880 /// This is typically used when you want to specify that a box (like a padding or margin area)
1881 /// should have no edges, effectively making it non-existent or invisible in layout calculations.
1882 ///
1883 /// # Returns
1884 ///
1885 /// Returns an `Edges<Length>` with all edges set to zero length.
1886 ///
1887 /// # Examples
1888 ///
1889 /// ```
1890 /// # use gpui::{DefiniteLength, Edges, Length, Pixels};
1891 /// let no_edges = Edges::<Length>::zero();
1892 /// assert_eq!(no_edges.top, Length::Definite(DefiniteLength::from(Pixels::ZERO)));
1893 /// assert_eq!(no_edges.right, Length::Definite(DefiniteLength::from(Pixels::ZERO)));
1894 /// assert_eq!(no_edges.bottom, Length::Definite(DefiniteLength::from(Pixels::ZERO)));
1895 /// assert_eq!(no_edges.left, Length::Definite(DefiniteLength::from(Pixels::ZERO)));
1896 /// ```
1897 pub fn zero() -> Self {
1898 Self {
1899 top: px(0.).into(),
1900 right: px(0.).into(),
1901 bottom: px(0.).into(),
1902 left: px(0.).into(),
1903 }
1904 }
1905}
1906
1907impl Edges<DefiniteLength> {
1908 /// Sets the edges of the `Edges` struct to zero, which means no size or thickness.
1909 ///
1910 /// This is typically used when you want to specify that a box (like a padding or margin area)
1911 /// should have no edges, effectively making it non-existent or invisible in layout calculations.
1912 ///
1913 /// # Returns
1914 ///
1915 /// Returns an `Edges<DefiniteLength>` with all edges set to zero length.
1916 ///
1917 /// # Examples
1918 ///
1919 /// ```
1920 /// # use gpui::{px, DefiniteLength, Edges};
1921 /// let no_edges = Edges::<DefiniteLength>::zero();
1922 /// assert_eq!(no_edges.top, DefiniteLength::from(px(0.)));
1923 /// assert_eq!(no_edges.right, DefiniteLength::from(px(0.)));
1924 /// assert_eq!(no_edges.bottom, DefiniteLength::from(px(0.)));
1925 /// assert_eq!(no_edges.left, DefiniteLength::from(px(0.)));
1926 /// ```
1927 pub fn zero() -> Self {
1928 Self {
1929 top: px(0.).into(),
1930 right: px(0.).into(),
1931 bottom: px(0.).into(),
1932 left: px(0.).into(),
1933 }
1934 }
1935
1936 /// Converts the `DefiniteLength` to `Pixels` based on the parent size and the REM size.
1937 ///
1938 /// This method allows for a `DefiniteLength` value to be converted into pixels, taking into account
1939 /// the size of the parent element (for percentage-based lengths) and the size of a rem unit (for rem-based lengths).
1940 ///
1941 /// # Arguments
1942 ///
1943 /// * `parent_size` - `Size<AbsoluteLength>` representing the size of the parent element.
1944 /// * `rem_size` - `Pixels` representing the size of one REM unit.
1945 ///
1946 /// # Returns
1947 ///
1948 /// Returns an `Edges<Pixels>` representing the edges with lengths converted to pixels.
1949 ///
1950 /// # Examples
1951 ///
1952 /// ```
1953 /// # use gpui::{Edges, DefiniteLength, px, AbsoluteLength, rems, Size};
1954 /// let edges = Edges {
1955 /// top: DefiniteLength::Absolute(AbsoluteLength::Pixels(px(10.0))),
1956 /// right: DefiniteLength::Fraction(0.5),
1957 /// bottom: DefiniteLength::Absolute(AbsoluteLength::Rems(rems(2.0))),
1958 /// left: DefiniteLength::Fraction(0.25),
1959 /// };
1960 /// let parent_size = Size {
1961 /// width: AbsoluteLength::Pixels(px(200.0)),
1962 /// height: AbsoluteLength::Pixels(px(100.0)),
1963 /// };
1964 /// let rem_size = px(16.0);
1965 /// let edges_in_pixels = edges.to_pixels(parent_size, rem_size);
1966 ///
1967 /// assert_eq!(edges_in_pixels.top, px(10.0)); // Absolute length in pixels
1968 /// assert_eq!(edges_in_pixels.right, px(100.0)); // 50% of parent width
1969 /// assert_eq!(edges_in_pixels.bottom, px(32.0)); // 2 rems
1970 /// assert_eq!(edges_in_pixels.left, px(50.0)); // 25% of parent width
1971 /// ```
1972 pub fn to_pixels(self, parent_size: Size<AbsoluteLength>, rem_size: Pixels) -> Edges<Pixels> {
1973 Edges {
1974 top: self.top.to_pixels(parent_size.height, rem_size),
1975 right: self.right.to_pixels(parent_size.width, rem_size),
1976 bottom: self.bottom.to_pixels(parent_size.height, rem_size),
1977 left: self.left.to_pixels(parent_size.width, rem_size),
1978 }
1979 }
1980}
1981
1982impl Edges<AbsoluteLength> {
1983 /// Sets the edges of the `Edges` struct to zero, which means no size or thickness.
1984 ///
1985 /// This is typically used when you want to specify that a box (like a padding or margin area)
1986 /// should have no edges, effectively making it non-existent or invisible in layout calculations.
1987 ///
1988 /// # Returns
1989 ///
1990 /// Returns an `Edges<AbsoluteLength>` with all edges set to zero length.
1991 ///
1992 /// # Examples
1993 ///
1994 /// ```
1995 /// # use gpui::{AbsoluteLength, Edges, Pixels};
1996 /// let no_edges = Edges::<AbsoluteLength>::zero();
1997 /// assert_eq!(no_edges.top, AbsoluteLength::Pixels(Pixels::ZERO));
1998 /// assert_eq!(no_edges.right, AbsoluteLength::Pixels(Pixels::ZERO));
1999 /// assert_eq!(no_edges.bottom, AbsoluteLength::Pixels(Pixels::ZERO));
2000 /// assert_eq!(no_edges.left, AbsoluteLength::Pixels(Pixels::ZERO));
2001 /// ```
2002 pub fn zero() -> Self {
2003 Self {
2004 top: px(0.).into(),
2005 right: px(0.).into(),
2006 bottom: px(0.).into(),
2007 left: px(0.).into(),
2008 }
2009 }
2010
2011 /// Converts the `AbsoluteLength` to `Pixels` based on the `rem_size`.
2012 ///
2013 /// If the `AbsoluteLength` is already in pixels, it simply returns the corresponding `Pixels` value.
2014 /// If the `AbsoluteLength` is in rems, it multiplies the number of rems by the `rem_size` to convert it to pixels.
2015 ///
2016 /// # Arguments
2017 ///
2018 /// * `rem_size` - The size of one rem unit in pixels.
2019 ///
2020 /// # Returns
2021 ///
2022 /// Returns an `Edges<Pixels>` representing the edges with lengths converted to pixels.
2023 ///
2024 /// # Examples
2025 ///
2026 /// ```
2027 /// # use gpui::{Edges, AbsoluteLength, Pixels, px, rems};
2028 /// let edges = Edges {
2029 /// top: AbsoluteLength::Pixels(px(10.0)),
2030 /// right: AbsoluteLength::Rems(rems(1.0)),
2031 /// bottom: AbsoluteLength::Pixels(px(20.0)),
2032 /// left: AbsoluteLength::Rems(rems(2.0)),
2033 /// };
2034 /// let rem_size = px(16.0);
2035 /// let edges_in_pixels = edges.to_pixels(rem_size);
2036 ///
2037 /// assert_eq!(edges_in_pixels.top, px(10.0)); // Already in pixels
2038 /// assert_eq!(edges_in_pixels.right, px(16.0)); // 1 rem converted to pixels
2039 /// assert_eq!(edges_in_pixels.bottom, px(20.0)); // Already in pixels
2040 /// assert_eq!(edges_in_pixels.left, px(32.0)); // 2 rems converted to pixels
2041 /// ```
2042 pub fn to_pixels(self, rem_size: Pixels) -> Edges<Pixels> {
2043 Edges {
2044 top: self.top.to_pixels(rem_size),
2045 right: self.right.to_pixels(rem_size),
2046 bottom: self.bottom.to_pixels(rem_size),
2047 left: self.left.to_pixels(rem_size),
2048 }
2049 }
2050}
2051
2052impl Edges<Pixels> {
2053 /// Scales the `Edges<Pixels>` by a given factor, returning `Edges<ScaledPixels>`.
2054 ///
2055 /// This method is typically used for adjusting the edge sizes for different display densities or scaling factors.
2056 ///
2057 /// # Arguments
2058 ///
2059 /// * `factor` - The scaling factor to apply to each edge.
2060 ///
2061 /// # Returns
2062 ///
2063 /// Returns a new `Edges<ScaledPixels>` where each edge is the result of scaling the original edge by the given factor.
2064 ///
2065 /// # Examples
2066 ///
2067 /// ```
2068 /// # use gpui::{Edges, Pixels, ScaledPixels};
2069 /// let edges = Edges {
2070 /// top: Pixels::from(10.0),
2071 /// right: Pixels::from(20.0),
2072 /// bottom: Pixels::from(30.0),
2073 /// left: Pixels::from(40.0),
2074 /// };
2075 /// let scaled_edges = edges.scale(2.0);
2076 /// assert_eq!(scaled_edges.top, ScaledPixels::from(20.0));
2077 /// assert_eq!(scaled_edges.right, ScaledPixels::from(40.0));
2078 /// assert_eq!(scaled_edges.bottom, ScaledPixels::from(60.0));
2079 /// assert_eq!(scaled_edges.left, ScaledPixels::from(80.0));
2080 /// ```
2081 pub fn scale(&self, factor: f32) -> Edges<ScaledPixels> {
2082 Edges {
2083 top: self.top.scale(factor),
2084 right: self.right.scale(factor),
2085 bottom: self.bottom.scale(factor),
2086 left: self.left.scale(factor),
2087 }
2088 }
2089
2090 /// Returns the maximum value of any edge.
2091 ///
2092 /// # Returns
2093 ///
2094 /// The maximum `Pixels` value among all four edges.
2095 pub fn max(&self) -> Pixels {
2096 self.top.max(self.right).max(self.bottom).max(self.left)
2097 }
2098}
2099
2100impl From<f32> for Edges<Pixels> {
2101 fn from(val: f32) -> Self {
2102 let val: Pixels = val.into();
2103 val.into()
2104 }
2105}
2106
2107impl From<Pixels> for Edges<Pixels> {
2108 fn from(val: Pixels) -> Self {
2109 Edges {
2110 top: val,
2111 right: val,
2112 bottom: val,
2113 left: val,
2114 }
2115 }
2116}
2117
2118/// Identifies a corner of a 2d box.
2119#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2120pub enum Corner {
2121 /// The top left corner
2122 TopLeft,
2123 /// The top right corner
2124 TopRight,
2125 /// The bottom left corner
2126 BottomLeft,
2127 /// The bottom right corner
2128 BottomRight,
2129}
2130
2131impl Corner {
2132 /// Returns the directly opposite corner.
2133 ///
2134 /// # Examples
2135 ///
2136 /// ```
2137 /// # use gpui::Corner;
2138 /// assert_eq!(Corner::TopLeft.opposite_corner(), Corner::BottomRight);
2139 /// ```
2140 #[must_use]
2141 pub fn opposite_corner(self) -> Self {
2142 match self {
2143 Corner::TopLeft => Corner::BottomRight,
2144 Corner::TopRight => Corner::BottomLeft,
2145 Corner::BottomLeft => Corner::TopRight,
2146 Corner::BottomRight => Corner::TopLeft,
2147 }
2148 }
2149
2150 /// Returns the corner across from this corner, moving along the specified axis.
2151 ///
2152 /// # Examples
2153 ///
2154 /// ```
2155 /// # use gpui::{Axis, Corner};
2156 /// let result = Corner::TopLeft.other_side_corner_along(Axis::Horizontal);
2157 /// assert_eq!(result, Corner::TopRight);
2158 /// ```
2159 #[must_use]
2160 pub fn other_side_corner_along(self, axis: Axis) -> Self {
2161 match axis {
2162 Axis::Vertical => match self {
2163 Corner::TopLeft => Corner::BottomLeft,
2164 Corner::TopRight => Corner::BottomRight,
2165 Corner::BottomLeft => Corner::TopLeft,
2166 Corner::BottomRight => Corner::TopRight,
2167 },
2168 Axis::Horizontal => match self {
2169 Corner::TopLeft => Corner::TopRight,
2170 Corner::TopRight => Corner::TopLeft,
2171 Corner::BottomLeft => Corner::BottomRight,
2172 Corner::BottomRight => Corner::BottomLeft,
2173 },
2174 }
2175 }
2176}
2177
2178/// Represents the corners of a box in a 2D space, such as border radius.
2179///
2180/// Each field represents the size of the corner on one side of the box: `top_left`, `top_right`, `bottom_right`, and `bottom_left`.
2181#[derive(Refineable, Clone, Default, Debug, Eq, PartialEq)]
2182#[refineable(Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
2183#[repr(C)]
2184pub struct Corners<T: Clone + Debug + Default + PartialEq> {
2185 /// The value associated with the top left corner.
2186 pub top_left: T,
2187 /// The value associated with the top right corner.
2188 pub top_right: T,
2189 /// The value associated with the bottom right corner.
2190 pub bottom_right: T,
2191 /// The value associated with the bottom left corner.
2192 pub bottom_left: T,
2193}
2194
2195impl<T> Corners<T>
2196where
2197 T: Clone + Debug + Default + PartialEq,
2198{
2199 /// Constructs `Corners` where all sides are set to the same specified value.
2200 ///
2201 /// This function creates a `Corners` instance with the `top_left`, `top_right`, `bottom_right`, and `bottom_left` fields all initialized
2202 /// to the same value provided as an argument. This is useful when you want to have uniform corners around a box,
2203 /// such as a uniform border radius on a rectangle.
2204 ///
2205 /// # Arguments
2206 ///
2207 /// * `value` - The value to set for all four corners.
2208 ///
2209 /// # Returns
2210 ///
2211 /// An `Corners` instance with all corners set to the given value.
2212 ///
2213 /// # Examples
2214 ///
2215 /// ```
2216 /// # use gpui::Corners;
2217 /// let uniform_corners = Corners::all(5.0);
2218 /// assert_eq!(uniform_corners.top_left, 5.0);
2219 /// assert_eq!(uniform_corners.top_right, 5.0);
2220 /// assert_eq!(uniform_corners.bottom_right, 5.0);
2221 /// assert_eq!(uniform_corners.bottom_left, 5.0);
2222 /// ```
2223 pub fn all(value: T) -> Self {
2224 Self {
2225 top_left: value.clone(),
2226 top_right: value.clone(),
2227 bottom_right: value.clone(),
2228 bottom_left: value,
2229 }
2230 }
2231
2232 /// Returns the requested corner.
2233 ///
2234 /// # Returns
2235 ///
2236 /// A `Point<T>` representing the corner requested by the parameter.
2237 ///
2238 /// # Examples
2239 ///
2240 /// ```
2241 /// # use gpui::{Corner, Corners};
2242 /// let corners = Corners {
2243 /// top_left: 1,
2244 /// top_right: 2,
2245 /// bottom_left: 3,
2246 /// bottom_right: 4
2247 /// };
2248 /// assert_eq!(corners.corner(Corner::BottomLeft), 3);
2249 /// ```
2250 #[must_use]
2251 pub fn corner(&self, corner: Corner) -> T {
2252 match corner {
2253 Corner::TopLeft => self.top_left.clone(),
2254 Corner::TopRight => self.top_right.clone(),
2255 Corner::BottomLeft => self.bottom_left.clone(),
2256 Corner::BottomRight => self.bottom_right.clone(),
2257 }
2258 }
2259}
2260
2261impl Corners<AbsoluteLength> {
2262 /// Converts the `AbsoluteLength` to `Pixels` based on the provided rem size.
2263 ///
2264 /// # Arguments
2265 ///
2266 /// * `rem_size` - The size of one REM unit in pixels, used for conversion if the `AbsoluteLength` is in REMs.
2267 ///
2268 /// # Returns
2269 ///
2270 /// Returns a `Corners<Pixels>` instance with each corner's length converted to pixels.
2271 ///
2272 /// # Examples
2273 ///
2274 /// ```
2275 /// # use gpui::{Corners, AbsoluteLength, Pixels, Rems, Size};
2276 /// let corners = Corners {
2277 /// top_left: AbsoluteLength::Pixels(Pixels::from(15.0)),
2278 /// top_right: AbsoluteLength::Rems(Rems(1.0)),
2279 /// bottom_right: AbsoluteLength::Pixels(Pixels::from(30.0)),
2280 /// bottom_left: AbsoluteLength::Rems(Rems(2.0)),
2281 /// };
2282 /// let rem_size = Pixels::from(16.0);
2283 /// let corners_in_pixels = corners.to_pixels(rem_size);
2284 ///
2285 /// assert_eq!(corners_in_pixels.top_left, Pixels::from(15.0));
2286 /// assert_eq!(corners_in_pixels.top_right, Pixels::from(16.0)); // 1 rem converted to pixels
2287 /// assert_eq!(corners_in_pixels.bottom_right, Pixels::from(30.0));
2288 /// assert_eq!(corners_in_pixels.bottom_left, Pixels::from(32.0)); // 2 rems converted to pixels
2289 /// ```
2290 pub fn to_pixels(self, rem_size: Pixels) -> Corners<Pixels> {
2291 Corners {
2292 top_left: self.top_left.to_pixels(rem_size),
2293 top_right: self.top_right.to_pixels(rem_size),
2294 bottom_right: self.bottom_right.to_pixels(rem_size),
2295 bottom_left: self.bottom_left.to_pixels(rem_size),
2296 }
2297 }
2298}
2299
2300impl Corners<Pixels> {
2301 /// Scales the `Corners<Pixels>` by a given factor, returning `Corners<ScaledPixels>`.
2302 ///
2303 /// This method is typically used for adjusting the corner sizes for different display densities or scaling factors.
2304 ///
2305 /// # Arguments
2306 ///
2307 /// * `factor` - The scaling factor to apply to each corner.
2308 ///
2309 /// # Returns
2310 ///
2311 /// Returns a new `Corners<ScaledPixels>` where each corner is the result of scaling the original corner by the given factor.
2312 ///
2313 /// # Examples
2314 ///
2315 /// ```
2316 /// # use gpui::{Corners, Pixels, ScaledPixels};
2317 /// let corners = Corners {
2318 /// top_left: Pixels::from(10.0),
2319 /// top_right: Pixels::from(20.0),
2320 /// bottom_right: Pixels::from(30.0),
2321 /// bottom_left: Pixels::from(40.0),
2322 /// };
2323 /// let scaled_corners = corners.scale(2.0);
2324 /// assert_eq!(scaled_corners.top_left, ScaledPixels::from(20.0));
2325 /// assert_eq!(scaled_corners.top_right, ScaledPixels::from(40.0));
2326 /// assert_eq!(scaled_corners.bottom_right, ScaledPixels::from(60.0));
2327 /// assert_eq!(scaled_corners.bottom_left, ScaledPixels::from(80.0));
2328 /// ```
2329 #[must_use]
2330 pub fn scale(&self, factor: f32) -> Corners<ScaledPixels> {
2331 Corners {
2332 top_left: self.top_left.scale(factor),
2333 top_right: self.top_right.scale(factor),
2334 bottom_right: self.bottom_right.scale(factor),
2335 bottom_left: self.bottom_left.scale(factor),
2336 }
2337 }
2338
2339 /// Returns the maximum value of any corner.
2340 ///
2341 /// # Returns
2342 ///
2343 /// The maximum `Pixels` value among all four corners.
2344 #[must_use]
2345 pub fn max(&self) -> Pixels {
2346 self.top_left
2347 .max(self.top_right)
2348 .max(self.bottom_right)
2349 .max(self.bottom_left)
2350 }
2351}
2352
2353impl<T: Div<f32, Output = T> + Ord + Clone + Debug + Default + PartialEq> Corners<T> {
2354 /// Clamps corner radii to be less than or equal to half the shortest side of a quad.
2355 ///
2356 /// # Arguments
2357 ///
2358 /// * `size` - The size of the quad which limits the size of the corner radii.
2359 ///
2360 /// # Returns
2361 ///
2362 /// Corner radii values clamped to fit.
2363 #[must_use]
2364 pub fn clamp_radii_for_quad_size(self, size: Size<T>) -> Corners<T> {
2365 let max = cmp::min(size.width, size.height) / 2.;
2366 Corners {
2367 top_left: cmp::min(self.top_left, max.clone()),
2368 top_right: cmp::min(self.top_right, max.clone()),
2369 bottom_right: cmp::min(self.bottom_right, max.clone()),
2370 bottom_left: cmp::min(self.bottom_left, max),
2371 }
2372 }
2373}
2374
2375impl<T: Clone + Debug + Default + PartialEq> Corners<T> {
2376 /// Applies a function to each field of the `Corners`, producing a new `Corners<U>`.
2377 ///
2378 /// This method allows for converting a `Corners<T>` to a `Corners<U>` by specifying a closure
2379 /// that defines how to convert between the two types. The closure is applied to each field
2380 /// (`top_left`, `top_right`, `bottom_right`, `bottom_left`), resulting in new corners of the desired type.
2381 ///
2382 /// # Arguments
2383 ///
2384 /// * `f` - A closure that takes a reference to a value of type `T` and returns a value of type `U`.
2385 ///
2386 /// # Returns
2387 ///
2388 /// Returns a new `Corners<U>` with each field mapped by the provided function.
2389 ///
2390 /// # Examples
2391 ///
2392 /// ```
2393 /// # use gpui::{Corners, Pixels, Rems};
2394 /// let corners = Corners {
2395 /// top_left: Pixels::from(10.0),
2396 /// top_right: Pixels::from(20.0),
2397 /// bottom_right: Pixels::from(30.0),
2398 /// bottom_left: Pixels::from(40.0),
2399 /// };
2400 /// let corners_in_rems = corners.map(|&px| Rems(f32::from(px) / 16.0));
2401 /// assert_eq!(corners_in_rems, Corners {
2402 /// top_left: Rems(0.625),
2403 /// top_right: Rems(1.25),
2404 /// bottom_right: Rems(1.875),
2405 /// bottom_left: Rems(2.5),
2406 /// });
2407 /// ```
2408 #[must_use]
2409 pub fn map<U>(&self, f: impl Fn(&T) -> U) -> Corners<U>
2410 where
2411 U: Clone + Debug + Default + PartialEq,
2412 {
2413 Corners {
2414 top_left: f(&self.top_left),
2415 top_right: f(&self.top_right),
2416 bottom_right: f(&self.bottom_right),
2417 bottom_left: f(&self.bottom_left),
2418 }
2419 }
2420}
2421
2422impl<T> Mul for Corners<T>
2423where
2424 T: Mul<Output = T> + Clone + Debug + Default + PartialEq,
2425{
2426 type Output = Self;
2427
2428 fn mul(self, rhs: Self) -> Self::Output {
2429 Self {
2430 top_left: self.top_left.clone() * rhs.top_left,
2431 top_right: self.top_right.clone() * rhs.top_right,
2432 bottom_right: self.bottom_right.clone() * rhs.bottom_right,
2433 bottom_left: self.bottom_left * rhs.bottom_left,
2434 }
2435 }
2436}
2437
2438impl<T, S> MulAssign<S> for Corners<T>
2439where
2440 T: Mul<S, Output = T> + Clone + Debug + Default + PartialEq,
2441 S: Clone,
2442{
2443 fn mul_assign(&mut self, rhs: S) {
2444 self.top_left = self.top_left.clone() * rhs.clone();
2445 self.top_right = self.top_right.clone() * rhs.clone();
2446 self.bottom_right = self.bottom_right.clone() * rhs.clone();
2447 self.bottom_left = self.bottom_left.clone() * rhs;
2448 }
2449}
2450
2451impl<T> Copy for Corners<T> where T: Copy + Clone + Debug + Default + PartialEq {}
2452
2453impl From<f32> for Corners<Pixels> {
2454 fn from(val: f32) -> Self {
2455 Corners {
2456 top_left: val.into(),
2457 top_right: val.into(),
2458 bottom_right: val.into(),
2459 bottom_left: val.into(),
2460 }
2461 }
2462}
2463
2464impl From<Pixels> for Corners<Pixels> {
2465 fn from(val: Pixels) -> Self {
2466 Corners {
2467 top_left: val,
2468 top_right: val,
2469 bottom_right: val,
2470 bottom_left: val,
2471 }
2472 }
2473}
2474
2475/// Represents an angle in Radians
2476#[derive(
2477 Clone,
2478 Copy,
2479 Default,
2480 Add,
2481 AddAssign,
2482 Sub,
2483 SubAssign,
2484 Neg,
2485 Div,
2486 DivAssign,
2487 PartialEq,
2488 Serialize,
2489 Deserialize,
2490 Debug,
2491)]
2492#[repr(transparent)]
2493pub struct Radians(pub f32);
2494
2495/// Create a `Radian` from a raw value
2496pub fn radians(value: f32) -> Radians {
2497 Radians(value)
2498}
2499
2500/// A type representing a percentage value.
2501#[derive(
2502 Clone,
2503 Copy,
2504 Default,
2505 Add,
2506 AddAssign,
2507 Sub,
2508 SubAssign,
2509 Neg,
2510 Div,
2511 DivAssign,
2512 PartialEq,
2513 Serialize,
2514 Deserialize,
2515 Debug,
2516)]
2517#[repr(transparent)]
2518pub struct Percentage(pub f32);
2519
2520/// Generate a `Radian` from a percentage of a full circle.
2521pub fn percentage(value: f32) -> Percentage {
2522 debug_assert!(
2523 (0.0..=1.0).contains(&value),
2524 "Percentage must be between 0 and 1"
2525 );
2526 Percentage(value)
2527}
2528
2529impl From<Percentage> for Radians {
2530 fn from(value: Percentage) -> Self {
2531 radians(value.0 * std::f32::consts::PI * 2.0)
2532 }
2533}
2534
2535/// Represents a length in pixels, the base unit of measurement in the UI framework.
2536///
2537/// `Pixels` is a value type that represents an absolute length in pixels, which is used
2538/// for specifying sizes, positions, and distances in the UI. It is the fundamental unit
2539/// of measurement for all visual elements and layout calculations.
2540///
2541/// The inner value is an `f32`, allowing for sub-pixel precision which can be useful for
2542/// anti-aliasing and animations. However, when applied to actual pixel grids, the value
2543/// is typically rounded to the nearest integer.
2544///
2545/// # Examples
2546///
2547/// ```
2548/// use gpui::{Pixels, ScaledPixels};
2549///
2550/// // Define a length of 10 pixels
2551/// let length = Pixels::from(10.0);
2552///
2553/// // Define a length and scale it by a factor of 2
2554/// let scaled_length = length.scale(2.0);
2555/// assert_eq!(scaled_length, ScaledPixels::from(20.0));
2556/// ```
2557#[derive(
2558 Clone,
2559 Copy,
2560 Default,
2561 Add,
2562 AddAssign,
2563 Sub,
2564 SubAssign,
2565 Neg,
2566 Div,
2567 DivAssign,
2568 PartialEq,
2569 Serialize,
2570 Deserialize,
2571 JsonSchema,
2572)]
2573#[repr(transparent)]
2574pub struct Pixels(pub(crate) f32);
2575
2576impl Div for Pixels {
2577 type Output = f32;
2578
2579 fn div(self, rhs: Self) -> Self::Output {
2580 self.0 / rhs.0
2581 }
2582}
2583
2584impl std::ops::DivAssign for Pixels {
2585 fn div_assign(&mut self, rhs: Self) {
2586 *self = Self(self.0 / rhs.0);
2587 }
2588}
2589
2590impl std::ops::RemAssign for Pixels {
2591 fn rem_assign(&mut self, rhs: Self) {
2592 self.0 %= rhs.0;
2593 }
2594}
2595
2596impl std::ops::Rem for Pixels {
2597 type Output = Self;
2598
2599 fn rem(self, rhs: Self) -> Self {
2600 Self(self.0 % rhs.0)
2601 }
2602}
2603
2604impl Mul<f32> for Pixels {
2605 type Output = Self;
2606
2607 fn mul(self, rhs: f32) -> Self {
2608 Self(self.0 * rhs)
2609 }
2610}
2611
2612impl Mul<Pixels> for f32 {
2613 type Output = Pixels;
2614
2615 fn mul(self, rhs: Pixels) -> Self::Output {
2616 rhs * self
2617 }
2618}
2619
2620impl Mul<usize> for Pixels {
2621 type Output = Self;
2622
2623 fn mul(self, rhs: usize) -> Self {
2624 self * (rhs as f32)
2625 }
2626}
2627
2628impl Mul<Pixels> for usize {
2629 type Output = Pixels;
2630
2631 fn mul(self, rhs: Pixels) -> Pixels {
2632 rhs * self
2633 }
2634}
2635
2636impl MulAssign<f32> for Pixels {
2637 fn mul_assign(&mut self, rhs: f32) {
2638 self.0 *= rhs;
2639 }
2640}
2641
2642impl Display for Pixels {
2643 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2644 write!(f, "{}px", self.0)
2645 }
2646}
2647
2648impl Debug for Pixels {
2649 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2650 Display::fmt(self, f)
2651 }
2652}
2653
2654impl std::iter::Sum for Pixels {
2655 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
2656 iter.fold(Self::ZERO, |a, b| a + b)
2657 }
2658}
2659
2660impl<'a> std::iter::Sum<&'a Pixels> for Pixels {
2661 fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
2662 iter.fold(Self::ZERO, |a, b| a + *b)
2663 }
2664}
2665
2666impl TryFrom<&'_ str> for Pixels {
2667 type Error = anyhow::Error;
2668
2669 fn try_from(value: &'_ str) -> Result<Self, Self::Error> {
2670 value
2671 .strip_suffix("px")
2672 .context("expected 'px' suffix")
2673 .and_then(|number| Ok(number.parse()?))
2674 .map(Self)
2675 }
2676}
2677
2678impl Pixels {
2679 /// Represents zero pixels.
2680 pub const ZERO: Pixels = Pixels(0.0);
2681 /// The maximum value that can be represented by `Pixels`.
2682 pub const MAX: Pixels = Pixels(f32::MAX);
2683 /// The minimum value that can be represented by `Pixels`.
2684 pub const MIN: Pixels = Pixels(f32::MIN);
2685
2686 /// Floors the `Pixels` value to the nearest whole number.
2687 ///
2688 /// # Returns
2689 ///
2690 /// Returns a new `Pixels` instance with the floored value.
2691 pub fn floor(&self) -> Self {
2692 Self(self.0.floor())
2693 }
2694
2695 /// Rounds the `Pixels` value to the nearest whole number.
2696 ///
2697 /// # Returns
2698 ///
2699 /// Returns a new `Pixels` instance with the rounded value.
2700 pub fn round(&self) -> Self {
2701 Self(self.0.round())
2702 }
2703
2704 /// Returns the ceiling of the `Pixels` value to the nearest whole number.
2705 ///
2706 /// # Returns
2707 ///
2708 /// Returns a new `Pixels` instance with the ceiling value.
2709 pub fn ceil(&self) -> Self {
2710 Self(self.0.ceil())
2711 }
2712
2713 /// Scales the `Pixels` value by a given factor, producing `ScaledPixels`.
2714 ///
2715 /// This method is used when adjusting pixel values for display scaling factors,
2716 /// such as high DPI (dots per inch) or Retina displays, where the pixel density is higher and
2717 /// thus requires scaling to maintain visual consistency and readability.
2718 ///
2719 /// The resulting `ScaledPixels` represent the scaled value which can be used for rendering
2720 /// calculations where display scaling is considered.
2721 #[must_use]
2722 pub fn scale(&self, factor: f32) -> ScaledPixels {
2723 ScaledPixels(self.0 * factor)
2724 }
2725
2726 /// Raises the `Pixels` value to a given power.
2727 ///
2728 /// # Arguments
2729 ///
2730 /// * `exponent` - The exponent to raise the `Pixels` value by.
2731 ///
2732 /// # Returns
2733 ///
2734 /// Returns a new `Pixels` instance with the value raised to the given exponent.
2735 pub fn pow(&self, exponent: f32) -> Self {
2736 Self(self.0.powf(exponent))
2737 }
2738
2739 /// Returns the absolute value of the `Pixels`.
2740 ///
2741 /// # Returns
2742 ///
2743 /// A new `Pixels` instance with the absolute value of the original `Pixels`.
2744 pub fn abs(&self) -> Self {
2745 Self(self.0.abs())
2746 }
2747
2748 /// Returns the sign of the `Pixels` value.
2749 ///
2750 /// # Returns
2751 ///
2752 /// Returns:
2753 /// * `1.0` if the value is positive
2754 /// * `-1.0` if the value is negative
2755 pub fn signum(&self) -> f32 {
2756 self.0.signum()
2757 }
2758
2759 /// Returns the f64 value of `Pixels`.
2760 ///
2761 /// # Returns
2762 ///
2763 /// A f64 value of the `Pixels`.
2764 pub fn to_f64(self) -> f64 {
2765 self.0 as f64
2766 }
2767}
2768
2769impl Eq for Pixels {}
2770
2771impl PartialOrd for Pixels {
2772 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
2773 Some(self.cmp(other))
2774 }
2775}
2776
2777impl Ord for Pixels {
2778 fn cmp(&self, other: &Self) -> cmp::Ordering {
2779 self.0.total_cmp(&other.0)
2780 }
2781}
2782
2783impl std::hash::Hash for Pixels {
2784 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2785 self.0.to_bits().hash(state);
2786 }
2787}
2788
2789impl From<f64> for Pixels {
2790 fn from(pixels: f64) -> Self {
2791 Pixels(pixels as f32)
2792 }
2793}
2794
2795impl From<f32> for Pixels {
2796 fn from(pixels: f32) -> Self {
2797 Pixels(pixels)
2798 }
2799}
2800
2801impl From<Pixels> for f32 {
2802 fn from(pixels: Pixels) -> Self {
2803 pixels.0
2804 }
2805}
2806
2807impl From<&Pixels> for f32 {
2808 fn from(pixels: &Pixels) -> Self {
2809 pixels.0
2810 }
2811}
2812
2813impl From<Pixels> for f64 {
2814 fn from(pixels: Pixels) -> Self {
2815 pixels.0 as f64
2816 }
2817}
2818
2819impl From<Pixels> for u32 {
2820 fn from(pixels: Pixels) -> Self {
2821 pixels.0 as u32
2822 }
2823}
2824
2825impl From<&Pixels> for u32 {
2826 fn from(pixels: &Pixels) -> Self {
2827 pixels.0 as u32
2828 }
2829}
2830
2831impl From<u32> for Pixels {
2832 fn from(pixels: u32) -> Self {
2833 Pixels(pixels as f32)
2834 }
2835}
2836
2837impl From<Pixels> for usize {
2838 fn from(pixels: Pixels) -> Self {
2839 pixels.0 as usize
2840 }
2841}
2842
2843impl From<usize> for Pixels {
2844 fn from(pixels: usize) -> Self {
2845 Pixels(pixels as f32)
2846 }
2847}
2848
2849/// Represents physical pixels on the display.
2850///
2851/// `DevicePixels` is a unit of measurement that refers to the actual pixels on a device's screen.
2852/// This type is used when precise pixel manipulation is required, such as rendering graphics or
2853/// interfacing with hardware that operates on the pixel level. Unlike logical pixels that may be
2854/// affected by the device's scale factor, `DevicePixels` always correspond to real pixels on the
2855/// display.
2856#[derive(
2857 Add,
2858 AddAssign,
2859 Clone,
2860 Copy,
2861 Default,
2862 Div,
2863 Eq,
2864 Hash,
2865 Ord,
2866 PartialEq,
2867 PartialOrd,
2868 Sub,
2869 SubAssign,
2870 Serialize,
2871 Deserialize,
2872)]
2873#[repr(transparent)]
2874pub struct DevicePixels(pub i32);
2875
2876impl DevicePixels {
2877 /// Converts the `DevicePixels` value to the number of bytes needed to represent it in memory.
2878 ///
2879 /// This function is useful when working with graphical data that needs to be stored in a buffer,
2880 /// such as images or framebuffers, where each pixel may be represented by a specific number of bytes.
2881 ///
2882 /// # Arguments
2883 ///
2884 /// * `bytes_per_pixel` - The number of bytes used to represent a single pixel.
2885 ///
2886 /// # Returns
2887 ///
2888 /// The number of bytes required to represent the `DevicePixels` value in memory.
2889 ///
2890 /// # Examples
2891 ///
2892 /// ```
2893 /// # use gpui::DevicePixels;
2894 /// let pixels = DevicePixels(10); // 10 device pixels
2895 /// let bytes_per_pixel = 4; // Assume each pixel is represented by 4 bytes (e.g., RGBA)
2896 /// let total_bytes = pixels.to_bytes(bytes_per_pixel);
2897 /// assert_eq!(total_bytes, 40); // 10 pixels * 4 bytes/pixel = 40 bytes
2898 /// ```
2899 pub fn to_bytes(self, bytes_per_pixel: u8) -> u32 {
2900 self.0 as u32 * bytes_per_pixel as u32
2901 }
2902}
2903
2904impl fmt::Debug for DevicePixels {
2905 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2906 write!(f, "{} px (device)", self.0)
2907 }
2908}
2909
2910impl From<DevicePixels> for i32 {
2911 fn from(device_pixels: DevicePixels) -> Self {
2912 device_pixels.0
2913 }
2914}
2915
2916impl From<i32> for DevicePixels {
2917 fn from(device_pixels: i32) -> Self {
2918 DevicePixels(device_pixels)
2919 }
2920}
2921
2922impl From<u32> for DevicePixels {
2923 fn from(device_pixels: u32) -> Self {
2924 DevicePixels(device_pixels as i32)
2925 }
2926}
2927
2928impl From<DevicePixels> for u32 {
2929 fn from(device_pixels: DevicePixels) -> Self {
2930 device_pixels.0 as u32
2931 }
2932}
2933
2934impl From<DevicePixels> for u64 {
2935 fn from(device_pixels: DevicePixels) -> Self {
2936 device_pixels.0 as u64
2937 }
2938}
2939
2940impl From<u64> for DevicePixels {
2941 fn from(device_pixels: u64) -> Self {
2942 DevicePixels(device_pixels as i32)
2943 }
2944}
2945
2946impl From<DevicePixels> for usize {
2947 fn from(device_pixels: DevicePixels) -> Self {
2948 device_pixels.0 as usize
2949 }
2950}
2951
2952impl From<usize> for DevicePixels {
2953 fn from(device_pixels: usize) -> Self {
2954 DevicePixels(device_pixels as i32)
2955 }
2956}
2957
2958/// Represents scaled pixels that take into account the device's scale factor.
2959///
2960/// `ScaledPixels` are used to ensure that UI elements appear at the correct size on devices
2961/// with different pixel densities. When a device has a higher scale factor (such as Retina displays),
2962/// a single logical pixel may correspond to multiple physical pixels. By using `ScaledPixels`,
2963/// dimensions and positions can be specified in a way that scales appropriately across different
2964/// display resolutions.
2965#[derive(Clone, Copy, Default, Add, AddAssign, Sub, SubAssign, Div, DivAssign, PartialEq)]
2966#[repr(transparent)]
2967pub struct ScaledPixels(pub(crate) f32);
2968
2969impl ScaledPixels {
2970 /// Floors the `ScaledPixels` value to the nearest whole number.
2971 ///
2972 /// # Returns
2973 ///
2974 /// Returns a new `ScaledPixels` instance with the floored value.
2975 pub fn floor(&self) -> Self {
2976 Self(self.0.floor())
2977 }
2978
2979 /// Rounds the `ScaledPixels` value to the nearest whole number.
2980 ///
2981 /// # Returns
2982 ///
2983 /// Returns a new `ScaledPixels` instance with the rounded value.
2984 pub fn round(&self) -> Self {
2985 Self(self.0.round())
2986 }
2987
2988 /// Ceils the `ScaledPixels` value to the nearest whole number.
2989 ///
2990 /// # Returns
2991 ///
2992 /// Returns a new `ScaledPixels` instance with the ceiled value.
2993 pub fn ceil(&self) -> Self {
2994 Self(self.0.ceil())
2995 }
2996}
2997
2998impl Eq for ScaledPixels {}
2999
3000impl PartialOrd for ScaledPixels {
3001 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
3002 Some(self.cmp(other))
3003 }
3004}
3005
3006impl Ord for ScaledPixels {
3007 fn cmp(&self, other: &Self) -> cmp::Ordering {
3008 self.0.total_cmp(&other.0)
3009 }
3010}
3011
3012impl Debug for ScaledPixels {
3013 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3014 write!(f, "{}px (scaled)", self.0)
3015 }
3016}
3017
3018impl From<ScaledPixels> for DevicePixels {
3019 fn from(scaled: ScaledPixels) -> Self {
3020 DevicePixels(scaled.0.ceil() as i32)
3021 }
3022}
3023
3024impl From<DevicePixels> for ScaledPixels {
3025 fn from(device: DevicePixels) -> Self {
3026 ScaledPixels(device.0 as f32)
3027 }
3028}
3029
3030impl From<ScaledPixels> for f64 {
3031 fn from(scaled_pixels: ScaledPixels) -> Self {
3032 scaled_pixels.0 as f64
3033 }
3034}
3035
3036impl From<ScaledPixels> for u32 {
3037 fn from(pixels: ScaledPixels) -> Self {
3038 pixels.0 as u32
3039 }
3040}
3041
3042impl From<f32> for ScaledPixels {
3043 fn from(pixels: f32) -> Self {
3044 Self(pixels)
3045 }
3046}
3047
3048impl Div for ScaledPixels {
3049 type Output = f32;
3050
3051 fn div(self, rhs: Self) -> Self::Output {
3052 self.0 / rhs.0
3053 }
3054}
3055
3056impl std::ops::DivAssign for ScaledPixels {
3057 fn div_assign(&mut self, rhs: Self) {
3058 *self = Self(self.0 / rhs.0);
3059 }
3060}
3061
3062impl std::ops::RemAssign for ScaledPixels {
3063 fn rem_assign(&mut self, rhs: Self) {
3064 self.0 %= rhs.0;
3065 }
3066}
3067
3068impl std::ops::Rem for ScaledPixels {
3069 type Output = Self;
3070
3071 fn rem(self, rhs: Self) -> Self {
3072 Self(self.0 % rhs.0)
3073 }
3074}
3075
3076impl Mul<f32> for ScaledPixels {
3077 type Output = Self;
3078
3079 fn mul(self, rhs: f32) -> Self {
3080 Self(self.0 * rhs)
3081 }
3082}
3083
3084impl Mul<ScaledPixels> for f32 {
3085 type Output = ScaledPixels;
3086
3087 fn mul(self, rhs: ScaledPixels) -> Self::Output {
3088 rhs * self
3089 }
3090}
3091
3092impl Mul<usize> for ScaledPixels {
3093 type Output = Self;
3094
3095 fn mul(self, rhs: usize) -> Self {
3096 self * (rhs as f32)
3097 }
3098}
3099
3100impl Mul<ScaledPixels> for usize {
3101 type Output = ScaledPixels;
3102
3103 fn mul(self, rhs: ScaledPixels) -> ScaledPixels {
3104 rhs * self
3105 }
3106}
3107
3108impl MulAssign<f32> for ScaledPixels {
3109 fn mul_assign(&mut self, rhs: f32) {
3110 self.0 *= rhs;
3111 }
3112}
3113
3114/// 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].
3115///
3116/// Rems are used for defining lengths that are scalable and consistent across different UI elements.
3117/// The value of `1rem` is typically equal to the font-size of the root element (often the `<html>` element in browsers),
3118/// making it a flexible unit that adapts to the user's text size preferences. In this framework, `rems` serve a similar
3119/// purpose, allowing for scalable and accessible design that can adjust to different display settings or user preferences.
3120///
3121/// For example, if the root element's font-size is `16px`, then `1rem` equals `16px`. A length of `2rems` would then be `32px`.
3122///
3123/// [set_rem_size]: crate::Window::set_rem_size
3124#[derive(Clone, Copy, Default, Add, Sub, Mul, Div, Neg, PartialEq)]
3125pub struct Rems(pub f32);
3126
3127impl Rems {
3128 /// Convert this Rem value to pixels.
3129 pub fn to_pixels(self, rem_size: Pixels) -> Pixels {
3130 self * rem_size
3131 }
3132}
3133
3134impl Mul<Pixels> for Rems {
3135 type Output = Pixels;
3136
3137 fn mul(self, other: Pixels) -> Pixels {
3138 Pixels(self.0 * other.0)
3139 }
3140}
3141
3142impl Display for Rems {
3143 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3144 write!(f, "{}rem", self.0)
3145 }
3146}
3147
3148impl Debug for Rems {
3149 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3150 Display::fmt(self, f)
3151 }
3152}
3153
3154impl TryFrom<&'_ str> for Rems {
3155 type Error = anyhow::Error;
3156
3157 fn try_from(value: &'_ str) -> Result<Self, Self::Error> {
3158 value
3159 .strip_suffix("rem")
3160 .context("expected 'rem' suffix")
3161 .and_then(|number| Ok(number.parse()?))
3162 .map(Self)
3163 }
3164}
3165
3166/// Represents an absolute length in pixels or rems.
3167///
3168/// `AbsoluteLength` can be either a fixed number of pixels, which is an absolute measurement not
3169/// affected by the current font size, or a number of rems, which is relative to the font size of
3170/// the root element. It is used for specifying dimensions that are either independent of or
3171/// related to the typographic scale.
3172#[derive(Clone, Copy, Neg, PartialEq)]
3173pub enum AbsoluteLength {
3174 /// A length in pixels.
3175 Pixels(Pixels),
3176 /// A length in rems.
3177 Rems(Rems),
3178}
3179
3180impl AbsoluteLength {
3181 /// Checks if the absolute length is zero.
3182 pub fn is_zero(&self) -> bool {
3183 match self {
3184 AbsoluteLength::Pixels(px) => px.0 == 0.0,
3185 AbsoluteLength::Rems(rems) => rems.0 == 0.0,
3186 }
3187 }
3188}
3189
3190impl From<Pixels> for AbsoluteLength {
3191 fn from(pixels: Pixels) -> Self {
3192 AbsoluteLength::Pixels(pixels)
3193 }
3194}
3195
3196impl From<Rems> for AbsoluteLength {
3197 fn from(rems: Rems) -> Self {
3198 AbsoluteLength::Rems(rems)
3199 }
3200}
3201
3202impl AbsoluteLength {
3203 /// Converts an `AbsoluteLength` to `Pixels` based on a given `rem_size`.
3204 ///
3205 /// # Arguments
3206 ///
3207 /// * `rem_size` - The size of one rem in pixels.
3208 ///
3209 /// # Returns
3210 ///
3211 /// Returns the `AbsoluteLength` as `Pixels`.
3212 ///
3213 /// # Examples
3214 ///
3215 /// ```
3216 /// # use gpui::{AbsoluteLength, Pixels, Rems};
3217 /// let length_in_pixels = AbsoluteLength::Pixels(Pixels::from(42.0));
3218 /// let length_in_rems = AbsoluteLength::Rems(Rems(2.0));
3219 /// let rem_size = Pixels::from(16.0);
3220 ///
3221 /// assert_eq!(length_in_pixels.to_pixels(rem_size), Pixels::from(42.0));
3222 /// assert_eq!(length_in_rems.to_pixels(rem_size), Pixels::from(32.0));
3223 /// ```
3224 pub fn to_pixels(self, rem_size: Pixels) -> Pixels {
3225 match self {
3226 AbsoluteLength::Pixels(pixels) => pixels,
3227 AbsoluteLength::Rems(rems) => rems.to_pixels(rem_size),
3228 }
3229 }
3230
3231 /// Converts an `AbsoluteLength` to `Rems` based on a given `rem_size`.
3232 ///
3233 /// # Arguments
3234 ///
3235 /// * `rem_size` - The size of one rem in pixels.
3236 ///
3237 /// # Returns
3238 ///
3239 /// Returns the `AbsoluteLength` as `Pixels`.
3240 pub fn to_rems(self, rem_size: Pixels) -> Rems {
3241 match self {
3242 AbsoluteLength::Pixels(pixels) => Rems(pixels.0 / rem_size.0),
3243 AbsoluteLength::Rems(rems) => rems,
3244 }
3245 }
3246}
3247
3248impl Default for AbsoluteLength {
3249 fn default() -> Self {
3250 px(0.).into()
3251 }
3252}
3253
3254impl Display for AbsoluteLength {
3255 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3256 match self {
3257 Self::Pixels(pixels) => write!(f, "{pixels}"),
3258 Self::Rems(rems) => write!(f, "{rems}"),
3259 }
3260 }
3261}
3262
3263impl Debug for AbsoluteLength {
3264 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3265 Display::fmt(self, f)
3266 }
3267}
3268
3269const EXPECTED_ABSOLUTE_LENGTH: &str = "number with 'px' or 'rem' suffix";
3270
3271impl TryFrom<&'_ str> for AbsoluteLength {
3272 type Error = anyhow::Error;
3273
3274 fn try_from(value: &'_ str) -> Result<Self, Self::Error> {
3275 if let Ok(pixels) = value.try_into() {
3276 Ok(Self::Pixels(pixels))
3277 } else if let Ok(rems) = value.try_into() {
3278 Ok(Self::Rems(rems))
3279 } else {
3280 Err(anyhow!(
3281 "invalid AbsoluteLength '{value}', expected {EXPECTED_ABSOLUTE_LENGTH}"
3282 ))
3283 }
3284 }
3285}
3286
3287impl JsonSchema for AbsoluteLength {
3288 fn schema_name() -> Cow<'static, str> {
3289 "AbsoluteLength".into()
3290 }
3291
3292 fn json_schema(_generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
3293 json_schema!({
3294 "type": "string",
3295 "pattern": r"^-?\d+(\.\d+)?(px|rem)$"
3296 })
3297 }
3298}
3299
3300impl<'de> Deserialize<'de> for AbsoluteLength {
3301 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
3302 struct StringVisitor;
3303
3304 impl de::Visitor<'_> for StringVisitor {
3305 type Value = AbsoluteLength;
3306
3307 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
3308 write!(f, "{EXPECTED_ABSOLUTE_LENGTH}")
3309 }
3310
3311 fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
3312 AbsoluteLength::try_from(value).map_err(E::custom)
3313 }
3314 }
3315
3316 deserializer.deserialize_str(StringVisitor)
3317 }
3318}
3319
3320impl Serialize for AbsoluteLength {
3321 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
3322 where
3323 S: Serializer,
3324 {
3325 serializer.serialize_str(&format!("{self}"))
3326 }
3327}
3328
3329/// A non-auto length that can be defined in pixels, rems, or percent of parent.
3330///
3331/// This enum represents lengths that have a specific value, as opposed to lengths that are automatically
3332/// determined by the context. It includes absolute lengths in pixels or rems, and relative lengths as a
3333/// fraction of the parent's size.
3334#[derive(Clone, Copy, Neg, PartialEq)]
3335pub enum DefiniteLength {
3336 /// An absolute length specified in pixels or rems.
3337 Absolute(AbsoluteLength),
3338 /// A relative length specified as a fraction of the parent's size, between 0 and 1.
3339 Fraction(f32),
3340}
3341
3342impl DefiniteLength {
3343 /// Converts the `DefiniteLength` to `Pixels` based on a given `base_size` and `rem_size`.
3344 ///
3345 /// If the `DefiniteLength` is an absolute length, it will be directly converted to `Pixels`.
3346 /// If it is a fraction, the fraction will be multiplied by the `base_size` to get the length in pixels.
3347 ///
3348 /// # Arguments
3349 ///
3350 /// * `base_size` - The base size in `AbsoluteLength` to which the fraction will be applied.
3351 /// * `rem_size` - The size of one rem in pixels, used to convert rems to pixels.
3352 ///
3353 /// # Returns
3354 ///
3355 /// Returns the `DefiniteLength` as `Pixels`.
3356 ///
3357 /// # Examples
3358 ///
3359 /// ```
3360 /// # use gpui::{DefiniteLength, AbsoluteLength, Pixels, px, rems};
3361 /// let length_in_pixels = DefiniteLength::Absolute(AbsoluteLength::Pixels(px(42.0)));
3362 /// let length_in_rems = DefiniteLength::Absolute(AbsoluteLength::Rems(rems(2.0)));
3363 /// let length_as_fraction = DefiniteLength::Fraction(0.5);
3364 /// let base_size = AbsoluteLength::Pixels(px(100.0));
3365 /// let rem_size = px(16.0);
3366 ///
3367 /// assert_eq!(length_in_pixels.to_pixels(base_size, rem_size), Pixels::from(42.0));
3368 /// assert_eq!(length_in_rems.to_pixels(base_size, rem_size), Pixels::from(32.0));
3369 /// assert_eq!(length_as_fraction.to_pixels(base_size, rem_size), Pixels::from(50.0));
3370 /// ```
3371 pub fn to_pixels(self, base_size: AbsoluteLength, rem_size: Pixels) -> Pixels {
3372 match self {
3373 DefiniteLength::Absolute(size) => size.to_pixels(rem_size),
3374 DefiniteLength::Fraction(fraction) => match base_size {
3375 AbsoluteLength::Pixels(px) => px * fraction,
3376 AbsoluteLength::Rems(rems) => rems * rem_size * fraction,
3377 },
3378 }
3379 }
3380}
3381
3382impl Debug for DefiniteLength {
3383 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3384 Display::fmt(self, f)
3385 }
3386}
3387
3388impl Display for DefiniteLength {
3389 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3390 match self {
3391 DefiniteLength::Absolute(length) => write!(f, "{length}"),
3392 DefiniteLength::Fraction(fraction) => write!(f, "{}%", (fraction * 100.0) as i32),
3393 }
3394 }
3395}
3396
3397const EXPECTED_DEFINITE_LENGTH: &str = "expected number with 'px', 'rem', or '%' suffix";
3398
3399impl TryFrom<&'_ str> for DefiniteLength {
3400 type Error = anyhow::Error;
3401
3402 fn try_from(value: &'_ str) -> Result<Self, Self::Error> {
3403 if let Some(percentage) = value.strip_suffix('%') {
3404 let fraction: f32 = percentage.parse::<f32>().with_context(|| {
3405 format!("invalid DefiniteLength '{value}', expected {EXPECTED_DEFINITE_LENGTH}")
3406 })?;
3407 Ok(DefiniteLength::Fraction(fraction / 100.0))
3408 } else if let Ok(absolute_length) = value.try_into() {
3409 Ok(DefiniteLength::Absolute(absolute_length))
3410 } else {
3411 Err(anyhow!(
3412 "invalid DefiniteLength '{value}', expected {EXPECTED_DEFINITE_LENGTH}"
3413 ))
3414 }
3415 }
3416}
3417
3418impl JsonSchema for DefiniteLength {
3419 fn schema_name() -> Cow<'static, str> {
3420 "DefiniteLength".into()
3421 }
3422
3423 fn json_schema(_generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
3424 json_schema!({
3425 "type": "string",
3426 "pattern": r"^-?\d+(\.\d+)?(px|rem|%)$"
3427 })
3428 }
3429}
3430
3431impl<'de> Deserialize<'de> for DefiniteLength {
3432 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
3433 struct StringVisitor;
3434
3435 impl de::Visitor<'_> for StringVisitor {
3436 type Value = DefiniteLength;
3437
3438 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
3439 write!(f, "{EXPECTED_DEFINITE_LENGTH}")
3440 }
3441
3442 fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
3443 DefiniteLength::try_from(value).map_err(E::custom)
3444 }
3445 }
3446
3447 deserializer.deserialize_str(StringVisitor)
3448 }
3449}
3450
3451impl Serialize for DefiniteLength {
3452 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
3453 where
3454 S: Serializer,
3455 {
3456 serializer.serialize_str(&format!("{self}"))
3457 }
3458}
3459
3460impl From<Pixels> for DefiniteLength {
3461 fn from(pixels: Pixels) -> Self {
3462 Self::Absolute(pixels.into())
3463 }
3464}
3465
3466impl From<Rems> for DefiniteLength {
3467 fn from(rems: Rems) -> Self {
3468 Self::Absolute(rems.into())
3469 }
3470}
3471
3472impl From<AbsoluteLength> for DefiniteLength {
3473 fn from(length: AbsoluteLength) -> Self {
3474 Self::Absolute(length)
3475 }
3476}
3477
3478impl Default for DefiniteLength {
3479 fn default() -> Self {
3480 Self::Absolute(AbsoluteLength::default())
3481 }
3482}
3483
3484/// A length that can be defined in pixels, rems, percent of parent, or auto.
3485#[derive(Clone, Copy, PartialEq)]
3486pub enum Length {
3487 /// A definite length specified either in pixels, rems, or as a fraction of the parent's size.
3488 Definite(DefiniteLength),
3489 /// An automatic length that is determined by the context in which it is used.
3490 Auto,
3491}
3492
3493impl Debug for Length {
3494 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3495 Display::fmt(self, f)
3496 }
3497}
3498
3499impl Display for Length {
3500 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3501 match self {
3502 Length::Definite(definite_length) => write!(f, "{}", definite_length),
3503 Length::Auto => write!(f, "auto"),
3504 }
3505 }
3506}
3507
3508const EXPECTED_LENGTH: &str = "expected 'auto' or number with 'px', 'rem', or '%' suffix";
3509
3510impl TryFrom<&'_ str> for Length {
3511 type Error = anyhow::Error;
3512
3513 fn try_from(value: &'_ str) -> Result<Self, Self::Error> {
3514 if value == "auto" {
3515 Ok(Length::Auto)
3516 } else if let Ok(definite_length) = value.try_into() {
3517 Ok(Length::Definite(definite_length))
3518 } else {
3519 Err(anyhow!(
3520 "invalid Length '{value}', expected {EXPECTED_LENGTH}"
3521 ))
3522 }
3523 }
3524}
3525
3526impl JsonSchema for Length {
3527 fn schema_name() -> Cow<'static, str> {
3528 "Length".into()
3529 }
3530
3531 fn json_schema(_generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
3532 json_schema!({
3533 "type": "string",
3534 "pattern": r"^(auto|-?\d+(\.\d+)?(px|rem|%))$"
3535 })
3536 }
3537}
3538
3539impl<'de> Deserialize<'de> for Length {
3540 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
3541 struct StringVisitor;
3542
3543 impl de::Visitor<'_> for StringVisitor {
3544 type Value = Length;
3545
3546 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
3547 write!(f, "{EXPECTED_LENGTH}")
3548 }
3549
3550 fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
3551 Length::try_from(value).map_err(E::custom)
3552 }
3553 }
3554
3555 deserializer.deserialize_str(StringVisitor)
3556 }
3557}
3558
3559impl Serialize for Length {
3560 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
3561 where
3562 S: Serializer,
3563 {
3564 serializer.serialize_str(&format!("{self}"))
3565 }
3566}
3567
3568/// Constructs a `DefiniteLength` representing a relative fraction of a parent size.
3569///
3570/// This function creates a `DefiniteLength` that is a specified fraction of a parent's dimension.
3571/// The fraction should be a floating-point number between 0.0 and 1.0, where 1.0 represents 100% of the parent's size.
3572///
3573/// # Arguments
3574///
3575/// * `fraction` - The fraction of the parent's size, between 0.0 and 1.0.
3576///
3577/// # Returns
3578///
3579/// A `DefiniteLength` representing the relative length as a fraction of the parent's size.
3580pub const fn relative(fraction: f32) -> DefiniteLength {
3581 DefiniteLength::Fraction(fraction)
3582}
3583
3584/// Returns the Golden Ratio, i.e. `~(1.0 + sqrt(5.0)) / 2.0`.
3585pub const fn phi() -> DefiniteLength {
3586 relative(1.618_034)
3587}
3588
3589/// Constructs a `Rems` value representing a length in rems.
3590///
3591/// # Arguments
3592///
3593/// * `rems` - The number of rems for the length.
3594///
3595/// # Returns
3596///
3597/// A `Rems` representing the specified number of rems.
3598pub const fn rems(rems: f32) -> Rems {
3599 Rems(rems)
3600}
3601
3602/// Constructs a `Pixels` value representing a length in pixels.
3603///
3604/// # Arguments
3605///
3606/// * `pixels` - The number of pixels for the length.
3607///
3608/// # Returns
3609///
3610/// A `Pixels` representing the specified number of pixels.
3611pub const fn px(pixels: f32) -> Pixels {
3612 Pixels(pixels)
3613}
3614
3615/// Returns a `Length` representing an automatic length.
3616///
3617/// The `auto` length is often used in layout calculations where the length should be determined
3618/// by the layout context itself rather than being explicitly set. This is commonly used in CSS
3619/// for properties like `width`, `height`, `margin`, `padding`, etc., where `auto` can be used
3620/// to instruct the layout engine to calculate the size based on other factors like the size of the
3621/// container or the intrinsic size of the content.
3622///
3623/// # Returns
3624///
3625/// A `Length` variant set to `Auto`.
3626pub const fn auto() -> Length {
3627 Length::Auto
3628}
3629
3630impl From<Pixels> for Length {
3631 fn from(pixels: Pixels) -> Self {
3632 Self::Definite(pixels.into())
3633 }
3634}
3635
3636impl From<Rems> for Length {
3637 fn from(rems: Rems) -> Self {
3638 Self::Definite(rems.into())
3639 }
3640}
3641
3642impl From<DefiniteLength> for Length {
3643 fn from(length: DefiniteLength) -> Self {
3644 Self::Definite(length)
3645 }
3646}
3647
3648impl From<AbsoluteLength> for Length {
3649 fn from(length: AbsoluteLength) -> Self {
3650 Self::Definite(length.into())
3651 }
3652}
3653
3654impl Default for Length {
3655 fn default() -> Self {
3656 Self::Definite(DefiniteLength::default())
3657 }
3658}
3659
3660impl From<()> for Length {
3661 fn from(_: ()) -> Self {
3662 Self::Definite(DefiniteLength::default())
3663 }
3664}
3665
3666/// A location in a grid layout.
3667#[derive(Clone, PartialEq, Debug, Serialize, Deserialize, JsonSchema, Default)]
3668pub struct GridLocation {
3669 /// The rows this item uses within the grid.
3670 pub row: Range<GridPlacement>,
3671 /// The columns this item uses within the grid.
3672 pub column: Range<GridPlacement>,
3673}
3674
3675/// The placement of an item within a grid layout's column or row.
3676#[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize, JsonSchema, Default)]
3677pub enum GridPlacement {
3678 /// The grid line index to place this item.
3679 Line(i16),
3680 /// The number of grid lines to span.
3681 Span(u16),
3682 /// Automatically determine the placement, equivalent to Span(1)
3683 #[default]
3684 Auto,
3685}
3686
3687impl From<GridPlacement> for taffy::GridPlacement {
3688 fn from(placement: GridPlacement) -> Self {
3689 match placement {
3690 GridPlacement::Line(index) => taffy::GridPlacement::from_line_index(index),
3691 GridPlacement::Span(span) => taffy::GridPlacement::from_span(span),
3692 GridPlacement::Auto => taffy::GridPlacement::Auto,
3693 }
3694 }
3695}
3696
3697/// Provides a trait for types that can calculate half of their value.
3698///
3699/// The `Half` trait is used for types that can be evenly divided, returning a new instance of the same type
3700/// representing half of the original value. This is commonly used for types that represent measurements or sizes,
3701/// such as lengths or pixels, where halving is a frequent operation during layout calculations or animations.
3702pub trait Half {
3703 /// Returns half of the current value.
3704 ///
3705 /// # Returns
3706 ///
3707 /// A new instance of the implementing type, representing half of the original value.
3708 fn half(&self) -> Self;
3709}
3710
3711impl Half for i32 {
3712 fn half(&self) -> Self {
3713 self / 2
3714 }
3715}
3716
3717impl Half for f32 {
3718 fn half(&self) -> Self {
3719 self / 2.
3720 }
3721}
3722
3723impl Half for DevicePixels {
3724 fn half(&self) -> Self {
3725 Self(self.0 / 2)
3726 }
3727}
3728
3729impl Half for ScaledPixels {
3730 fn half(&self) -> Self {
3731 Self(self.0 / 2.)
3732 }
3733}
3734
3735impl Half for Pixels {
3736 fn half(&self) -> Self {
3737 Self(self.0 / 2.)
3738 }
3739}
3740
3741impl Half for Rems {
3742 fn half(&self) -> Self {
3743 Self(self.0 / 2.)
3744 }
3745}
3746
3747/// Provides a trait for types that can negate their values.
3748pub trait Negate {
3749 /// Returns the negation of the given value
3750 fn negate(self) -> Self;
3751}
3752
3753impl Negate for i32 {
3754 fn negate(self) -> Self {
3755 -self
3756 }
3757}
3758
3759impl Negate for f32 {
3760 fn negate(self) -> Self {
3761 -self
3762 }
3763}
3764
3765impl Negate for DevicePixels {
3766 fn negate(self) -> Self {
3767 Self(-self.0)
3768 }
3769}
3770
3771impl Negate for ScaledPixels {
3772 fn negate(self) -> Self {
3773 Self(-self.0)
3774 }
3775}
3776
3777impl Negate for Pixels {
3778 fn negate(self) -> Self {
3779 Self(-self.0)
3780 }
3781}
3782
3783impl Negate for Rems {
3784 fn negate(self) -> Self {
3785 Self(-self.0)
3786 }
3787}
3788
3789/// A trait for checking if a value is zero.
3790///
3791/// This trait provides a method to determine if a value is considered to be zero.
3792/// It is implemented for various numeric and length-related types where the concept
3793/// of zero is applicable. This can be useful for comparisons, optimizations, or
3794/// determining if an operation has a neutral effect.
3795pub trait IsZero {
3796 /// Determines if the value is zero.
3797 ///
3798 /// # Returns
3799 ///
3800 /// Returns `true` if the value is zero, `false` otherwise.
3801 fn is_zero(&self) -> bool;
3802}
3803
3804impl IsZero for DevicePixels {
3805 fn is_zero(&self) -> bool {
3806 self.0 == 0
3807 }
3808}
3809
3810impl IsZero for ScaledPixels {
3811 fn is_zero(&self) -> bool {
3812 self.0 == 0.
3813 }
3814}
3815
3816impl IsZero for Pixels {
3817 fn is_zero(&self) -> bool {
3818 self.0 == 0.
3819 }
3820}
3821
3822impl IsZero for Rems {
3823 fn is_zero(&self) -> bool {
3824 self.0 == 0.
3825 }
3826}
3827
3828impl IsZero for AbsoluteLength {
3829 fn is_zero(&self) -> bool {
3830 match self {
3831 AbsoluteLength::Pixels(pixels) => pixels.is_zero(),
3832 AbsoluteLength::Rems(rems) => rems.is_zero(),
3833 }
3834 }
3835}
3836
3837impl IsZero for DefiniteLength {
3838 fn is_zero(&self) -> bool {
3839 match self {
3840 DefiniteLength::Absolute(length) => length.is_zero(),
3841 DefiniteLength::Fraction(fraction) => *fraction == 0.,
3842 }
3843 }
3844}
3845
3846impl IsZero for Length {
3847 fn is_zero(&self) -> bool {
3848 match self {
3849 Length::Definite(length) => length.is_zero(),
3850 Length::Auto => false,
3851 }
3852 }
3853}
3854
3855impl<T: IsZero + Clone + Debug + Default + PartialEq> IsZero for Point<T> {
3856 fn is_zero(&self) -> bool {
3857 self.x.is_zero() && self.y.is_zero()
3858 }
3859}
3860
3861impl<T> IsZero for Size<T>
3862where
3863 T: IsZero + Clone + Debug + Default + PartialEq,
3864{
3865 fn is_zero(&self) -> bool {
3866 self.width.is_zero() || self.height.is_zero()
3867 }
3868}
3869
3870impl<T: IsZero + Clone + Debug + Default + PartialEq> IsZero for Bounds<T> {
3871 fn is_zero(&self) -> bool {
3872 self.size.is_zero()
3873 }
3874}
3875
3876impl<T> IsZero for Corners<T>
3877where
3878 T: IsZero + Clone + Debug + Default + PartialEq,
3879{
3880 fn is_zero(&self) -> bool {
3881 self.top_left.is_zero()
3882 && self.top_right.is_zero()
3883 && self.bottom_right.is_zero()
3884 && self.bottom_left.is_zero()
3885 }
3886}
3887
3888#[cfg(test)]
3889mod tests {
3890 use super::*;
3891
3892 #[test]
3893 fn test_bounds_intersects() {
3894 let bounds1 = Bounds {
3895 origin: Point { x: 0.0, y: 0.0 },
3896 size: Size {
3897 width: 5.0,
3898 height: 5.0,
3899 },
3900 };
3901 let bounds2 = Bounds {
3902 origin: Point { x: 4.0, y: 4.0 },
3903 size: Size {
3904 width: 5.0,
3905 height: 5.0,
3906 },
3907 };
3908 let bounds3 = Bounds {
3909 origin: Point { x: 10.0, y: 10.0 },
3910 size: Size {
3911 width: 5.0,
3912 height: 5.0,
3913 },
3914 };
3915
3916 // Test Case 1: Intersecting bounds
3917 assert!(bounds1.intersects(&bounds2));
3918
3919 // Test Case 2: Non-Intersecting bounds
3920 assert!(!bounds1.intersects(&bounds3));
3921
3922 // Test Case 3: Bounds intersecting with themselves
3923 assert!(bounds1.intersects(&bounds1));
3924 }
3925}