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