1mod insets;
8mod interaction;
9mod layout;
10mod semantics;
11
12use tessera_ui::{
13 AxisConstraint, CallbackWith, Dp, Modifier, Px, modifier::ModifierCapabilityExt as _,
14};
15
16use crate::alignment::Alignment;
17
18use layout::{
19 AlignmentParentDataModifierNode, ConstraintModifierNode, DefaultMinSizeModifierNode,
20 MinimumInteractiveModifierNode, OffsetModifierNode, PaddingModifierNode,
21 RequiredSizeModifierNode, WeightParentDataModifierNode,
22};
23
24pub use interaction::{
25 ClickableArgs, DragDelta, DraggableArgs, InteractionState, InteractionVisualState,
26 PointerEventContext, SelectableArgs, ToggleableArgs,
27};
28pub use layout::{
29 AlignmentParentData, MinimumInteractiveComponentEnforcement, Padding, WeightParentData,
30};
31pub use semantics::SemanticsArgs;
32
33pub trait ModifierExt {
35 fn window_insets_padding(self, insets: tessera_ui::WindowInsets) -> Modifier;
37
38 fn consume_window_insets(self, insets: tessera_ui::WindowInsets) -> Modifier;
40
41 fn window_insets_left_width(self, insets: tessera_ui::WindowInsets) -> Modifier;
43
44 fn window_insets_top_height(self, insets: tessera_ui::WindowInsets) -> Modifier;
46
47 fn window_insets_right_width(self, insets: tessera_ui::WindowInsets) -> Modifier;
49
50 fn window_insets_bottom_height(self, insets: tessera_ui::WindowInsets) -> Modifier;
52
53 fn padding(self, padding: Padding) -> Modifier;
55
56 fn padding_all(self, padding: Dp) -> Modifier;
58
59 fn padding_symmetric(self, horizontal: Dp, vertical: Dp) -> Modifier;
61
62 fn offset(self, x: Dp, y: Dp) -> Modifier;
64
65 fn size(self, width: Dp, height: Dp) -> Modifier;
67
68 fn required_size(self, width: Dp, height: Dp) -> Modifier;
70
71 fn required_width(self, width: Dp) -> Modifier;
73
74 fn required_height(self, height: Dp) -> Modifier;
76
77 fn default_min_size(self, min_width: Dp, min_height: Dp) -> Modifier;
80
81 fn width(self, width: Dp) -> Modifier;
83
84 fn height(self, height: Dp) -> Modifier;
86
87 fn size_in(
89 self,
90 min_width: Option<Dp>,
91 max_width: Option<Dp>,
92 min_height: Option<Dp>,
93 max_height: Option<Dp>,
94 ) -> Modifier;
95
96 fn constrain(self, width: Option<AxisConstraint>, height: Option<AxisConstraint>) -> Modifier;
98
99 fn fill_max_width(self) -> Modifier;
101
102 fn fill_max_height(self) -> Modifier;
104
105 fn fill_max_size(self) -> Modifier;
107
108 fn minimum_interactive_component_size(self) -> Modifier;
110
111 fn weight(self, weight: f32) -> Modifier;
113
114 fn align(self, alignment: Alignment) -> Modifier;
116
117 fn draggable<C>(self, on_drag_delta: C) -> Modifier
119 where
120 C: Into<CallbackWith<DragDelta, ()>>;
121
122 fn draggable_with(self, args: DraggableArgs) -> Modifier;
124
125 fn semantics(self, args: SemanticsArgs) -> Modifier;
127
128 fn clear_and_set_semantics(self, args: SemanticsArgs) -> Modifier;
130}
131
132impl ModifierExt for Modifier {
133 fn window_insets_padding(self, insets: tessera_ui::WindowInsets) -> Modifier {
134 self.push_layout(insets::InsetPadding {
135 insets,
136 consume_only: false,
137 })
138 }
139 fn consume_window_insets(self, insets: tessera_ui::WindowInsets) -> Modifier {
140 self.push_layout(insets::InsetPadding {
141 insets,
142 consume_only: true,
143 })
144 }
145 fn window_insets_left_width(self, insets: tessera_ui::WindowInsets) -> Modifier {
146 self.push_layout(insets::InsetSize { insets, edge: 0 })
147 }
148 fn window_insets_top_height(self, insets: tessera_ui::WindowInsets) -> Modifier {
149 self.push_layout(insets::InsetSize { insets, edge: 1 })
150 }
151 fn window_insets_right_width(self, insets: tessera_ui::WindowInsets) -> Modifier {
152 self.push_layout(insets::InsetSize { insets, edge: 2 })
153 }
154 fn window_insets_bottom_height(self, insets: tessera_ui::WindowInsets) -> Modifier {
155 self.push_layout(insets::InsetSize { insets, edge: 3 })
156 }
157
158 fn padding(self, padding: Padding) -> Modifier {
159 self.push_layout(PaddingModifierNode { padding })
160 }
161
162 fn padding_all(self, padding: Dp) -> Modifier {
163 self.padding(Padding::all(padding))
164 }
165
166 fn padding_symmetric(self, horizontal: Dp, vertical: Dp) -> Modifier {
167 self.padding(Padding::symmetric(horizontal, vertical))
168 }
169
170 fn offset(self, x: Dp, y: Dp) -> Modifier {
171 self.push_placement(OffsetModifierNode { x, y })
172 }
173
174 fn default_min_size(self, min_width: Dp, min_height: Dp) -> Modifier {
175 self.push_layout(DefaultMinSizeModifierNode {
176 min_width,
177 min_height,
178 })
179 }
180
181 fn size(self, width: Dp, height: Dp) -> Modifier {
182 let width_px: Px = width.into();
183 let height_px: Px = height.into();
184 self.push_layout(ConstraintModifierNode {
185 width_override: Some(AxisConstraint::exact(width_px)),
186 height_override: Some(AxisConstraint::exact(height_px)),
187 fill_width: false,
188 fill_height: false,
189 enforce_incoming: true,
190 })
191 }
192
193 fn required_size(self, width: Dp, height: Dp) -> Modifier {
194 let width_px: Px = width.into();
195 let height_px: Px = height.into();
196 self.push_layout(RequiredSizeModifierNode {
197 width: Some(AxisConstraint::exact(width_px)),
198 height: Some(AxisConstraint::exact(height_px)),
199 })
200 }
201
202 fn required_width(self, width: Dp) -> Modifier {
203 let width_px: Px = width.into();
204 self.push_layout(RequiredSizeModifierNode {
205 width: Some(AxisConstraint::exact(width_px)),
206 height: None,
207 })
208 }
209
210 fn required_height(self, height: Dp) -> Modifier {
211 let height_px: Px = height.into();
212 self.push_layout(RequiredSizeModifierNode {
213 width: None,
214 height: Some(AxisConstraint::exact(height_px)),
215 })
216 }
217 fn width(self, width: Dp) -> Modifier {
218 let width_px: Px = width.into();
219 self.push_layout(ConstraintModifierNode {
220 width_override: Some(AxisConstraint::exact(width_px)),
221 height_override: None,
222 fill_width: false,
223 fill_height: false,
224 enforce_incoming: true,
225 })
226 }
227
228 fn height(self, height: Dp) -> Modifier {
229 let height_px: Px = height.into();
230 self.push_layout(ConstraintModifierNode {
231 width_override: None,
232 height_override: Some(AxisConstraint::exact(height_px)),
233 fill_width: false,
234 fill_height: false,
235 enforce_incoming: true,
236 })
237 }
238
239 fn size_in(
240 self,
241 min_width: Option<Dp>,
242 max_width: Option<Dp>,
243 min_height: Option<Dp>,
244 max_height: Option<Dp>,
245 ) -> Modifier {
246 let width = AxisConstraint::new(
247 min_width.map(Into::into).unwrap_or(Px::ZERO),
248 max_width.map(Into::into),
249 );
250 let height = AxisConstraint::new(
251 min_height.map(Into::into).unwrap_or(Px::ZERO),
252 max_height.map(Into::into),
253 );
254 self.push_layout(ConstraintModifierNode {
255 width_override: Some(width),
256 height_override: Some(height),
257 fill_width: false,
258 fill_height: false,
259 enforce_incoming: true,
260 })
261 }
262
263 fn constrain(self, width: Option<AxisConstraint>, height: Option<AxisConstraint>) -> Modifier {
264 self.push_layout(ConstraintModifierNode {
265 width_override: width,
266 height_override: height,
267 fill_width: false,
268 fill_height: false,
269 enforce_incoming: false,
270 })
271 }
272
273 fn fill_max_width(self) -> Modifier {
274 self.push_layout(ConstraintModifierNode {
275 width_override: None,
276 height_override: None,
277 fill_width: true,
278 fill_height: false,
279 enforce_incoming: false,
280 })
281 }
282
283 fn fill_max_height(self) -> Modifier {
284 self.push_layout(ConstraintModifierNode {
285 width_override: None,
286 height_override: None,
287 fill_width: false,
288 fill_height: true,
289 enforce_incoming: false,
290 })
291 }
292
293 fn fill_max_size(self) -> Modifier {
294 self.push_layout(ConstraintModifierNode {
295 width_override: None,
296 height_override: None,
297 fill_width: true,
298 fill_height: true,
299 enforce_incoming: false,
300 })
301 }
302
303 fn minimum_interactive_component_size(self) -> Modifier {
304 self.push_layout(MinimumInteractiveModifierNode)
305 }
306
307 fn weight(self, weight: f32) -> Modifier {
308 self.push_parent_data(WeightParentDataModifierNode { weight })
309 }
310
311 fn align(self, alignment: Alignment) -> Modifier {
312 self.push_parent_data(AlignmentParentDataModifierNode { alignment })
313 }
314
315 fn draggable<C>(self, on_drag_delta: C) -> Modifier
316 where
317 C: Into<CallbackWith<DragDelta, ()>>,
318 {
319 self.draggable_with(DraggableArgs {
320 on_drag_delta: on_drag_delta.into(),
321 ..Default::default()
322 })
323 }
324
325 fn draggable_with(self, args: DraggableArgs) -> Modifier {
326 interaction::apply_draggable_modifier(self, args)
327 }
328
329 fn semantics(self, args: SemanticsArgs) -> Modifier {
330 semantics::apply_semantics_modifier(self, args)
331 }
332
333 fn clear_and_set_semantics(self, mut args: SemanticsArgs) -> Modifier {
334 args.merge_descendants = false;
335 semantics::apply_semantics_modifier(self, args)
336 }
337}