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