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