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