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