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