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