anathema_widgets/layout/
constraints.rs1use anathema_geometry::Region;
2
3use crate::layout::Size;
4
5#[derive(Debug, Copy, Clone, PartialEq, Eq)]
8pub struct Constraints {
9 pub min_width: u16,
11 pub min_height: u16,
13 max_width: u16,
15 max_height: u16,
17}
18
19impl Constraints {
20 pub const MAX: Self = Self {
21 min_width: u16::MAX,
22 min_height: u16::MAX,
23 max_width: u16::MAX,
24 max_height: u16::MAX,
25 };
26 pub const ZERO: Self = Self {
27 min_width: 0,
28 min_height: 0,
29 max_width: 0,
30 max_height: 0,
31 };
32
33 pub fn max_height(&self) -> u16 {
34 self.max_height
35 }
36
37 pub fn max_width(&self) -> u16 {
38 self.max_width
39 }
40
41 pub fn sub_max_width(&mut self, width: u16) {
44 if self.max_width < u16::MAX {
45 self.max_width = self.max_width.saturating_sub(width);
46 self.min_width = self.min_width.min(self.max_width);
47 }
48 }
49
50 pub fn sub_max_height(&mut self, height: u16) {
53 if self.max_height < u16::MAX {
54 self.max_height = self.max_height.saturating_sub(height);
55 self.min_height = self.min_height.min(self.max_height);
56 }
57 }
58
59 pub fn new(max_width: impl Into<Option<u16>>, max_height: impl Into<Option<u16>>) -> Self {
67 let max_width = max_width.into().unwrap_or(u16::MAX);
68 let max_height = max_height.into().unwrap_or(u16::MAX);
69 Self {
70 min_width: 0,
71 min_height: 0,
72 max_width,
73 max_height,
74 }
75 }
76
77 pub fn unbounded() -> Self {
79 Self {
80 min_width: 0,
81 min_height: 0,
82 max_width: u16::MAX,
83 max_height: u16::MAX,
84 }
85 }
86
87 pub fn unbound_height(&mut self) {
89 self.max_height = u16::MAX;
90 }
91
92 pub fn unbound_width(&mut self) {
94 self.max_width = u16::MAX;
95 }
96
97 pub fn is_unbounded(&self) -> bool {
99 self.is_width_unbounded() && self.is_height_unbounded()
100 }
101
102 pub fn is_width_unbounded(&self) -> bool {
104 self.max_width == u16::MAX
105 }
106
107 pub fn is_height_unbounded(&self) -> bool {
109 self.max_height == u16::MAX
110 }
111
112 pub fn is_width_tight(&self) -> bool {
114 self.max_width == self.min_width
115 }
116
117 pub fn is_height_tight(&self) -> bool {
119 self.max_height == self.min_height
120 }
121
122 pub fn make_width_tight(&mut self, width: u16) {
130 self.max_width = self.max_width.min(width);
131 self.min_width = self.max_width;
132 }
133
134 pub fn make_height_tight(&mut self, height: u16) {
142 self.max_height = self.max_height.min(height);
143 self.min_height = self.max_height;
144 }
145
146 pub fn expand_horz(&mut self, mut size: Size) -> Size {
147 size.width = self.max_width;
148 size
149 }
150
151 pub fn expand_vert(&mut self, mut size: Size) -> Size {
152 size.height = self.max_height;
153 size
154 }
155
156 pub fn expand_all(&mut self, mut size: Size) -> Size {
157 size = self.expand_horz(size);
158 self.expand_vert(size)
159 }
160
161 pub fn set_max_width(&mut self, width: u16) {
165 self.max_width = width;
166 }
167
168 pub fn set_max_height(&mut self, height: u16) {
172 self.max_height = height;
173 }
174
175 pub fn div_assign_max_width(mut self, count: u16, overflow: u16) -> Self {
176 let width = self.max_width / count + overflow;
177 self.make_width_tight(width);
178 self
179 }
180
181 pub fn div_assign_max_height(mut self, count: u16, overflow: u16) -> Self {
182 let height = self.max_height / count + overflow;
183 self.make_height_tight(height);
184 self
185 }
186
187 pub fn has_zero_dimension(&self) -> bool {
191 self.max_width == 0 || self.max_height == 0
192 }
193
194 pub fn max_size(&self) -> Size {
196 (self.max_width, self.max_height).into()
197 }
198}
199
200impl From<Size> for Constraints {
201 fn from(value: Size) -> Self {
202 Self::new(value.width, value.height)
203 }
204}
205
206impl From<Region> for Constraints {
207 fn from(value: Region) -> Self {
208 let width = value.to.x - value.from.x;
209 let height = value.to.y - value.from.y;
210 Self::new(width as u16, height as u16)
211 }
212}
213
214impl Default for Constraints {
215 fn default() -> Self {
216 Self::ZERO
217 }
218}