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