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