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