Skip to main content

open_gpui_motion/
geometry.rs

1//! Renderer-neutral geometry values for UI component state.
2
3use std::ops::{Add, Div, Mul, Neg, Sub};
4
5/// A renderer-neutral logical pixel scalar.
6#[derive(Debug, Clone, Copy, Default, PartialEq, PartialOrd)]
7pub struct MotionPx(f32);
8
9impl MotionPx {
10    /// Zero logical pixels.
11    pub const ZERO: Self = Self(0.0);
12
13    /// One logical pixel.
14    pub const ONE: Self = Self(1.0);
15
16    /// Creates a logical pixel value.
17    pub const fn new(value: f32) -> Self {
18        Self(value)
19    }
20
21    /// Returns the raw scalar value.
22    pub const fn as_f32(self) -> f32 {
23        self.0
24    }
25
26    /// Returns half of this value.
27    pub const fn half(self) -> Self {
28        Self(self.0 * 0.5)
29    }
30
31    /// Returns the smaller of two pixel values.
32    pub const fn min(self, other: Self) -> Self {
33        if self.0 <= other.0 { self } else { other }
34    }
35
36    /// Returns the larger of two pixel values.
37    pub const fn max(self, other: Self) -> Self {
38        if self.0 >= other.0 { self } else { other }
39    }
40}
41
42impl Add for MotionPx {
43    type Output = Self;
44
45    fn add(self, rhs: Self) -> Self::Output {
46        Self(self.0 + rhs.0)
47    }
48}
49
50impl Sub for MotionPx {
51    type Output = Self;
52
53    fn sub(self, rhs: Self) -> Self::Output {
54        Self(self.0 - rhs.0)
55    }
56}
57
58impl Neg for MotionPx {
59    type Output = Self;
60
61    fn neg(self) -> Self::Output {
62        Self(-self.0)
63    }
64}
65
66impl Mul<f32> for MotionPx {
67    type Output = Self;
68
69    fn mul(self, rhs: f32) -> Self::Output {
70        Self(self.0 * rhs)
71    }
72}
73
74impl Div<f32> for MotionPx {
75    type Output = Self;
76
77    fn div(self, rhs: f32) -> Self::Output {
78        Self(self.0 / rhs)
79    }
80}
81
82/// Creates a renderer-neutral logical pixel scalar.
83pub const fn motion_px(value: f32) -> MotionPx {
84    MotionPx::new(value)
85}
86
87/// A renderer-neutral point.
88#[derive(Debug, Clone, Copy, Default, PartialEq)]
89pub struct MotionPoint {
90    /// Horizontal coordinate.
91    pub x: MotionPx,
92    /// Vertical coordinate.
93    pub y: MotionPx,
94}
95
96impl MotionPoint {
97    /// Creates a point from x and y coordinates.
98    pub const fn new(x: MotionPx, y: MotionPx) -> Self {
99        Self { x, y }
100    }
101}
102
103/// Creates a renderer-neutral point.
104pub const fn motion_point(x: MotionPx, y: MotionPx) -> MotionPoint {
105    MotionPoint::new(x, y)
106}
107
108/// A renderer-neutral size.
109#[derive(Debug, Clone, Copy, Default, PartialEq)]
110pub struct MotionSize {
111    /// Horizontal extent.
112    pub width: MotionPx,
113    /// Vertical extent.
114    pub height: MotionPx,
115}
116
117impl MotionSize {
118    /// Creates a size from width and height.
119    pub const fn new(width: MotionPx, height: MotionPx) -> Self {
120        Self { width, height }
121    }
122}
123
124/// Creates a renderer-neutral size.
125pub const fn motion_size(width: MotionPx, height: MotionPx) -> MotionSize {
126    MotionSize::new(width, height)
127}
128
129/// A renderer-neutral rectangle.
130#[derive(Debug, Clone, Copy, Default, PartialEq)]
131pub struct MotionRect {
132    /// Top-left rectangle origin.
133    pub origin: MotionPoint,
134    /// Rectangle extent.
135    pub size: MotionSize,
136}
137
138impl MotionRect {
139    /// Creates a rectangle from origin and size.
140    pub const fn new(origin: MotionPoint, size: MotionSize) -> Self {
141        Self { origin, size }
142    }
143
144    /// Returns the rectangle top-left point.
145    pub const fn top_left(self) -> MotionPoint {
146        self.origin
147    }
148
149    /// Returns the rectangle top-center point.
150    pub fn top_center(self) -> MotionPoint {
151        MotionPoint::new(self.origin.x + self.size.width.half(), self.origin.y)
152    }
153
154    /// Returns the rectangle top-right point.
155    pub fn top_right(self) -> MotionPoint {
156        MotionPoint::new(self.origin.x + self.size.width, self.origin.y)
157    }
158
159    /// Returns the rectangle right-center point.
160    pub fn right_center(self) -> MotionPoint {
161        MotionPoint::new(
162            self.origin.x + self.size.width,
163            self.origin.y + self.size.height.half(),
164        )
165    }
166
167    /// Returns the rectangle bottom-left point.
168    pub fn bottom_left(self) -> MotionPoint {
169        MotionPoint::new(self.origin.x, self.origin.y + self.size.height)
170    }
171
172    /// Returns the rectangle bottom-center point.
173    pub fn bottom_center(self) -> MotionPoint {
174        MotionPoint::new(
175            self.origin.x + self.size.width.half(),
176            self.origin.y + self.size.height,
177        )
178    }
179
180    /// Returns the rectangle bottom-right point.
181    pub fn bottom_right(self) -> MotionPoint {
182        MotionPoint::new(
183            self.origin.x + self.size.width,
184            self.origin.y + self.size.height,
185        )
186    }
187
188    /// Returns the rectangle left-center point.
189    pub fn left_center(self) -> MotionPoint {
190        MotionPoint::new(self.origin.x, self.origin.y + self.size.height.half())
191    }
192
193    /// Returns a rectangle inset by the same amount on every side.
194    pub fn inset(self, amount: MotionPx) -> Self {
195        let double = MotionPx::new(amount.as_f32() * 2.0);
196        Self {
197            origin: MotionPoint::new(self.origin.x + amount, self.origin.y + amount),
198            size: MotionSize::new(self.size.width - double, self.size.height - double),
199        }
200    }
201}
202
203/// Creates a renderer-neutral rectangle.
204pub const fn motion_rect(origin: MotionPoint, size: MotionSize) -> MotionRect {
205    MotionRect::new(origin, size)
206}
207
208/// Renderer-neutral edge insets.
209#[derive(Debug, Clone, Copy, Default, PartialEq)]
210pub struct MotionEdges {
211    /// Top edge inset.
212    pub top: MotionPx,
213    /// Right edge inset.
214    pub right: MotionPx,
215    /// Bottom edge inset.
216    pub bottom: MotionPx,
217    /// Left edge inset.
218    pub left: MotionPx,
219}
220
221impl MotionEdges {
222    /// Creates edge insets from top, right, bottom, and left values.
223    pub const fn new(top: MotionPx, right: MotionPx, bottom: MotionPx, left: MotionPx) -> Self {
224        Self {
225            top,
226            right,
227            bottom,
228            left,
229        }
230    }
231
232    /// Creates equal edge insets on every side.
233    pub const fn uniform(value: MotionPx) -> Self {
234        Self {
235            top: value,
236            right: value,
237            bottom: value,
238            left: value,
239        }
240    }
241}
242
243/// Creates renderer-neutral edge insets.
244pub const fn motion_edges(
245    top: MotionPx,
246    right: MotionPx,
247    bottom: MotionPx,
248    left: MotionPx,
249) -> MotionEdges {
250    MotionEdges::new(top, right, bottom, left)
251}