iced_core/layout/
limits.rs1#![allow(clippy::manual_clamp)]
2use crate::length;
3use crate::{Length, Size};
4
5#[derive(Debug, Clone, Copy, PartialEq)]
7pub struct Limits {
8 min: Size,
9 max: Size,
10 compression: Size<bool>,
11}
12
13impl Limits {
14 pub const NONE: Limits = Limits {
16 min: Size::ZERO,
17 max: Size::INFINITE,
18 compression: Size::new(false, false),
19 };
20
21 pub const fn new(min: Size, max: Size) -> Limits {
23 Limits::with_compression(min, max, Size::new(false, false))
24 }
25
26 pub const fn with_compression(min: Size, max: Size, compress: Size<bool>) -> Self {
29 Limits {
30 min,
31 max,
32 compression: compress,
33 }
34 }
35
36 pub fn min(&self) -> Size {
38 self.min
39 }
40
41 pub fn max(&self) -> Size {
43 self.max
44 }
45
46 pub fn compression(&self) -> Size<bool> {
48 self.compression
49 }
50
51 pub fn width(mut self, width: impl Into<Length>) -> Limits {
53 match width.into() {
54 Length::Shrink => {
55 self.compression.width = true;
56 }
57 Length::Fit | Length::Fluid(_) => {
58 self.compression.width = false;
59 }
60 Length::Fixed(amount) => {
61 let new_width = amount.min(self.max.width).max(self.min.width);
62
63 self.min.width = new_width;
64 self.max.width = new_width;
65 self.compression.width = false;
66 }
67 Length::Bounded { bounds, sizing } => {
68 match bounds {
69 length::Bounds::Min(min) => {
70 self.min.width = min.min(self.max.width).max(self.min.width);
71 }
72 length::Bounds::Max(max) => {
73 self.max.width = max.min(self.max.width).max(self.min.width);
74 }
75 length::Bounds::Both { min, max } => {
76 self.min.width = min.min(self.max.width).max(self.min.width);
77 self.max.width = max.min(self.max.width).max(self.min.width);
78 }
79 }
80
81 match sizing {
82 length::Sizing::Shrink => {
83 self.compression.width = true;
84 }
85 length::Sizing::Fit => {
86 self.compression.width = false;
87 }
88 length::Sizing::Fill(_) => {}
89 }
90 }
91 Length::Fill | Length::FillPortion(_) => {}
92 }
93
94 self
95 }
96
97 pub fn height(mut self, height: impl Into<Length>) -> Limits {
99 match height.into() {
100 Length::Shrink => {
101 self.compression.height = true;
102 }
103 Length::Fit | Length::Fluid(_) => {
104 self.compression.height = false;
105 }
106 Length::Fixed(amount) => {
107 let new_height = amount.min(self.max.height).max(self.min.height);
108
109 self.min.height = new_height;
110 self.max.height = new_height;
111 self.compression.height = false;
112 }
113 Length::Bounded { bounds, sizing } => {
114 match bounds {
115 length::Bounds::Min(min) => {
116 self.min.height = min.min(self.max.height).max(self.min.height);
117 }
118 length::Bounds::Max(max) => {
119 self.max.height = max.min(self.max.height).max(self.min.height);
120 }
121 length::Bounds::Both { min, max } => {
122 self.min.height = min.min(self.max.height).max(self.min.height);
123 self.max.height = max.min(self.max.height).max(self.min.height);
124 }
125 }
126
127 match sizing {
128 length::Sizing::Shrink => {
129 self.compression.height = true;
130 }
131 length::Sizing::Fit => {
132 self.compression.height = false;
133 }
134 length::Sizing::Fill(_) => {}
135 }
136 }
137 Length::Fill | Length::FillPortion(_) => {}
138 }
139
140 self
141 }
142
143 pub fn shrink(&self, size: impl Into<Size>) -> Limits {
145 let size = size.into();
146
147 let min = Size::new(
148 (self.min().width - size.width).max(0.0),
149 (self.min().height - size.height).max(0.0),
150 );
151
152 let max = Size::new(
153 (self.max().width - size.width).max(0.0),
154 (self.max().height - size.height).max(0.0),
155 );
156
157 Limits {
158 min,
159 max,
160 compression: self.compression,
161 }
162 }
163
164 pub fn loose(&self) -> Limits {
166 Limits {
167 min: Size::ZERO,
168 max: self.max,
169 compression: self.compression,
170 }
171 }
172
173 pub fn resolve(
177 &self,
178 width: impl Into<Length>,
179 height: impl Into<Length>,
180 intrinsic_size: Size,
181 ) -> Size {
182 Size::new(
183 self.resolve_width(width, intrinsic_size.width),
184 self.resolve_height(height, intrinsic_size.height),
185 )
186 }
187
188 pub fn resolve_width(&self, width: impl Into<Length>, intrinsic_width: f32) -> f32 {
190 match width.into() {
191 Length::Fill
192 | Length::FillPortion(_)
193 | Length::Bounded {
194 sizing: length::Sizing::Fill(_),
195 ..
196 } if !self.compression.width => self.max.width,
197 Length::Fixed(amount) => amount.min(self.max.width).max(self.min.width),
198 _ => intrinsic_width.min(self.max.width).max(self.min.width),
199 }
200 }
201
202 pub fn resolve_height(&self, height: impl Into<Length>, intrinsic_height: f32) -> f32 {
204 match height.into() {
205 Length::Fill
206 | Length::FillPortion(_)
207 | Length::Bounded {
208 sizing: length::Sizing::Fill(_),
209 ..
210 } if !self.compression.height => self.max.height,
211 Length::Fixed(amount) => amount.min(self.max.height).max(self.min.height),
212 _ => intrinsic_height.min(self.max.height).max(self.min.height),
213 }
214 }
215}