hui/frame/
point.rs

1//! frame-relative positioning/size
2
3use glam::{Vec2, vec2};
4use derive_more::{Add, AddAssign, Sub, SubAssign};
5use crate::layout::{Size, Size2d};
6
7/// Point inside a frame
8///
9/// Can be absolute, relative, or a combination of both\
10/// Final coordinate is calculated as `absolute + relative * parent_size`
11#[derive(Clone, Copy, Debug, Default, Add, AddAssign, Sub, SubAssign)]
12pub struct FramePoint {
13  /// Absolute positioning
14  pub absolute: f32,
15
16  /// Relative positioning
17  pub relative: f32,
18}
19
20impl From<f32> for FramePoint {
21  fn from(value: f32) -> Self {
22    Self::absolute(value)
23  }
24}
25
26impl From<Size> for FramePoint {
27  /// Convert a `Size` into a `FramePoint`
28  ///
29  /// This function behaves just as you would expect, but:
30  /// - `Auto` is always treated as `BEGIN`
31  /// - `Remaining` is treated as `Relative`
32  fn from(size: Size) -> Self {
33    match size {
34      Size::Auto => Self::BEGIN,
35      Size::Relative(value) | Size::Remaining(value) => Self::relative(value),
36      Size::Absolute(value) => Self::absolute(value),
37    }
38  }
39}
40
41impl FramePoint {
42  /// Beginning of the frame axis
43  pub const BEGIN: Self = Self {
44    absolute: 0.0,
45    relative: 0.0,
46  };
47
48  /// Center of the frame axis
49  pub const CENTER: Self = Self {
50    absolute: 0.0,
51    relative: 0.5,
52  };
53
54  /// End of the frame axis
55  pub const END: Self = Self {
56    absolute: 0.0,
57    relative: 1.0,
58  };
59
60  /// Create a new absolutely positioned `FramePoint`
61  pub const fn absolute(value: f32) -> Self {
62    Self {
63      absolute: value,
64      relative: 0.0,
65    }
66  }
67
68  /// Create a new relatively positioned `FramePoint`
69  pub const fn relative(value: f32) -> Self {
70    Self {
71      absolute: 0.0,
72      relative: value,
73    }
74  }
75
76  /// Create a new `FramePoint` with both absolute and relative positioning
77  pub const fn relative_absolute(relative: f32, absolute: f32) -> Self {
78    Self {
79      absolute,
80      relative,
81    }
82  }
83
84  /// Resolve the `FramePoint` into an absolute coordinate
85  pub(crate) fn resolve(&self, parent_size: f32) -> f32 {
86    self.absolute + self.relative * parent_size
87  }
88}
89
90/// A 2-dimensional [`FramePoint`]
91#[derive(Clone, Copy, Debug, Default, Add, AddAssign, Sub, SubAssign)]
92pub struct FramePoint2d {
93  pub x: FramePoint,
94  pub y: FramePoint,
95}
96
97impl From<(FramePoint, FramePoint)> for FramePoint2d {
98  fn from((x, y): (FramePoint, FramePoint)) -> Self {
99    Self { x, y }
100  }
101}
102
103impl From<Size> for FramePoint2d {
104  fn from(size: Size) -> Self {
105    Self {
106      x: size.into(),
107      y: size.into(),
108    }
109  }
110}
111
112impl From<Size2d> for FramePoint2d {
113  fn from(size: Size2d) -> Self {
114    Self {
115      x: size.width.into(),
116      y: size.height.into(),
117    }
118  }
119}
120
121impl From<(f32, f32)> for FramePoint2d {
122  fn from((x, y): (f32, f32)) -> Self {
123    Self {
124      x: FramePoint::absolute(x),
125      y: FramePoint::absolute(y),
126    }
127  }
128}
129
130impl From<Vec2> for FramePoint2d {
131  fn from(vec: Vec2) -> Self {
132    Self {
133      x: FramePoint::absolute(vec.x),
134      y: FramePoint::absolute(vec.y),
135    }
136  }
137}
138
139impl FramePoint2d {
140  /// Top left corner of the frame
141  pub const TOP_LEFT: Self = Self {
142    x: FramePoint::BEGIN,
143    y: FramePoint::BEGIN,
144  };
145
146  /// Top center of the frame
147  pub const TOP_CENTER: Self = Self {
148    x: FramePoint::CENTER,
149    y: FramePoint::BEGIN,
150  };
151
152  /// Top right corner of the frame
153  pub const TOP_RIGHT: Self = Self {
154    x: FramePoint::END,
155    y: FramePoint::BEGIN,
156  };
157
158  /// Center left of the frame
159  pub const CENTER_LEFT: Self = Self {
160    x: FramePoint::BEGIN,
161    y: FramePoint::CENTER,
162  };
163
164  /// Center of the frame
165  pub const CENTER: Self = Self {
166    x: FramePoint::CENTER,
167    y: FramePoint::CENTER,
168  };
169
170  /// Center right of the frame
171  pub const CENTER_RIGHT: Self = Self {
172    x: FramePoint::END,
173    y: FramePoint::CENTER,
174  };
175
176  /// Bottom left corner of the frame
177  pub const BOTTOM_LEFT: Self = Self {
178    x: FramePoint::BEGIN,
179    y: FramePoint::END,
180  };
181
182  /// Bottom center of the frame
183  pub const BOTTOM_CENTER: Self = Self {
184    x: FramePoint::CENTER,
185    y: FramePoint::END,
186  };
187
188  /// Bottom right corner of the frame
189  pub const BOTTOM_RIGHT: Self = Self {
190    x: FramePoint::END,
191    y: FramePoint::END,
192  };
193
194  /// Resolve the `FramePoint2d` into an absolute coordinate within the frame's coordinate system\
195  ///
196  /// (point with absolute cordinates, relative to the frame's top-left corner)
197  pub(crate) fn resolve(&self, parent_size: Vec2) -> Vec2 {
198    let x = self.x.resolve(parent_size.x);
199    let y = self.y.resolve(parent_size.y);
200    vec2(x, y)
201  }
202}