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