1#[allow(unused)] use super::Stretch; use crate::dir::Directional;
10use crate::geom::{Rect, Size};
11
12pub use crate::text::Align;
13
14#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
37pub struct AlignHints {
38 pub horiz: Option<Align>,
39 pub vert: Option<Align>,
40}
41
42impl AlignHints {
43 pub const NONE: AlignHints = AlignHints::new(None, None);
45
46 pub const TOP: AlignHints = AlignHints::new(None, Some(Align::TL));
48 pub const BOTTOM: AlignHints = AlignHints::new(None, Some(Align::BR));
50 pub const LEFT: AlignHints = AlignHints::new(Some(Align::TL), None);
52 pub const RIGHT: AlignHints = AlignHints::new(Some(Align::BR), None);
54
55 pub const TOP_LEFT: AlignHints = AlignHints::new(Some(Align::TL), Some(Align::TL));
57 pub const TOP_RIGHT: AlignHints = AlignHints::new(Some(Align::BR), Some(Align::TL));
59 pub const BOTTOM_LEFT: AlignHints = AlignHints::new(Some(Align::TL), Some(Align::BR));
61 pub const BOTTOM_RIGHT: AlignHints = AlignHints::new(Some(Align::BR), Some(Align::BR));
63
64 pub const CENTER: AlignHints = AlignHints::new(Some(Align::Center), Some(Align::Center));
66 pub const TOP_CENTER: AlignHints = AlignHints::new(Some(Align::Center), Some(Align::TL));
68 pub const BOTTOM_CENTER: AlignHints = AlignHints::new(Some(Align::Center), Some(Align::BR));
70 pub const CENTER_LEFT: AlignHints = AlignHints::new(Some(Align::TL), Some(Align::Center));
72 pub const CENTER_RIGHT: AlignHints = AlignHints::new(Some(Align::BR), Some(Align::Center));
74 pub const HORIZ_CENTER: AlignHints = AlignHints::new(Some(Align::Center), None);
76 pub const VERT_CENTER: AlignHints = AlignHints::new(None, Some(Align::Center));
78
79 pub const STRETCH: AlignHints = AlignHints::new(Some(Align::Stretch), Some(Align::Stretch));
81
82 pub const fn new(horiz: Option<Align>, vert: Option<Align>) -> Self {
84 Self { horiz, vert }
85 }
86
87 #[inline]
89 pub fn extract(self, dir: impl Directional) -> Option<Align> {
90 match dir.is_vertical() {
91 false => self.horiz,
92 true => self.vert,
93 }
94 }
95
96 #[inline]
98 pub fn set_component<D: Directional>(&mut self, dir: D, align: Option<Align>) {
99 match dir.is_vertical() {
100 false => self.horiz = align,
101 true => self.vert = align,
102 }
103 }
104
105 #[must_use = "method does not modify self but returns a new value"]
107 pub fn combine(self, rhs: AlignHints) -> Self {
108 Self {
109 horiz: self.horiz.or(rhs.horiz),
110 vert: self.vert.or(rhs.vert),
111 }
112 }
113
114 pub fn unwrap_or(self, horiz: Align, vert: Align) -> (Align, Align) {
116 (self.horiz.unwrap_or(horiz), self.vert.unwrap_or(vert))
117 }
118
119 pub fn complete(&self, horiz: Align, vert: Align) -> AlignPair {
121 AlignPair::new(self.horiz.unwrap_or(horiz), self.vert.unwrap_or(vert))
122 }
123
124 pub fn complete_default(&self) -> AlignPair {
126 self.complete(Align::Default, Align::Default)
127 }
128
129 pub fn complete_center(&self) -> AlignPair {
131 self.complete(Align::Center, Align::Center)
132 }
133}
134
135#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
139pub struct AlignPair {
140 pub horiz: Align,
141 pub vert: Align,
142}
143
144impl AlignPair {
145 pub const DEFAULT: AlignPair = AlignPair::new(Align::Default, Align::Default);
147
148 pub const CENTER: AlignPair = AlignPair::new(Align::Center, Align::Center);
150
151 pub const STRETCH: AlignPair = AlignPair::new(Align::Stretch, Align::Stretch);
153
154 pub const fn new(horiz: Align, vert: Align) -> Self {
156 Self { horiz, vert }
157 }
158
159 #[inline]
161 pub fn extract<D: Directional>(self, dir: D) -> Align {
162 match dir.is_vertical() {
163 false => self.horiz,
164 true => self.vert,
165 }
166 }
167
168 #[inline]
170 pub fn set_component<D: Directional>(&mut self, dir: D, align: Align) {
171 match dir.is_vertical() {
172 false => self.horiz = align,
173 true => self.vert = align,
174 }
175 }
176
177 pub fn aligned_rect(&self, ideal: Size, rect: Rect) -> Rect {
179 let mut pos = rect.pos;
180 let mut size = rect.size;
181 if ideal.0 < size.0 && self.horiz != Align::Stretch {
182 pos.0 += match self.horiz {
183 Align::Center => (size.0 - ideal.0) / 2,
184 Align::BR => size.0 - ideal.0,
185 Align::Default | Align::TL | Align::Stretch => 0,
186 };
187 size.0 = ideal.0;
188 }
189 if ideal.1 < size.1 && self.vert != Align::Stretch {
190 pos.1 += match self.vert {
191 Align::Center => (size.1 - ideal.1) / 2,
192 Align::BR => size.1 - ideal.1,
193 Align::Default | Align::TL | Align::Stretch => 0,
194 };
195 size.1 = ideal.1;
196 }
197 Rect { pos, size }
198 }
199}
200
201impl From<(Align, Align)> for AlignHints {
202 #[inline]
203 fn from((h, v): (Align, Align)) -> Self {
204 AlignHints::new(Some(h), Some(v))
205 }
206}
207
208impl From<(Align, Align)> for AlignPair {
209 #[inline]
210 fn from((h, v): (Align, Align)) -> Self {
211 AlignPair::new(h, v)
212 }
213}
214
215impl From<AlignPair> for (Align, Align) {
216 #[inline]
217 fn from(p: AlignPair) -> Self {
218 (p.horiz, p.vert)
219 }
220}