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 true if at the center.
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
2220/// Represents the corners of a box in a 2D space, such as border radius.
2221///
2222/// Each field represents the size of the corner on one side of the box: `top_left`, `top_right`, `bottom_right`, and `bottom_left`.
2223#[derive(Refineable, Clone, Default, Debug, Eq, PartialEq)]
2224#[refineable(Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
2225#[repr(C)]
2226pub struct Corners<T: Clone + Debug + Default + PartialEq> {
2227 /// The value associated with the top left corner.
2228 pub top_left: T,
2229 /// The value associated with the top right corner.
2230 pub top_right: T,
2231 /// The value associated with the bottom right corner.
2232 pub bottom_right: T,
2233 /// The value associated with the bottom left corner.
2234 pub bottom_left: T,
2235}
2236
2237impl<T> Corners<T>
2238where
2239 T: Add<T, Output = T> + Half + Clone + Debug + Default + PartialEq,
2240{
2241 /// Constructs `Corners` where all sides are set to the same specified value.
2242 ///
2243 /// This function creates a `Corners` instance with the `top_left`, `top_right`, `bottom_right`, and `bottom_left` fields all initialized
2244 /// to the same value provided as an argument. This is useful when you want to have uniform corners around a box,
2245 /// such as a uniform border radius on a rectangle.
2246 ///
2247 /// # Arguments
2248 ///
2249 /// * `value` - The value to set for all four corners.
2250 ///
2251 /// # Returns
2252 ///
2253 /// An `Corners` instance with all corners set to the given value.
2254 ///
2255 /// # Examples
2256 ///
2257 /// ```
2258 /// # use gpui::Corners;
2259 /// let uniform_corners = Corners::all(5.0);
2260 /// assert_eq!(uniform_corners.top_left, 5.0);
2261 /// assert_eq!(uniform_corners.top_right, 5.0);
2262 /// assert_eq!(uniform_corners.bottom_right, 5.0);
2263 /// assert_eq!(uniform_corners.bottom_left, 5.0);
2264 /// ```
2265 pub fn all(value: T) -> Self {
2266 Self {
2267 top_left: value.clone(),
2268 top_right: value.clone(),
2269 bottom_right: value.clone(),
2270 bottom_left: value,
2271 }
2272 }
2273
2274 /// Returns the requested corner value, supporting all eight corner positions.
2275 ///
2276 /// For the four basic corners (TopLeft, TopRight, BottomLeft, BottomRight),
2277 /// this returns the corresponding field value directly.
2278 ///
2279 /// For the center positions (TopCenter, BottomCenter, LeftCenter, RightCenter),
2280 /// this calculates the average of the two adjacent corners.
2281 ///
2282 /// # Returns
2283 ///
2284 /// A value of type `T` representing the corner requested by the parameter.
2285 ///
2286 /// # Examples
2287 ///
2288 /// Basic corner positions:
2289 ///
2290 /// ```
2291 /// # use gpui::{Anchor, Corners};
2292 /// let corners = Corners {
2293 /// top_left: 10,
2294 /// top_right: 20,
2295 /// bottom_left: 30,
2296 /// bottom_right: 40
2297 /// };
2298 /// assert_eq!(corners.corner(Anchor::TopLeft), 10);
2299 /// assert_eq!(corners.corner(Anchor::BottomRight), 40);
2300 /// ```
2301 ///
2302 /// Center positions (calculated as average of adjacent corners):
2303 ///
2304 /// ```
2305 /// # use gpui::{Anchor, Corners};
2306 /// let corners = Corners {
2307 /// top_left: 10,
2308 /// top_right: 20,
2309 /// bottom_left: 30,
2310 /// bottom_right: 40
2311 /// };
2312 /// assert_eq!(corners.corner(Anchor::TopCenter), 15);
2313 /// assert_eq!(corners.corner(Anchor::BottomCenter), 35);
2314 /// assert_eq!(corners.corner(Anchor::LeftCenter), 20);
2315 /// assert_eq!(corners.corner(Anchor::RightCenter), 30);
2316 /// ```
2317 #[must_use]
2318 pub fn corner(&self, corner: Anchor) -> T {
2319 match corner {
2320 Anchor::TopLeft => self.top_left.clone(),
2321 Anchor::TopRight => self.top_right.clone(),
2322 Anchor::BottomLeft => self.bottom_left.clone(),
2323 Anchor::BottomRight => self.bottom_right.clone(),
2324 Anchor::TopCenter => (self.top_left.clone() + self.top_right.clone()).half(),
2325 Anchor::BottomCenter => (self.bottom_left.clone() + self.bottom_right.clone()).half(),
2326 Anchor::LeftCenter => (self.top_left.clone() + self.bottom_left.clone()).half(),
2327 Anchor::RightCenter => (self.top_right.clone() + self.bottom_right.clone()).half(),
2328 }
2329 }
2330}
2331
2332impl Corners<AbsoluteLength> {
2333 /// Converts the `AbsoluteLength` to `Pixels` based on the provided rem size.
2334 ///
2335 /// # Arguments
2336 ///
2337 /// * `rem_size` - The size of one REM unit in pixels, used for conversion if the `AbsoluteLength` is in REMs.
2338 ///
2339 /// # Returns
2340 ///
2341 /// Returns a `Corners<Pixels>` instance with each corner's length converted to pixels.
2342 ///
2343 /// # Examples
2344 ///
2345 /// ```
2346 /// # use gpui::{Corners, AbsoluteLength, Pixels, Rems, Size};
2347 /// let corners = Corners {
2348 /// top_left: AbsoluteLength::Pixels(Pixels::from(15.0)),
2349 /// top_right: AbsoluteLength::Rems(Rems(1.0)),
2350 /// bottom_right: AbsoluteLength::Pixels(Pixels::from(30.0)),
2351 /// bottom_left: AbsoluteLength::Rems(Rems(2.0)),
2352 /// };
2353 /// let rem_size = Pixels::from(16.0);
2354 /// let corners_in_pixels = corners.to_pixels(rem_size);
2355 ///
2356 /// assert_eq!(corners_in_pixels.top_left, Pixels::from(15.0));
2357 /// assert_eq!(corners_in_pixels.top_right, Pixels::from(16.0)); // 1 rem converted to pixels
2358 /// assert_eq!(corners_in_pixels.bottom_right, Pixels::from(30.0));
2359 /// assert_eq!(corners_in_pixels.bottom_left, Pixels::from(32.0)); // 2 rems converted to pixels
2360 /// ```
2361 pub fn to_pixels(self, rem_size: Pixels) -> Corners<Pixels> {
2362 Corners {
2363 top_left: self.top_left.to_pixels(rem_size),
2364 top_right: self.top_right.to_pixels(rem_size),
2365 bottom_right: self.bottom_right.to_pixels(rem_size),
2366 bottom_left: self.bottom_left.to_pixels(rem_size),
2367 }
2368 }
2369}
2370
2371impl Corners<Pixels> {
2372 /// Scales the `Corners<Pixels>` by a given factor, returning `Corners<ScaledPixels>`.
2373 ///
2374 /// This method is typically used for adjusting the corner sizes for different display densities or scaling factors.
2375 ///
2376 /// # Arguments
2377 ///
2378 /// * `factor` - The scaling factor to apply to each corner.
2379 ///
2380 /// # Returns
2381 ///
2382 /// Returns a new `Corners<ScaledPixels>` where each corner is the result of scaling the original corner by the given factor.
2383 ///
2384 /// # Examples
2385 ///
2386 /// ```
2387 /// # use gpui::{Corners, Pixels, ScaledPixels};
2388 /// let corners = Corners {
2389 /// top_left: Pixels::from(10.0),
2390 /// top_right: Pixels::from(20.0),
2391 /// bottom_right: Pixels::from(30.0),
2392 /// bottom_left: Pixels::from(40.0),
2393 /// };
2394 /// let scaled_corners = corners.scale(2.0);
2395 /// assert_eq!(scaled_corners.top_left, ScaledPixels::from(20.0));
2396 /// assert_eq!(scaled_corners.top_right, ScaledPixels::from(40.0));
2397 /// assert_eq!(scaled_corners.bottom_right, ScaledPixels::from(60.0));
2398 /// assert_eq!(scaled_corners.bottom_left, ScaledPixels::from(80.0));
2399 /// ```
2400 #[must_use]
2401 pub fn scale(&self, factor: f32) -> Corners<ScaledPixels> {
2402 Corners {
2403 top_left: self.top_left.scale(factor),
2404 top_right: self.top_right.scale(factor),
2405 bottom_right: self.bottom_right.scale(factor),
2406 bottom_left: self.bottom_left.scale(factor),
2407 }
2408 }
2409
2410 /// Returns the maximum value of any corner.
2411 ///
2412 /// # Returns
2413 ///
2414 /// The maximum `Pixels` value among all four corners.
2415 #[must_use]
2416 pub fn max(&self) -> Pixels {
2417 self.top_left
2418 .max(self.top_right)
2419 .max(self.bottom_right)
2420 .max(self.bottom_left)
2421 }
2422}
2423
2424impl<T: Div<f32, Output = T> + Ord + Clone + Debug + Default + PartialEq> Corners<T> {
2425 /// Clamps corner radii to be less than or equal to half the shortest side of a quad.
2426 ///
2427 /// # Arguments
2428 ///
2429 /// * `size` - The size of the quad which limits the size of the corner radii.
2430 ///
2431 /// # Returns
2432 ///
2433 /// Anchor radii values clamped to fit.
2434 #[must_use]
2435 pub fn clamp_radii_for_quad_size(self, size: Size<T>) -> Corners<T> {
2436 let max = cmp::min(size.width, size.height) / 2.;
2437 Corners {
2438 top_left: cmp::min(self.top_left, max.clone()),
2439 top_right: cmp::min(self.top_right, max.clone()),
2440 bottom_right: cmp::min(self.bottom_right, max.clone()),
2441 bottom_left: cmp::min(self.bottom_left, max),
2442 }
2443 }
2444}
2445
2446impl<T: Clone + Debug + Default + PartialEq> Corners<T> {
2447 /// Applies a function to each field of the `Corners`, producing a new `Corners<U>`.
2448 ///
2449 /// This method allows for converting a `Corners<T>` to a `Corners<U>` by specifying a closure
2450 /// that defines how to convert between the two types. The closure is applied to each field
2451 /// (`top_left`, `top_right`, `bottom_right`, `bottom_left`), resulting in new corners of the desired type.
2452 ///
2453 /// # Arguments
2454 ///
2455 /// * `f` - A closure that takes a reference to a value of type `T` and returns a value of type `U`.
2456 ///
2457 /// # Returns
2458 ///
2459 /// Returns a new `Corners<U>` with each field mapped by the provided function.
2460 ///
2461 /// # Examples
2462 ///
2463 /// ```
2464 /// # use gpui::{Corners, Pixels, Rems};
2465 /// let corners = Corners {
2466 /// top_left: Pixels::from(10.0),
2467 /// top_right: Pixels::from(20.0),
2468 /// bottom_right: Pixels::from(30.0),
2469 /// bottom_left: Pixels::from(40.0),
2470 /// };
2471 /// let corners_in_rems = corners.map(|&px| Rems(f32::from(px) / 16.0));
2472 /// assert_eq!(corners_in_rems, Corners {
2473 /// top_left: Rems(0.625),
2474 /// top_right: Rems(1.25),
2475 /// bottom_right: Rems(1.875),
2476 /// bottom_left: Rems(2.5),
2477 /// });
2478 /// ```
2479 #[must_use]
2480 pub fn map<U>(&self, f: impl Fn(&T) -> U) -> Corners<U>
2481 where
2482 U: Clone + Debug + Default + PartialEq,
2483 {
2484 Corners {
2485 top_left: f(&self.top_left),
2486 top_right: f(&self.top_right),
2487 bottom_right: f(&self.bottom_right),
2488 bottom_left: f(&self.bottom_left),
2489 }
2490 }
2491}
2492
2493impl<T> Mul for Corners<T>
2494where
2495 T: Mul<Output = T> + Clone + Debug + Default + PartialEq,
2496{
2497 type Output = Self;
2498
2499 fn mul(self, rhs: Self) -> Self::Output {
2500 Self {
2501 top_left: self.top_left.clone() * rhs.top_left,
2502 top_right: self.top_right.clone() * rhs.top_right,
2503 bottom_right: self.bottom_right.clone() * rhs.bottom_right,
2504 bottom_left: self.bottom_left * rhs.bottom_left,
2505 }
2506 }
2507}
2508
2509impl<T, S> MulAssign<S> for Corners<T>
2510where
2511 T: Mul<S, Output = T> + Clone + Debug + Default + PartialEq,
2512 S: Clone,
2513{
2514 fn mul_assign(&mut self, rhs: S) {
2515 self.top_left = self.top_left.clone() * rhs.clone();
2516 self.top_right = self.top_right.clone() * rhs.clone();
2517 self.bottom_right = self.bottom_right.clone() * rhs.clone();
2518 self.bottom_left = self.bottom_left.clone() * rhs;
2519 }
2520}
2521
2522impl<T> Copy for Corners<T> where T: Copy + Clone + Debug + Default + PartialEq {}
2523
2524impl From<f32> for Corners<Pixels> {
2525 fn from(val: f32) -> Self {
2526 Corners {
2527 top_left: val.into(),
2528 top_right: val.into(),
2529 bottom_right: val.into(),
2530 bottom_left: val.into(),
2531 }
2532 }
2533}
2534
2535impl From<Pixels> for Corners<Pixels> {
2536 fn from(val: Pixels) -> Self {
2537 Corners {
2538 top_left: val,
2539 top_right: val,
2540 bottom_right: val,
2541 bottom_left: val,
2542 }
2543 }
2544}
2545
2546/// Represents an angle in Radians
2547#[derive(
2548 Clone,
2549 Copy,
2550 Default,
2551 Add,
2552 AddAssign,
2553 Sub,
2554 SubAssign,
2555 Neg,
2556 Div,
2557 DivAssign,
2558 PartialEq,
2559 Serialize,
2560 Deserialize,
2561 Debug,
2562)]
2563#[repr(transparent)]
2564pub struct Radians(pub f32);
2565
2566/// Create a `Radian` from a raw value
2567pub fn radians(value: f32) -> Radians {
2568 Radians(value)
2569}
2570
2571/// A type representing a percentage value.
2572#[derive(
2573 Clone,
2574 Copy,
2575 Default,
2576 Add,
2577 AddAssign,
2578 Sub,
2579 SubAssign,
2580 Neg,
2581 Div,
2582 DivAssign,
2583 PartialEq,
2584 Serialize,
2585 Deserialize,
2586 Debug,
2587)]
2588#[repr(transparent)]
2589pub struct Percentage(pub f32);
2590
2591/// Generate a `Radian` from a percentage of a full circle.
2592pub fn percentage(value: f32) -> Percentage {
2593 debug_assert!(
2594 (0.0..=1.0).contains(&value),
2595 "Percentage must be between 0 and 1"
2596 );
2597 Percentage(value)
2598}
2599
2600impl From<Percentage> for Radians {
2601 fn from(value: Percentage) -> Self {
2602 radians(value.0 * std::f32::consts::PI * 2.0)
2603 }
2604}
2605
2606/// Represents a length in pixels, the base unit of measurement in the UI framework.
2607///
2608/// `Pixels` is a value type that represents an absolute length in pixels, which is used
2609/// for specifying sizes, positions, and distances in the UI. It is the fundamental unit
2610/// of measurement for all visual elements and layout calculations.
2611///
2612/// The inner value is an `f32`, allowing for sub-pixel precision which can be useful for
2613/// anti-aliasing and animations. However, when applied to actual pixel grids, the value
2614/// is typically rounded to the nearest integer.
2615///
2616/// # Examples
2617///
2618/// ```
2619/// use gpui::{Pixels, ScaledPixels};
2620///
2621/// // Define a length of 10 pixels
2622/// let length = Pixels::from(10.0);
2623///
2624/// // Define a length and scale it by a factor of 2
2625/// let scaled_length = length.scale(2.0);
2626/// assert_eq!(scaled_length, ScaledPixels::from(20.0));
2627/// ```
2628#[derive(
2629 Clone,
2630 Copy,
2631 Default,
2632 Add,
2633 AddAssign,
2634 Sub,
2635 SubAssign,
2636 Neg,
2637 Div,
2638 DivAssign,
2639 PartialEq,
2640 Serialize,
2641 Deserialize,
2642 JsonSchema,
2643)]
2644#[repr(transparent)]
2645pub struct Pixels(
2646 /// The raw pixel value.
2647 pub f32,
2648);
2649
2650impl Div for Pixels {
2651 type Output = f32;
2652
2653 fn div(self, rhs: Self) -> Self::Output {
2654 self.0 / rhs.0
2655 }
2656}
2657
2658impl std::ops::DivAssign for Pixels {
2659 fn div_assign(&mut self, rhs: Self) {
2660 *self = Self(self.0 / rhs.0);
2661 }
2662}
2663
2664impl std::ops::RemAssign for Pixels {
2665 fn rem_assign(&mut self, rhs: Self) {
2666 self.0 %= rhs.0;
2667 }
2668}
2669
2670impl std::ops::Rem for Pixels {
2671 type Output = Self;
2672
2673 fn rem(self, rhs: Self) -> Self {
2674 Self(self.0 % rhs.0)
2675 }
2676}
2677
2678impl Mul<f32> for Pixels {
2679 type Output = Self;
2680
2681 fn mul(self, rhs: f32) -> Self {
2682 Self(self.0 * rhs)
2683 }
2684}
2685
2686impl Mul<Pixels> for f32 {
2687 type Output = Pixels;
2688
2689 fn mul(self, rhs: Pixels) -> Self::Output {
2690 rhs * self
2691 }
2692}
2693
2694impl Mul<usize> for Pixels {
2695 type Output = Self;
2696
2697 fn mul(self, rhs: usize) -> Self {
2698 self * (rhs as f32)
2699 }
2700}
2701
2702impl Mul<Pixels> for usize {
2703 type Output = Pixels;
2704
2705 fn mul(self, rhs: Pixels) -> Pixels {
2706 rhs * self
2707 }
2708}
2709
2710impl MulAssign<f32> for Pixels {
2711 fn mul_assign(&mut self, rhs: f32) {
2712 self.0 *= rhs;
2713 }
2714}
2715
2716impl Display for Pixels {
2717 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2718 write!(f, "{}px", self.0)
2719 }
2720}
2721
2722impl Debug for Pixels {
2723 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2724 Display::fmt(self, f)
2725 }
2726}
2727
2728impl std::iter::Sum for Pixels {
2729 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
2730 iter.fold(Self::ZERO, |a, b| a + b)
2731 }
2732}
2733
2734impl<'a> std::iter::Sum<&'a Pixels> for Pixels {
2735 fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
2736 iter.fold(Self::ZERO, |a, b| a + *b)
2737 }
2738}
2739
2740impl TryFrom<&'_ str> for Pixels {
2741 type Error = anyhow::Error;
2742
2743 fn try_from(value: &'_ str) -> Result<Self, Self::Error> {
2744 value
2745 .strip_suffix("px")
2746 .context("expected 'px' suffix")
2747 .and_then(|number| Ok(number.parse()?))
2748 .map(Self)
2749 }
2750}
2751
2752impl Pixels {
2753 /// Represents zero pixels.
2754 pub const ZERO: Pixels = Pixels(0.0);
2755 /// The maximum value that can be represented by `Pixels`.
2756 pub const MAX: Pixels = Pixels(f32::MAX);
2757 /// The minimum value that can be represented by `Pixels`.
2758 pub const MIN: Pixels = Pixels(f32::MIN);
2759
2760 /// Returns the raw `f32` value of this `Pixels`.
2761 pub fn as_f32(self) -> f32 {
2762 self.0
2763 }
2764
2765 /// Floors the `Pixels` value to the nearest whole number.
2766 ///
2767 /// # Returns
2768 ///
2769 /// Returns a new `Pixels` instance with the floored value.
2770 pub fn floor(&self) -> Self {
2771 Self(self.0.floor())
2772 }
2773
2774 /// Rounds the `Pixels` value to the nearest whole number.
2775 ///
2776 /// # Returns
2777 ///
2778 /// Returns a new `Pixels` instance with the rounded value.
2779 pub fn round(&self) -> Self {
2780 Self(self.0.round())
2781 }
2782
2783 /// Returns the ceiling of the `Pixels` value to the nearest whole number.
2784 ///
2785 /// # Returns
2786 ///
2787 /// Returns a new `Pixels` instance with the ceiling value.
2788 pub fn ceil(&self) -> Self {
2789 Self(self.0.ceil())
2790 }
2791
2792 /// Scales the `Pixels` value by a given factor, producing `ScaledPixels`.
2793 ///
2794 /// This method is used when adjusting pixel values for display scaling factors,
2795 /// such as high DPI (dots per inch) or Retina displays, where the pixel density is higher and
2796 /// thus requires scaling to maintain visual consistency and readability.
2797 ///
2798 /// The resulting `ScaledPixels` represent the scaled value which can be used for rendering
2799 /// calculations where display scaling is considered.
2800 #[must_use]
2801 pub fn scale(&self, factor: f32) -> ScaledPixels {
2802 ScaledPixels(self.0 * factor)
2803 }
2804
2805 /// Raises the `Pixels` value to a given power.
2806 ///
2807 /// # Arguments
2808 ///
2809 /// * `exponent` - The exponent to raise the `Pixels` value by.
2810 ///
2811 /// # Returns
2812 ///
2813 /// Returns a new `Pixels` instance with the value raised to the given exponent.
2814 pub fn pow(&self, exponent: f32) -> Self {
2815 Self(self.0.powf(exponent))
2816 }
2817
2818 /// Returns the absolute value of the `Pixels`.
2819 ///
2820 /// # Returns
2821 ///
2822 /// A new `Pixels` instance with the absolute value of the original `Pixels`.
2823 pub fn abs(&self) -> Self {
2824 Self(self.0.abs())
2825 }
2826
2827 /// Returns the sign of the `Pixels` value.
2828 ///
2829 /// # Returns
2830 ///
2831 /// Returns:
2832 /// * `1.0` if the value is positive
2833 /// * `-1.0` if the value is negative
2834 pub fn signum(&self) -> f32 {
2835 self.0.signum()
2836 }
2837
2838 /// Returns the f64 value of `Pixels`.
2839 ///
2840 /// # Returns
2841 ///
2842 /// A f64 value of the `Pixels`.
2843 pub fn to_f64(self) -> f64 {
2844 self.0 as f64
2845 }
2846}
2847
2848impl Eq for Pixels {}
2849
2850impl PartialOrd for Pixels {
2851 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
2852 Some(self.cmp(other))
2853 }
2854}
2855
2856impl Ord for Pixels {
2857 fn cmp(&self, other: &Self) -> cmp::Ordering {
2858 self.0.total_cmp(&other.0)
2859 }
2860}
2861
2862impl std::hash::Hash for Pixels {
2863 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2864 self.0.to_bits().hash(state);
2865 }
2866}
2867
2868impl From<f64> for Pixels {
2869 fn from(pixels: f64) -> Self {
2870 Pixels(pixels as f32)
2871 }
2872}
2873
2874impl From<f32> for Pixels {
2875 fn from(pixels: f32) -> Self {
2876 Pixels(pixels)
2877 }
2878}
2879
2880impl From<Pixels> for f32 {
2881 fn from(pixels: Pixels) -> Self {
2882 pixels.0
2883 }
2884}
2885
2886impl From<&Pixels> for f32 {
2887 fn from(pixels: &Pixels) -> Self {
2888 pixels.0
2889 }
2890}
2891
2892impl From<Pixels> for f64 {
2893 fn from(pixels: Pixels) -> Self {
2894 pixels.0 as f64
2895 }
2896}
2897
2898impl From<Pixels> for u32 {
2899 fn from(pixels: Pixels) -> Self {
2900 pixels.0 as u32
2901 }
2902}
2903
2904impl From<&Pixels> for u32 {
2905 fn from(pixels: &Pixels) -> Self {
2906 pixels.0 as u32
2907 }
2908}
2909
2910impl From<u32> for Pixels {
2911 fn from(pixels: u32) -> Self {
2912 Pixels(pixels as f32)
2913 }
2914}
2915
2916impl From<Pixels> for usize {
2917 fn from(pixels: Pixels) -> Self {
2918 pixels.0 as usize
2919 }
2920}
2921
2922impl From<usize> for Pixels {
2923 fn from(pixels: usize) -> Self {
2924 Pixels(pixels as f32)
2925 }
2926}
2927
2928/// Represents physical pixels on the display.
2929///
2930/// `DevicePixels` is a unit of measurement that refers to the actual pixels on a device's screen.
2931/// This type is used when precise pixel manipulation is required, such as rendering graphics or
2932/// interfacing with hardware that operates on the pixel level. Unlike logical pixels that may be
2933/// affected by the device's scale factor, `DevicePixels` always correspond to real pixels on the
2934/// display.
2935#[derive(
2936 Add,
2937 AddAssign,
2938 Clone,
2939 Copy,
2940 Default,
2941 Div,
2942 Eq,
2943 Hash,
2944 Ord,
2945 PartialEq,
2946 PartialOrd,
2947 Sub,
2948 SubAssign,
2949 Serialize,
2950 Deserialize,
2951)]
2952#[repr(transparent)]
2953pub struct DevicePixels(pub i32);
2954
2955impl DevicePixels {
2956 /// Converts the `DevicePixels` value to the number of bytes needed to represent it in memory.
2957 ///
2958 /// This function is useful when working with graphical data that needs to be stored in a buffer,
2959 /// such as images or framebuffers, where each pixel may be represented by a specific number of bytes.
2960 ///
2961 /// # Arguments
2962 ///
2963 /// * `bytes_per_pixel` - The number of bytes used to represent a single pixel.
2964 ///
2965 /// # Returns
2966 ///
2967 /// The number of bytes required to represent the `DevicePixels` value in memory.
2968 ///
2969 /// # Examples
2970 ///
2971 /// ```
2972 /// # use gpui::DevicePixels;
2973 /// let pixels = DevicePixels(10); // 10 device pixels
2974 /// let bytes_per_pixel = 4; // Assume each pixel is represented by 4 bytes (e.g., RGBA)
2975 /// let total_bytes = pixels.to_bytes(bytes_per_pixel);
2976 /// assert_eq!(total_bytes, 40); // 10 pixels * 4 bytes/pixel = 40 bytes
2977 /// ```
2978 pub fn to_bytes(self, bytes_per_pixel: u8) -> u32 {
2979 self.0 as u32 * bytes_per_pixel as u32
2980 }
2981}
2982
2983impl fmt::Debug for DevicePixels {
2984 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2985 write!(f, "{} px (device)", self.0)
2986 }
2987}
2988
2989impl From<DevicePixels> for i32 {
2990 fn from(device_pixels: DevicePixels) -> Self {
2991 device_pixels.0
2992 }
2993}
2994
2995impl From<i32> for DevicePixels {
2996 fn from(device_pixels: i32) -> Self {
2997 DevicePixels(device_pixels)
2998 }
2999}
3000
3001impl From<u32> for DevicePixels {
3002 fn from(device_pixels: u32) -> Self {
3003 DevicePixels(device_pixels as i32)
3004 }
3005}
3006
3007impl From<DevicePixels> for u32 {
3008 fn from(device_pixels: DevicePixels) -> Self {
3009 device_pixels.0 as u32
3010 }
3011}
3012
3013impl From<DevicePixels> for u64 {
3014 fn from(device_pixels: DevicePixels) -> Self {
3015 device_pixels.0 as u64
3016 }
3017}
3018
3019impl From<u64> for DevicePixels {
3020 fn from(device_pixels: u64) -> Self {
3021 DevicePixels(device_pixels as i32)
3022 }
3023}
3024
3025impl From<DevicePixels> for usize {
3026 fn from(device_pixels: DevicePixels) -> Self {
3027 device_pixels.0 as usize
3028 }
3029}
3030
3031impl From<usize> for DevicePixels {
3032 fn from(device_pixels: usize) -> Self {
3033 DevicePixels(device_pixels as i32)
3034 }
3035}
3036
3037/// Represents scaled pixels that take into account the device's scale factor.
3038///
3039/// `ScaledPixels` are used to ensure that UI elements appear at the correct size on devices
3040/// with different pixel densities. When a device has a higher scale factor (such as Retina displays),
3041/// a single logical pixel may correspond to multiple physical pixels. By using `ScaledPixels`,
3042/// dimensions and positions can be specified in a way that scales appropriately across different
3043/// display resolutions.
3044#[derive(Clone, Copy, Default, Add, AddAssign, Sub, SubAssign, Div, DivAssign, PartialEq)]
3045#[repr(transparent)]
3046pub struct ScaledPixels(pub f32);
3047
3048impl ScaledPixels {
3049 /// Returns the raw `f32` value of this `ScaledPixels`.
3050 pub fn as_f32(self) -> f32 {
3051 self.0
3052 }
3053
3054 /// Floors the `ScaledPixels` value to the nearest whole number.
3055 ///
3056 /// # Returns
3057 ///
3058 /// Returns a new `ScaledPixels` instance with the floored value.
3059 pub fn floor(&self) -> Self {
3060 Self(self.0.floor())
3061 }
3062
3063 /// Rounds the `ScaledPixels` value to the nearest whole number.
3064 ///
3065 /// # Returns
3066 ///
3067 /// Returns a new `ScaledPixels` instance with the rounded value.
3068 pub fn round(&self) -> Self {
3069 Self(self.0.round())
3070 }
3071
3072 /// Ceils the `ScaledPixels` value to the nearest whole number.
3073 ///
3074 /// # Returns
3075 ///
3076 /// Returns a new `ScaledPixels` instance with the ceiled value.
3077 pub fn ceil(&self) -> Self {
3078 Self(self.0.ceil())
3079 }
3080}
3081
3082impl Eq for ScaledPixels {}
3083
3084impl PartialOrd for ScaledPixels {
3085 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
3086 Some(self.cmp(other))
3087 }
3088}
3089
3090impl Ord for ScaledPixels {
3091 fn cmp(&self, other: &Self) -> cmp::Ordering {
3092 self.0.total_cmp(&other.0)
3093 }
3094}
3095
3096impl Debug for ScaledPixels {
3097 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3098 write!(f, "{}px (scaled)", self.0)
3099 }
3100}
3101
3102impl From<ScaledPixels> for DevicePixels {
3103 fn from(scaled: ScaledPixels) -> Self {
3104 DevicePixels(scaled.0.ceil() as i32)
3105 }
3106}
3107
3108impl From<DevicePixels> for ScaledPixels {
3109 fn from(device: DevicePixels) -> Self {
3110 ScaledPixels(device.0 as f32)
3111 }
3112}
3113
3114impl From<ScaledPixels> for f64 {
3115 fn from(scaled_pixels: ScaledPixels) -> Self {
3116 scaled_pixels.0 as f64
3117 }
3118}
3119
3120impl From<ScaledPixels> for u32 {
3121 fn from(pixels: ScaledPixels) -> Self {
3122 pixels.0 as u32
3123 }
3124}
3125
3126impl From<f32> for ScaledPixels {
3127 fn from(pixels: f32) -> Self {
3128 Self(pixels)
3129 }
3130}
3131
3132impl Div for ScaledPixels {
3133 type Output = f32;
3134
3135 fn div(self, rhs: Self) -> Self::Output {
3136 self.0 / rhs.0
3137 }
3138}
3139
3140impl std::ops::DivAssign for ScaledPixels {
3141 fn div_assign(&mut self, rhs: Self) {
3142 *self = Self(self.0 / rhs.0);
3143 }
3144}
3145
3146impl std::ops::RemAssign for ScaledPixels {
3147 fn rem_assign(&mut self, rhs: Self) {
3148 self.0 %= rhs.0;
3149 }
3150}
3151
3152impl std::ops::Rem for ScaledPixels {
3153 type Output = Self;
3154
3155 fn rem(self, rhs: Self) -> Self {
3156 Self(self.0 % rhs.0)
3157 }
3158}
3159
3160impl Mul<f32> for ScaledPixels {
3161 type Output = Self;
3162
3163 fn mul(self, rhs: f32) -> Self {
3164 Self(self.0 * rhs)
3165 }
3166}
3167
3168impl Mul<ScaledPixels> for f32 {
3169 type Output = ScaledPixels;
3170
3171 fn mul(self, rhs: ScaledPixels) -> Self::Output {
3172 rhs * self
3173 }
3174}
3175
3176impl Mul<usize> for ScaledPixels {
3177 type Output = Self;
3178
3179 fn mul(self, rhs: usize) -> Self {
3180 self * (rhs as f32)
3181 }
3182}
3183
3184impl Mul<ScaledPixels> for usize {
3185 type Output = ScaledPixels;
3186
3187 fn mul(self, rhs: ScaledPixels) -> ScaledPixels {
3188 rhs * self
3189 }
3190}
3191
3192impl MulAssign<f32> for ScaledPixels {
3193 fn mul_assign(&mut self, rhs: f32) {
3194 self.0 *= rhs;
3195 }
3196}
3197
3198/// Represents a length in rems, a unit based on the font-size of the window, which can be assigned with `Window::set_rem_size`.
3199///
3200/// Rems are used for defining lengths that are scalable and consistent across different UI elements.
3201/// The value of `1rem` is typically equal to the font-size of the root element (often the `<html>` element in browsers),
3202/// making it a flexible unit that adapts to the user's text size preferences. In this framework, `rems` serve a similar
3203/// purpose, allowing for scalable and accessible design that can adjust to different display settings or user preferences.
3204///
3205/// For example, if the root element's font-size is `16px`, then `1rem` equals `16px`. A length of `2rems` would then be `32px`.
3206#[derive(Clone, Copy, Default, Add, Sub, Mul, Div, Neg, PartialEq)]
3207pub struct Rems(pub f32);
3208
3209/// A source of the current rem size, used to convert [`Pixels`] to [`Rems`].
3210///
3211/// Implementing this for the window type lets [`Rems::from_pixels`] live in this
3212/// crate without depending on the rest of GPUI.
3213pub trait HasRemSize {
3214 /// The size of one rem, in pixels.
3215 fn rem_size(&self) -> Pixels;
3216}
3217
3218impl Rems {
3219 /// A length of zero.
3220 pub const ZERO: Self = Self(0.0);
3221 /// Convert this Rem value to pixels.
3222 pub fn to_pixels(self, rem_size: Pixels) -> Pixels {
3223 self * rem_size
3224 }
3225 /// Convert from pixels to Rem, using the rem size reported by `source`.
3226 pub fn from_pixels(length: Pixels, source: &impl HasRemSize) -> Self {
3227 Self(length / source.rem_size())
3228 }
3229}
3230
3231impl Mul<Pixels> for Rems {
3232 type Output = Pixels;
3233
3234 fn mul(self, other: Pixels) -> Pixels {
3235 Pixels(self.0 * other.0)
3236 }
3237}
3238
3239impl AddAssign<Rems> for Rems {
3240 fn add_assign(&mut self, rhs: Rems) {
3241 self.0 += rhs.0
3242 }
3243}
3244
3245impl Display for Rems {
3246 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3247 write!(f, "{}rem", self.0)
3248 }
3249}
3250
3251impl Debug for Rems {
3252 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3253 Display::fmt(self, f)
3254 }
3255}
3256
3257impl TryFrom<&'_ str> for Rems {
3258 type Error = anyhow::Error;
3259
3260 fn try_from(value: &'_ str) -> Result<Self, Self::Error> {
3261 value
3262 .strip_suffix("rem")
3263 .context("expected 'rem' suffix")
3264 .and_then(|number| Ok(number.parse()?))
3265 .map(Self)
3266 }
3267}
3268
3269/// Represents an absolute length in pixels or rems.
3270///
3271/// `AbsoluteLength` can be either a fixed number of pixels, which is an absolute measurement not
3272/// affected by the current font size, or a number of rems, which is relative to the font size of
3273/// the root element. It is used for specifying dimensions that are either independent of or
3274/// related to the typographic scale.
3275#[derive(Clone, Copy, Neg, PartialEq)]
3276pub enum AbsoluteLength {
3277 /// A length in pixels.
3278 Pixels(Pixels),
3279 /// A length in rems.
3280 Rems(Rems),
3281}
3282
3283impl AbsoluteLength {
3284 /// Checks if the absolute length is zero.
3285 pub fn is_zero(&self) -> bool {
3286 match self {
3287 AbsoluteLength::Pixels(px) => px.0 == 0.0,
3288 AbsoluteLength::Rems(rems) => rems.0 == 0.0,
3289 }
3290 }
3291}
3292
3293impl From<Pixels> for AbsoluteLength {
3294 fn from(pixels: Pixels) -> Self {
3295 AbsoluteLength::Pixels(pixels)
3296 }
3297}
3298
3299impl From<Rems> for AbsoluteLength {
3300 fn from(rems: Rems) -> Self {
3301 AbsoluteLength::Rems(rems)
3302 }
3303}
3304
3305impl AbsoluteLength {
3306 /// Converts an `AbsoluteLength` to `Pixels` based on a given `rem_size`.
3307 ///
3308 /// # Arguments
3309 ///
3310 /// * `rem_size` - The size of one rem in pixels.
3311 ///
3312 /// # Returns
3313 ///
3314 /// Returns the `AbsoluteLength` as `Pixels`.
3315 ///
3316 /// # Examples
3317 ///
3318 /// ```
3319 /// # use gpui::{AbsoluteLength, Pixels, Rems};
3320 /// let length_in_pixels = AbsoluteLength::Pixels(Pixels::from(42.0));
3321 /// let length_in_rems = AbsoluteLength::Rems(Rems(2.0));
3322 /// let rem_size = Pixels::from(16.0);
3323 ///
3324 /// assert_eq!(length_in_pixels.to_pixels(rem_size), Pixels::from(42.0));
3325 /// assert_eq!(length_in_rems.to_pixels(rem_size), Pixels::from(32.0));
3326 /// ```
3327 pub fn to_pixels(self, rem_size: Pixels) -> Pixels {
3328 match self {
3329 AbsoluteLength::Pixels(pixels) => pixels,
3330 AbsoluteLength::Rems(rems) => rems.to_pixels(rem_size),
3331 }
3332 }
3333
3334 /// Converts an `AbsoluteLength` to `Rems` based on a given `rem_size`.
3335 ///
3336 /// # Arguments
3337 ///
3338 /// * `rem_size` - The size of one rem in pixels.
3339 ///
3340 /// # Returns
3341 ///
3342 /// Returns the `AbsoluteLength` as `Pixels`.
3343 pub fn to_rems(self, rem_size: Pixels) -> Rems {
3344 match self {
3345 AbsoluteLength::Pixels(pixels) => Rems(pixels.0 / rem_size.0),
3346 AbsoluteLength::Rems(rems) => rems,
3347 }
3348 }
3349}
3350
3351impl Default for AbsoluteLength {
3352 fn default() -> Self {
3353 px(0.).into()
3354 }
3355}
3356
3357impl Display for AbsoluteLength {
3358 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3359 match self {
3360 Self::Pixels(pixels) => write!(f, "{pixels}"),
3361 Self::Rems(rems) => write!(f, "{rems}"),
3362 }
3363 }
3364}
3365
3366impl Debug for AbsoluteLength {
3367 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3368 Display::fmt(self, f)
3369 }
3370}
3371
3372const EXPECTED_ABSOLUTE_LENGTH: &str = "number with 'px' or 'rem' suffix";
3373
3374impl TryFrom<&'_ str> for AbsoluteLength {
3375 type Error = anyhow::Error;
3376
3377 fn try_from(value: &'_ str) -> Result<Self, Self::Error> {
3378 if let Ok(pixels) = value.try_into() {
3379 Ok(Self::Pixels(pixels))
3380 } else if let Ok(rems) = value.try_into() {
3381 Ok(Self::Rems(rems))
3382 } else {
3383 Err(anyhow!(
3384 "invalid AbsoluteLength '{value}', expected {EXPECTED_ABSOLUTE_LENGTH}"
3385 ))
3386 }
3387 }
3388}
3389
3390impl JsonSchema for AbsoluteLength {
3391 fn schema_name() -> Cow<'static, str> {
3392 "AbsoluteLength".into()
3393 }
3394
3395 fn json_schema(_generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
3396 json_schema!({
3397 "type": "string",
3398 "pattern": r"^-?\d+(\.\d+)?(px|rem)$"
3399 })
3400 }
3401}
3402
3403impl<'de> Deserialize<'de> for AbsoluteLength {
3404 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
3405 struct StringVisitor;
3406
3407 impl de::Visitor<'_> for StringVisitor {
3408 type Value = AbsoluteLength;
3409
3410 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
3411 write!(f, "{EXPECTED_ABSOLUTE_LENGTH}")
3412 }
3413
3414 fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
3415 AbsoluteLength::try_from(value).map_err(E::custom)
3416 }
3417 }
3418
3419 deserializer.deserialize_str(StringVisitor)
3420 }
3421}
3422
3423impl Serialize for AbsoluteLength {
3424 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
3425 where
3426 S: Serializer,
3427 {
3428 serializer.serialize_str(&format!("{self}"))
3429 }
3430}
3431
3432/// A non-auto length that can be defined in pixels, rems, or percent of parent.
3433///
3434/// This enum represents lengths that have a specific value, as opposed to lengths that are automatically
3435/// determined by the context. It includes absolute lengths in pixels or rems, and relative lengths as a
3436/// fraction of the parent's size.
3437#[derive(Clone, Copy, Neg, PartialEq)]
3438pub enum DefiniteLength {
3439 /// An absolute length specified in pixels or rems.
3440 Absolute(AbsoluteLength),
3441 /// A relative length specified as a fraction of the parent's size, between 0 and 1.
3442 Fraction(f32),
3443}
3444
3445impl DefiniteLength {
3446 /// Converts the `DefiniteLength` to `Pixels` based on a given `base_size` and `rem_size`.
3447 ///
3448 /// If the `DefiniteLength` is an absolute length, it will be directly converted to `Pixels`.
3449 /// If it is a fraction, the fraction will be multiplied by the `base_size` to get the length in pixels.
3450 ///
3451 /// # Arguments
3452 ///
3453 /// * `base_size` - The base size in `AbsoluteLength` to which the fraction will be applied.
3454 /// * `rem_size` - The size of one rem in pixels, used to convert rems to pixels.
3455 ///
3456 /// # Returns
3457 ///
3458 /// Returns the `DefiniteLength` as `Pixels`.
3459 ///
3460 /// # Examples
3461 ///
3462 /// ```
3463 /// # use gpui::{DefiniteLength, AbsoluteLength, Pixels, px, rems};
3464 /// let length_in_pixels = DefiniteLength::Absolute(AbsoluteLength::Pixels(px(42.0)));
3465 /// let length_in_rems = DefiniteLength::Absolute(AbsoluteLength::Rems(rems(2.0)));
3466 /// let length_as_fraction = DefiniteLength::Fraction(0.5);
3467 /// let base_size = AbsoluteLength::Pixels(px(100.0));
3468 /// let rem_size = px(16.0);
3469 ///
3470 /// assert_eq!(length_in_pixels.to_pixels(base_size, rem_size), Pixels::from(42.0));
3471 /// assert_eq!(length_in_rems.to_pixels(base_size, rem_size), Pixels::from(32.0));
3472 /// assert_eq!(length_as_fraction.to_pixels(base_size, rem_size), Pixels::from(50.0));
3473 /// ```
3474 pub fn to_pixels(self, base_size: AbsoluteLength, rem_size: Pixels) -> Pixels {
3475 match self {
3476 DefiniteLength::Absolute(size) => size.to_pixels(rem_size),
3477 DefiniteLength::Fraction(fraction) => match base_size {
3478 AbsoluteLength::Pixels(px) => px * fraction,
3479 AbsoluteLength::Rems(rems) => rems * rem_size * fraction,
3480 },
3481 }
3482 }
3483}
3484
3485impl Debug for DefiniteLength {
3486 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3487 Display::fmt(self, f)
3488 }
3489}
3490
3491impl Display for DefiniteLength {
3492 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3493 match self {
3494 DefiniteLength::Absolute(length) => write!(f, "{length}"),
3495 DefiniteLength::Fraction(fraction) => write!(f, "{}%", (fraction * 100.0) as i32),
3496 }
3497 }
3498}
3499
3500const EXPECTED_DEFINITE_LENGTH: &str = "expected number with 'px', 'rem', or '%' suffix";
3501
3502impl TryFrom<&'_ str> for DefiniteLength {
3503 type Error = anyhow::Error;
3504
3505 fn try_from(value: &'_ str) -> Result<Self, Self::Error> {
3506 if let Some(percentage) = value.strip_suffix('%') {
3507 let fraction: f32 = percentage.parse::<f32>().with_context(|| {
3508 format!("invalid DefiniteLength '{value}', expected {EXPECTED_DEFINITE_LENGTH}")
3509 })?;
3510 Ok(DefiniteLength::Fraction(fraction / 100.0))
3511 } else if let Ok(absolute_length) = value.try_into() {
3512 Ok(DefiniteLength::Absolute(absolute_length))
3513 } else {
3514 Err(anyhow!(
3515 "invalid DefiniteLength '{value}', expected {EXPECTED_DEFINITE_LENGTH}"
3516 ))
3517 }
3518 }
3519}
3520
3521impl JsonSchema for DefiniteLength {
3522 fn schema_name() -> Cow<'static, str> {
3523 "DefiniteLength".into()
3524 }
3525
3526 fn json_schema(_generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
3527 json_schema!({
3528 "type": "string",
3529 "pattern": r"^-?\d+(\.\d+)?(px|rem|%)$"
3530 })
3531 }
3532}
3533
3534impl<'de> Deserialize<'de> for DefiniteLength {
3535 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
3536 struct StringVisitor;
3537
3538 impl de::Visitor<'_> for StringVisitor {
3539 type Value = DefiniteLength;
3540
3541 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
3542 write!(f, "{EXPECTED_DEFINITE_LENGTH}")
3543 }
3544
3545 fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
3546 DefiniteLength::try_from(value).map_err(E::custom)
3547 }
3548 }
3549
3550 deserializer.deserialize_str(StringVisitor)
3551 }
3552}
3553
3554impl Serialize for DefiniteLength {
3555 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
3556 where
3557 S: Serializer,
3558 {
3559 serializer.serialize_str(&format!("{self}"))
3560 }
3561}
3562
3563impl From<Pixels> for DefiniteLength {
3564 fn from(pixels: Pixels) -> Self {
3565 Self::Absolute(pixels.into())
3566 }
3567}
3568
3569impl From<Rems> for DefiniteLength {
3570 fn from(rems: Rems) -> Self {
3571 Self::Absolute(rems.into())
3572 }
3573}
3574
3575impl From<AbsoluteLength> for DefiniteLength {
3576 fn from(length: AbsoluteLength) -> Self {
3577 Self::Absolute(length)
3578 }
3579}
3580
3581impl Default for DefiniteLength {
3582 fn default() -> Self {
3583 Self::Absolute(AbsoluteLength::default())
3584 }
3585}
3586
3587/// A length that can be defined in pixels, rems, percent of parent, or auto.
3588#[derive(Clone, Copy, PartialEq)]
3589pub enum Length {
3590 /// A definite length specified either in pixels, rems, or as a fraction of the parent's size.
3591 Definite(DefiniteLength),
3592 /// An automatic length that is determined by the context in which it is used.
3593 Auto,
3594}
3595
3596impl Debug for Length {
3597 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3598 Display::fmt(self, f)
3599 }
3600}
3601
3602impl Display for Length {
3603 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3604 match self {
3605 Length::Definite(definite_length) => write!(f, "{}", definite_length),
3606 Length::Auto => write!(f, "auto"),
3607 }
3608 }
3609}
3610
3611const EXPECTED_LENGTH: &str = "expected 'auto' or number with 'px', 'rem', or '%' suffix";
3612
3613impl TryFrom<&'_ str> for Length {
3614 type Error = anyhow::Error;
3615
3616 fn try_from(value: &'_ str) -> Result<Self, Self::Error> {
3617 if value == "auto" {
3618 Ok(Length::Auto)
3619 } else if let Ok(definite_length) = value.try_into() {
3620 Ok(Length::Definite(definite_length))
3621 } else {
3622 Err(anyhow!(
3623 "invalid Length '{value}', expected {EXPECTED_LENGTH}"
3624 ))
3625 }
3626 }
3627}
3628
3629impl JsonSchema for Length {
3630 fn schema_name() -> Cow<'static, str> {
3631 "Length".into()
3632 }
3633
3634 fn json_schema(_generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
3635 json_schema!({
3636 "type": "string",
3637 "pattern": r"^(auto|-?\d+(\.\d+)?(px|rem|%))$"
3638 })
3639 }
3640}
3641
3642impl<'de> Deserialize<'de> for Length {
3643 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
3644 struct StringVisitor;
3645
3646 impl de::Visitor<'_> for StringVisitor {
3647 type Value = Length;
3648
3649 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
3650 write!(f, "{EXPECTED_LENGTH}")
3651 }
3652
3653 fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
3654 Length::try_from(value).map_err(E::custom)
3655 }
3656 }
3657
3658 deserializer.deserialize_str(StringVisitor)
3659 }
3660}
3661
3662impl Serialize for Length {
3663 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
3664 where
3665 S: Serializer,
3666 {
3667 serializer.serialize_str(&format!("{self}"))
3668 }
3669}
3670
3671/// Constructs a `DefiniteLength` representing a relative fraction of a parent size.
3672///
3673/// This function creates a `DefiniteLength` that is a specified fraction of a parent's dimension.
3674/// The fraction should be a floating-point number between 0.0 and 1.0, where 1.0 represents 100% of the parent's size.
3675///
3676/// # Arguments
3677///
3678/// * `fraction` - The fraction of the parent's size, between 0.0 and 1.0.
3679///
3680/// # Returns
3681///
3682/// A `DefiniteLength` representing the relative length as a fraction of the parent's size.
3683pub const fn relative(fraction: f32) -> DefiniteLength {
3684 DefiniteLength::Fraction(fraction)
3685}
3686
3687/// Returns the Golden Ratio, i.e. `~(1.0 + sqrt(5.0)) / 2.0`.
3688pub const fn phi() -> DefiniteLength {
3689 relative(1.618_034)
3690}
3691
3692/// Constructs a `Rems` value representing a length in rems.
3693///
3694/// # Arguments
3695///
3696/// * `rems` - The number of rems for the length.
3697///
3698/// # Returns
3699///
3700/// A `Rems` representing the specified number of rems.
3701pub const fn rems(rems: f32) -> Rems {
3702 Rems(rems)
3703}
3704
3705/// Constructs a `Pixels` value representing a length in pixels.
3706///
3707/// # Arguments
3708///
3709/// * `pixels` - The number of pixels for the length.
3710///
3711/// # Returns
3712///
3713/// A `Pixels` representing the specified number of pixels.
3714pub const fn px(pixels: f32) -> Pixels {
3715 Pixels(pixels)
3716}
3717
3718/// Returns a `Length` representing an automatic length.
3719///
3720/// The `auto` length is often used in layout calculations where the length should be determined
3721/// by the layout context itself rather than being explicitly set. This is commonly used in CSS
3722/// for properties like `width`, `height`, `margin`, `padding`, etc., where `auto` can be used
3723/// to instruct the layout engine to calculate the size based on other factors like the size of the
3724/// container or the intrinsic size of the content.
3725///
3726/// # Returns
3727///
3728/// A `Length` variant set to `Auto`.
3729pub const fn auto() -> Length {
3730 Length::Auto
3731}
3732
3733impl From<Pixels> for Length {
3734 fn from(pixels: Pixels) -> Self {
3735 Self::Definite(pixels.into())
3736 }
3737}
3738
3739impl From<Rems> for Length {
3740 fn from(rems: Rems) -> Self {
3741 Self::Definite(rems.into())
3742 }
3743}
3744
3745impl From<DefiniteLength> for Length {
3746 fn from(length: DefiniteLength) -> Self {
3747 Self::Definite(length)
3748 }
3749}
3750
3751impl From<AbsoluteLength> for Length {
3752 fn from(length: AbsoluteLength) -> Self {
3753 Self::Definite(length.into())
3754 }
3755}
3756
3757impl Default for Length {
3758 fn default() -> Self {
3759 Self::Definite(DefiniteLength::default())
3760 }
3761}
3762
3763impl From<()> for Length {
3764 fn from(_: ()) -> Self {
3765 Self::Definite(DefiniteLength::default())
3766 }
3767}
3768
3769/// A location in a grid layout.
3770#[derive(Clone, PartialEq, Debug, Serialize, Deserialize, JsonSchema, Default)]
3771pub struct GridLocation {
3772 /// The rows this item uses within the grid.
3773 pub row: Range<GridPlacement>,
3774 /// The columns this item uses within the grid.
3775 pub column: Range<GridPlacement>,
3776}
3777
3778/// The placement of an item within a grid layout's column or row.
3779#[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize, JsonSchema, Default)]
3780pub enum GridPlacement {
3781 /// The grid line index to place this item.
3782 Line(i16),
3783 /// The number of grid lines to span.
3784 Span(u16),
3785 /// Automatically determine the placement, equivalent to Span(1)
3786 #[default]
3787 Auto,
3788}
3789
3790impl From<GridPlacement> for taffy::GridPlacement {
3791 fn from(placement: GridPlacement) -> Self {
3792 match placement {
3793 GridPlacement::Line(index) => taffy::GridPlacement::from_line_index(index),
3794 GridPlacement::Span(span) => taffy::GridPlacement::from_span(span),
3795 GridPlacement::Auto => taffy::GridPlacement::Auto,
3796 }
3797 }
3798}
3799
3800/// Provides a trait for types that can calculate half of their value.
3801///
3802/// The `Half` trait is used for types that can be evenly divided, returning a new instance of the same type
3803/// representing half of the original value. This is commonly used for types that represent measurements or sizes,
3804/// such as lengths or pixels, where halving is a frequent operation during layout calculations or animations.
3805pub trait Half {
3806 /// Returns half of the current value.
3807 ///
3808 /// # Returns
3809 ///
3810 /// A new instance of the implementing type, representing half of the original value.
3811 fn half(&self) -> Self;
3812}
3813
3814impl Half for i32 {
3815 fn half(&self) -> Self {
3816 self / 2
3817 }
3818}
3819
3820impl Half for f32 {
3821 fn half(&self) -> Self {
3822 self / 2.
3823 }
3824}
3825
3826impl Half for DevicePixels {
3827 fn half(&self) -> Self {
3828 Self(self.0 / 2)
3829 }
3830}
3831
3832impl Half for ScaledPixels {
3833 fn half(&self) -> Self {
3834 Self(self.0 / 2.)
3835 }
3836}
3837
3838impl Half for Pixels {
3839 fn half(&self) -> Self {
3840 Self(self.0 / 2.)
3841 }
3842}
3843
3844impl Half for Rems {
3845 fn half(&self) -> Self {
3846 Self(self.0 / 2.)
3847 }
3848}
3849
3850/// A trait for checking if a value is zero.
3851///
3852/// This trait provides a method to determine if a value is considered to be zero.
3853/// It is implemented for various numeric and length-related types where the concept
3854/// of zero is applicable. This can be useful for comparisons, optimizations, or
3855/// determining if an operation has a neutral effect.
3856pub trait IsZero {
3857 /// Determines if the value is zero.
3858 ///
3859 /// # Returns
3860 ///
3861 /// Returns `true` if the value is zero, `false` otherwise.
3862 fn is_zero(&self) -> bool;
3863}
3864
3865impl IsZero for DevicePixels {
3866 fn is_zero(&self) -> bool {
3867 self.0 == 0
3868 }
3869}
3870
3871impl IsZero for ScaledPixels {
3872 fn is_zero(&self) -> bool {
3873 self.0 == 0.
3874 }
3875}
3876
3877impl IsZero for Pixels {
3878 fn is_zero(&self) -> bool {
3879 self.0 == 0.
3880 }
3881}
3882
3883impl IsZero for Rems {
3884 fn is_zero(&self) -> bool {
3885 self.0 == 0.
3886 }
3887}
3888
3889impl IsZero for AbsoluteLength {
3890 fn is_zero(&self) -> bool {
3891 match self {
3892 AbsoluteLength::Pixels(pixels) => pixels.is_zero(),
3893 AbsoluteLength::Rems(rems) => rems.is_zero(),
3894 }
3895 }
3896}
3897
3898impl IsZero for DefiniteLength {
3899 fn is_zero(&self) -> bool {
3900 match self {
3901 DefiniteLength::Absolute(length) => length.is_zero(),
3902 DefiniteLength::Fraction(fraction) => *fraction == 0.,
3903 }
3904 }
3905}
3906
3907impl IsZero for Length {
3908 fn is_zero(&self) -> bool {
3909 match self {
3910 Length::Definite(length) => length.is_zero(),
3911 Length::Auto => false,
3912 }
3913 }
3914}
3915
3916impl<T: IsZero + Clone + Debug + Default + PartialEq> IsZero for Point<T> {
3917 fn is_zero(&self) -> bool {
3918 self.x.is_zero() && self.y.is_zero()
3919 }
3920}
3921
3922impl<T> IsZero for Size<T>
3923where
3924 T: IsZero + Clone + Debug + Default + PartialEq,
3925{
3926 fn is_zero(&self) -> bool {
3927 self.width.is_zero() || self.height.is_zero()
3928 }
3929}
3930
3931impl<T: IsZero + Clone + Debug + Default + PartialEq> IsZero for Bounds<T> {
3932 fn is_zero(&self) -> bool {
3933 self.size.is_zero()
3934 }
3935}
3936
3937impl<T> IsZero for Corners<T>
3938where
3939 T: IsZero + Clone + Debug + Default + PartialEq,
3940{
3941 fn is_zero(&self) -> bool {
3942 self.top_left.is_zero()
3943 && self.top_right.is_zero()
3944 && self.bottom_right.is_zero()
3945 && self.bottom_left.is_zero()
3946 }
3947}
3948
3949#[cfg(test)]
3950mod tests {
3951 use super::*;
3952
3953 #[test]
3954 fn test_bounds_intersects() {
3955 let bounds1 = Bounds {
3956 origin: Point { x: 0.0, y: 0.0 },
3957 size: Size {
3958 width: 5.0,
3959 height: 5.0,
3960 },
3961 };
3962 let bounds2 = Bounds {
3963 origin: Point { x: 4.0, y: 4.0 },
3964 size: Size {
3965 width: 5.0,
3966 height: 5.0,
3967 },
3968 };
3969 let bounds3 = Bounds {
3970 origin: Point { x: 10.0, y: 10.0 },
3971 size: Size {
3972 width: 5.0,
3973 height: 5.0,
3974 },
3975 };
3976
3977 // Test Case 1: Intersecting bounds
3978 assert!(bounds1.intersects(&bounds2));
3979
3980 // Test Case 2: Non-Intersecting bounds
3981 assert!(!bounds1.intersects(&bounds3));
3982
3983 // Test Case 3: Bounds intersecting with themselves
3984 assert!(bounds1.intersects(&bounds1));
3985 }
3986}