ailloli_ui_core/style/layout_style.rs
1//! Declarative per-widget dimensions, bounds, margin, and padding.
2
3use crate::geometry::EdgeInsets;
4
5use super::Length;
6
7/// Per-widget layout: dimensions, min/max, margin, and padding.
8///
9/// # Examples
10///
11/// ```
12/// use ailloli_ui_core::style::{LayoutStyle, Length};
13/// let layout = LayoutStyle::new().width(120.0).fill_height().padding(8.0);
14/// assert_eq!(layout.width, Length::Px(120.0));
15/// ```
16#[derive(Debug, Clone, Copy, PartialEq)]
17pub struct LayoutStyle {
18 /// Preferred width; [`Length::Auto`] uses intrinsic width.
19 pub width: Length,
20 /// Preferred height; [`Length::Auto`] uses intrinsic height.
21 pub height: Length,
22 /// Optional minimum width; [`Length::Auto`] means no explicit minimum.
23 pub min_width: Length,
24 /// Optional maximum width; [`Length::Auto`] means no explicit maximum.
25 pub max_width: Length,
26 /// Optional minimum height; [`Length::Auto`] means no explicit minimum.
27 pub min_height: Length,
28 /// Optional maximum height; [`Length::Auto`] means no explicit maximum.
29 pub max_height: Length,
30 /// Space outside the widget border in logical pixels.
31 pub margin: EdgeInsets,
32 /// Space between border and content in logical pixels.
33 pub padding: EdgeInsets,
34}
35
36impl Default for LayoutStyle {
37 fn default() -> Self {
38 Self {
39 width: Length::Auto,
40 height: Length::Auto,
41 min_width: Length::Auto,
42 max_width: Length::Auto,
43 min_height: Length::Auto,
44 max_height: Length::Auto,
45 margin: EdgeInsets::default(),
46 padding: EdgeInsets::default(),
47 }
48 }
49}
50
51impl LayoutStyle {
52 /// Creates an entirely automatic layout with zero margin and padding.
53 ///
54 /// # Examples
55 ///
56 /// ```
57 /// use ailloli_ui_core::style::{LayoutStyle, Length};
58 /// assert_eq!(LayoutStyle::new().width, Length::Auto);
59 /// ```
60 pub fn new() -> Self {
61 Self::default()
62 }
63
64 /// Replaces the preferred width.
65 ///
66 /// # Examples
67 ///
68 /// ```
69 /// use ailloli_ui_core::style::{LayoutStyle, Length};
70 /// assert_eq!(LayoutStyle::new().width(20.0).width, Length::Px(20.0));
71 /// ```
72 pub fn width(mut self, width: impl Into<Length>) -> Self {
73 self.width = width.into();
74 self
75 }
76
77 /// Replaces the preferred height.
78 ///
79 /// # Examples
80 ///
81 /// ```
82 /// use ailloli_ui_core::style::{LayoutStyle, Length};
83 /// assert_eq!(LayoutStyle::new().height(20.0).height, Length::Px(20.0));
84 /// ```
85 pub fn height(mut self, height: impl Into<Length>) -> Self {
86 self.height = height.into();
87 self
88 }
89
90 /// Sets both preferred axes to [`Length::Fill`].
91 ///
92 /// # Examples
93 ///
94 /// ```
95 /// use ailloli_ui_core::style::{LayoutStyle, Length};
96 /// let layout = LayoutStyle::new().fill();
97 /// assert_eq!((layout.width, layout.height), (Length::Fill, Length::Fill));
98 /// ```
99 pub fn fill(mut self) -> Self {
100 self.width = Length::Fill;
101 self.height = Length::Fill;
102 self
103 }
104
105 /// Sets only preferred width to [`Length::Fill`].
106 ///
107 /// # Examples
108 ///
109 /// ```
110 /// use ailloli_ui_core::style::{LayoutStyle, Length};
111 /// assert_eq!(LayoutStyle::new().fill_width().width, Length::Fill);
112 /// ```
113 pub fn fill_width(mut self) -> Self {
114 self.width = Length::Fill;
115 self
116 }
117
118 /// Sets only preferred height to [`Length::Fill`].
119 ///
120 /// # Examples
121 ///
122 /// ```
123 /// use ailloli_ui_core::style::{LayoutStyle, Length};
124 /// assert_eq!(LayoutStyle::new().fill_height().height, Length::Fill);
125 /// ```
126 pub fn fill_height(mut self) -> Self {
127 self.height = Length::Fill;
128 self
129 }
130
131 /// Replaces the minimum-width declaration.
132 ///
133 /// # Examples
134 ///
135 /// ```
136 /// use ailloli_ui_core::style::{LayoutStyle, Length};
137 /// assert_eq!(LayoutStyle::new().min_width(10.0).min_width, Length::Px(10.0));
138 /// ```
139 pub fn min_width(mut self, value: impl Into<Length>) -> Self {
140 self.min_width = value.into();
141 self
142 }
143
144 /// Replaces the maximum-width declaration.
145 ///
146 /// # Examples
147 ///
148 /// ```
149 /// use ailloli_ui_core::style::{LayoutStyle, Length};
150 /// assert_eq!(LayoutStyle::new().max_width(10.0).max_width, Length::Px(10.0));
151 /// ```
152 pub fn max_width(mut self, value: impl Into<Length>) -> Self {
153 self.max_width = value.into();
154 self
155 }
156
157 /// Replaces the minimum-height declaration.
158 ///
159 /// # Examples
160 ///
161 /// ```
162 /// use ailloli_ui_core::style::{LayoutStyle, Length};
163 /// assert_eq!(LayoutStyle::new().min_height(10.0).min_height, Length::Px(10.0));
164 /// ```
165 pub fn min_height(mut self, value: impl Into<Length>) -> Self {
166 self.min_height = value.into();
167 self
168 }
169
170 /// Replaces the maximum-height declaration.
171 ///
172 /// # Examples
173 ///
174 /// ```
175 /// use ailloli_ui_core::style::{LayoutStyle, Length};
176 /// assert_eq!(LayoutStyle::new().max_height(10.0).max_height, Length::Px(10.0));
177 /// ```
178 pub fn max_height(mut self, value: impl Into<Length>) -> Self {
179 self.max_height = value.into();
180 self
181 }
182
183 /// Replaces all four padding edges with `value` logical pixels.
184 ///
185 /// The value is stored verbatim, including negative or non-finite input.
186 ///
187 /// # Examples
188 ///
189 /// ```
190 /// use ailloli_ui_core::style::LayoutStyle;
191 /// assert_eq!(LayoutStyle::new().padding(8.0).padding.left, 8.0);
192 /// ```
193 pub fn padding(mut self, value: f32) -> Self {
194 self.padding = EdgeInsets::all(value);
195 self
196 }
197
198 /// Replaces all four margin edges with `value` logical pixels.
199 ///
200 /// The value is stored verbatim, including negative or non-finite input.
201 ///
202 /// # Examples
203 ///
204 /// ```
205 /// use ailloli_ui_core::style::LayoutStyle;
206 /// assert_eq!(LayoutStyle::new().margin(8.0).margin.top, 8.0);
207 /// ```
208 pub fn margin(mut self, value: f32) -> Self {
209 self.margin = EdgeInsets::all(value);
210 self
211 }
212}