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