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