iced_core/layout/
limits.rs

1#![allow(clippy::manual_clamp)]
2use crate::{Length, Size};
3
4/// A set of size constraints for layouting.
5#[derive(Debug, Clone, Copy, PartialEq)]
6pub struct Limits {
7    min: Size,
8    max: Size,
9}
10
11impl Limits {
12    /// No limits
13    pub const NONE: Limits = Limits {
14        min: Size::ZERO,
15        max: Size::INFINITY,
16    };
17
18    /// Creates new [`Limits`] with the given minimum and maximum [`Size`].
19    pub const fn new(min: Size, max: Size) -> Limits {
20        Limits { min, max }
21    }
22
23    /// Returns the minimum [`Size`] of the [`Limits`].
24    pub fn min(&self) -> Size {
25        self.min
26    }
27
28    /// Returns the maximum [`Size`] of the [`Limits`].
29    pub fn max(&self) -> Size {
30        self.max
31    }
32
33    /// Applies a width constraint to the current [`Limits`].
34    pub fn width(mut self, width: impl Into<Length>) -> Limits {
35        match width.into() {
36            Length::Shrink | Length::Fill | Length::FillPortion(_) => {}
37            Length::Fixed(amount) => {
38                let new_width = amount.min(self.max.width).max(self.min.width);
39
40                self.min.width = new_width;
41                self.max.width = new_width;
42            }
43        }
44
45        self
46    }
47
48    /// Applies a height constraint to the current [`Limits`].
49    pub fn height(mut self, height: impl Into<Length>) -> Limits {
50        match height.into() {
51            Length::Shrink | Length::Fill | Length::FillPortion(_) => {}
52            Length::Fixed(amount) => {
53                let new_height =
54                    amount.min(self.max.height).max(self.min.height);
55
56                self.min.height = new_height;
57                self.max.height = new_height;
58            }
59        }
60
61        self
62    }
63
64    /// Applies a minimum width constraint to the current [`Limits`].
65    pub fn min_width(mut self, min_width: f32) -> Limits {
66        self.min.width = self.min.width.max(min_width).min(self.max.width);
67
68        self
69    }
70
71    /// Applies a maximum width constraint to the current [`Limits`].
72    pub fn max_width(mut self, max_width: f32) -> Limits {
73        self.max.width = self.max.width.min(max_width).max(self.min.width);
74
75        self
76    }
77
78    /// Applies a minimum height constraint to the current [`Limits`].
79    pub fn min_height(mut self, min_height: f32) -> Limits {
80        self.min.height = self.min.height.max(min_height).min(self.max.height);
81
82        self
83    }
84
85    /// Applies a maximum height constraint to the current [`Limits`].
86    pub fn max_height(mut self, max_height: f32) -> Limits {
87        self.max.height = self.max.height.min(max_height).max(self.min.height);
88
89        self
90    }
91
92    /// Shrinks the current [`Limits`] by the given [`Size`].
93    pub fn shrink(&self, size: impl Into<Size>) -> Limits {
94        let size = size.into();
95
96        let min = Size::new(
97            (self.min().width - size.width).max(0.0),
98            (self.min().height - size.height).max(0.0),
99        );
100
101        let max = Size::new(
102            (self.max().width - size.width).max(0.0),
103            (self.max().height - size.height).max(0.0),
104        );
105
106        Limits { min, max }
107    }
108
109    /// Removes the minimum width constraint for the current [`Limits`].
110    pub fn loose(&self) -> Limits {
111        Limits {
112            min: Size::ZERO,
113            max: self.max,
114        }
115    }
116
117    /// Computes the resulting [`Size`] that fits the [`Limits`] given
118    /// some width and height requirements and the intrinsic size of
119    /// some content.
120    pub fn resolve(
121        &self,
122        width: impl Into<Length>,
123        height: impl Into<Length>,
124        intrinsic_size: Size,
125    ) -> Size {
126        let width = match width.into() {
127            Length::Fill | Length::FillPortion(_) => self.max.width,
128            Length::Fixed(amount) => {
129                amount.min(self.max.width).max(self.min.width)
130            }
131            Length::Shrink => {
132                intrinsic_size.width.min(self.max.width).max(self.min.width)
133            }
134        };
135
136        let height = match height.into() {
137            Length::Fill | Length::FillPortion(_) => self.max.height,
138            Length::Fixed(amount) => {
139                amount.min(self.max.height).max(self.min.height)
140            }
141            Length::Shrink => intrinsic_size
142                .height
143                .min(self.max.height)
144                .max(self.min.height),
145        };
146
147        Size::new(width, height)
148    }
149}