1use crate::color::Color;
4use crate::device_scale::device_scale;
5use crate::event::{Event, EventResult};
6use crate::geometry::{Rect, Size};
7use crate::draw_ctx::DrawCtx;
8use crate::layout_props::{HAnchor, Insets, VAnchor, WidgetBase, resolve_fit_or_stretch};
9use crate::widget::Widget;
10
11pub struct Stack {
20 bounds: Rect,
21 children: Vec<Box<dyn Widget>>,
22 base: WidgetBase,
23}
24
25impl Stack {
26 pub fn new() -> Self {
27 Self { bounds: Rect::default(), children: Vec::new(), base: WidgetBase::new() }
28 }
29
30 pub fn add(mut self, child: Box<dyn Widget>) -> Self {
31 self.children.push(child);
32 self
33 }
34
35 pub fn with_margin(mut self, m: Insets) -> Self { self.base.margin = m; self }
36 pub fn with_h_anchor(mut self, h: HAnchor) -> Self { self.base.h_anchor = h; self }
37 pub fn with_v_anchor(mut self, v: VAnchor) -> Self { self.base.v_anchor = v; self }
38 pub fn with_min_size(mut self, s: Size) -> Self { self.base.min_size = s; self }
39 pub fn with_max_size(mut self, s: Size) -> Self { self.base.max_size = s; self }
40}
41
42impl Default for Stack { fn default() -> Self { Self::new() } }
43
44impl Widget for Stack {
45 fn type_name(&self) -> &'static str { "Stack" }
46 fn bounds(&self) -> Rect { self.bounds }
47 fn set_bounds(&mut self, b: Rect) { self.bounds = b; }
48 fn children(&self) -> &[Box<dyn Widget>] { &self.children }
49 fn children_mut(&mut self) -> &mut Vec<Box<dyn Widget>> { &mut self.children }
50
51 fn margin(&self) -> Insets { self.base.margin }
52 fn h_anchor(&self) -> HAnchor { self.base.h_anchor }
53 fn v_anchor(&self) -> VAnchor { self.base.v_anchor }
54 fn min_size(&self) -> Size { self.base.min_size }
55 fn max_size(&self) -> Size { self.base.max_size }
56
57 fn layout(&mut self, available: Size) -> Size {
58 for child in &mut self.children {
59 child.layout(available);
60 child.set_bounds(Rect::new(0.0, 0.0, available.width, available.height));
61 }
62
63 let mut i = 0;
82 let mut raised: Vec<Box<dyn Widget>> = Vec::new();
83 while i < self.children.len() {
84 if self.children[i].take_raise_request() {
85 raised.push(self.children.remove(i));
86 } else {
88 i += 1;
89 }
90 }
91 for r in raised {
92 self.children.push(r);
93 }
94
95 available
96 }
97
98 fn paint(&mut self, _ctx: &mut dyn DrawCtx) {}
99
100 fn on_event(&mut self, _: &Event) -> EventResult { EventResult::Ignored }
101}
102
103pub struct Padding {
109 bounds: Rect,
110 children: Vec<Box<dyn Widget>>,
111 base: WidgetBase,
112 insets: Insets,
113}
114
115impl Padding {
116 pub fn new(insets: Insets, child: Box<dyn Widget>) -> Self {
118 Self { bounds: Rect::default(), children: vec![child], base: WidgetBase::new(), insets }
119 }
120
121 pub fn uniform(amount: f64, child: Box<dyn Widget>) -> Self {
123 Self::new(Insets::all(amount), child)
124 }
125
126 pub fn with_margin(mut self, m: Insets) -> Self { self.base.margin = m; self }
127 pub fn with_h_anchor(mut self, h: HAnchor) -> Self { self.base.h_anchor = h; self }
128 pub fn with_v_anchor(mut self, v: VAnchor) -> Self { self.base.v_anchor = v; self }
129 pub fn with_min_size(mut self, s: Size) -> Self { self.base.min_size = s; self }
130 pub fn with_max_size(mut self, s: Size) -> Self { self.base.max_size = s; self }
131}
132
133impl Widget for Padding {
134 fn type_name(&self) -> &'static str { "Padding" }
135 fn bounds(&self) -> Rect { self.bounds }
136 fn set_bounds(&mut self, b: Rect) { self.bounds = b; }
137 fn children(&self) -> &[Box<dyn Widget>] { &self.children }
138 fn children_mut(&mut self) -> &mut Vec<Box<dyn Widget>> { &mut self.children }
139
140 fn margin(&self) -> Insets { self.base.margin }
141 fn h_anchor(&self) -> HAnchor { self.base.h_anchor }
142 fn v_anchor(&self) -> VAnchor { self.base.v_anchor }
143 fn min_size(&self) -> Size { self.base.min_size }
144 fn max_size(&self) -> Size { self.base.max_size }
145
146 fn layout(&mut self, available: Size) -> Size {
147 let p = &self.insets;
148 let inner = Size::new(
149 (available.width - p.left - p.right ).max(0.0),
150 (available.height - p.top - p.bottom).max(0.0),
151 );
152 if let Some(child) = self.children.first_mut() {
153 let desired = child.layout(inner);
154 child.set_bounds(Rect::new(p.left, p.bottom, desired.width, desired.height));
156 }
157 let content_w = self.children.first().map_or(0.0, |c| c.bounds().width);
159 let content_h = self.children.first().map_or(0.0, |c| c.bounds().height);
160 Size::new(content_w + p.left + p.right, content_h + p.top + p.bottom)
161 }
162
163 fn paint(&mut self, _ctx: &mut dyn DrawCtx) {}
164
165 fn on_event(&mut self, _: &Event) -> EventResult { EventResult::Ignored }
166}
167
168pub struct SizedBox {
178 bounds: Rect,
179 children: Vec<Box<dyn Widget>>,
180 base: WidgetBase,
181 pub width: Option<f64>,
182 pub height: Option<f64>,
183}
184
185impl SizedBox {
186 pub fn new() -> Self {
187 Self {
188 bounds: Rect::default(),
189 children: Vec::new(),
190 base: WidgetBase::new(),
191 width: None,
192 height: None,
193 }
194 }
195
196 pub fn with_width(mut self, w: f64) -> Self { self.width = Some(w); self }
197 pub fn with_height(mut self, h: f64) -> Self { self.height = Some(h); self }
198
199 pub fn with_child(mut self, child: Box<dyn Widget>) -> Self {
200 self.children.clear();
201 self.children.push(child);
202 self
203 }
204
205 pub fn fixed(width: f64, height: f64) -> Self {
207 Self::new().with_width(width).with_height(height)
208 }
209
210 pub fn with_margin(mut self, m: Insets) -> Self { self.base.margin = m; self }
211 pub fn with_h_anchor(mut self, h: HAnchor) -> Self { self.base.h_anchor = h; self }
212 pub fn with_v_anchor(mut self, v: VAnchor) -> Self { self.base.v_anchor = v; self }
213 pub fn with_min_size(mut self, s: Size) -> Self { self.base.min_size = s; self }
214 pub fn with_max_size(mut self, s: Size) -> Self { self.base.max_size = s; self }
215}
216
217impl Default for SizedBox { fn default() -> Self { Self::new() } }
218
219impl Widget for SizedBox {
220 fn type_name(&self) -> &'static str { "SizedBox" }
221 fn bounds(&self) -> Rect { self.bounds }
222 fn set_bounds(&mut self, b: Rect) { self.bounds = b; }
223 fn children(&self) -> &[Box<dyn Widget>] { &self.children }
224 fn children_mut(&mut self) -> &mut Vec<Box<dyn Widget>> { &mut self.children }
225
226 fn margin(&self) -> Insets { self.base.margin }
227 fn h_anchor(&self) -> HAnchor { self.base.h_anchor }
228 fn v_anchor(&self) -> VAnchor { self.base.v_anchor }
229 fn min_size(&self) -> Size { self.base.min_size }
230 fn max_size(&self) -> Size { self.base.max_size }
231
232 fn layout(&mut self, available: Size) -> Size {
233 let w = self.width.unwrap_or(available.width);
244 let mut h = self.height.unwrap_or_else(|| {
245 if self.children.is_empty() { 0.0 } else { available.height }
246 });
247
248 if let Some(child) = self.children.first_mut() {
249 let scale = device_scale();
250 let m = child.margin().scale(scale);
251 let slot_w = (w - m.left - m.right ).max(0.0);
252 let slot_h = (h - m.top - m.bottom).max(0.0);
253
254 let desired = child.layout(Size::new(slot_w, slot_h));
255
256 if self.height.is_none() {
259 h = (desired.height + m.vertical())
260 .clamp(self.base.min_size.height, self.base.max_size.height);
261 }
262
263 let h_anchor = child.h_anchor();
265 let min_w = child.min_size().width;
266 let max_w = child.max_size().width;
267 let child_w = if h_anchor.is_stretch() {
268 slot_w.clamp(min_w, max_w)
269 } else if h_anchor == HAnchor::MAX_FIT_OR_STRETCH {
270 resolve_fit_or_stretch(desired.width, slot_w, true).clamp(min_w, max_w)
271 } else if h_anchor == HAnchor::MIN_FIT_OR_STRETCH {
272 resolve_fit_or_stretch(desired.width, slot_w, false).clamp(min_w, max_w)
273 } else {
274 desired.width.clamp(min_w, max_w)
275 };
276
277 let child_x = if h_anchor.contains(HAnchor::RIGHT) && !h_anchor.contains(HAnchor::LEFT) {
278 (w - m.right - child_w).max(0.0)
279 } else if h_anchor.contains(HAnchor::CENTER) && !h_anchor.is_stretch() {
280 m.left + (slot_w - child_w) * 0.5
281 } else {
282 m.left
283 };
284
285 let v_anchor = child.v_anchor();
287 let min_h = child.min_size().height;
288 let max_h = child.max_size().height;
289 let child_h = if v_anchor.is_stretch() {
290 slot_h.clamp(min_h, max_h)
291 } else if v_anchor == VAnchor::MAX_FIT_OR_STRETCH {
292 resolve_fit_or_stretch(desired.height, slot_h, true).clamp(min_h, max_h)
293 } else if v_anchor == VAnchor::MIN_FIT_OR_STRETCH {
294 resolve_fit_or_stretch(desired.height, slot_h, false).clamp(min_h, max_h)
295 } else {
296 desired.height.clamp(min_h, max_h)
297 };
298
299 let child_w = if self.width.is_some() { child_w.min(slot_w) } else { child_w };
306 let child_h = if self.height.is_some() { child_h.min(slot_h) } else { child_h };
307
308 let child_y = if v_anchor.contains(VAnchor::TOP) && !v_anchor.contains(VAnchor::BOTTOM) {
309 (h - m.top - child_h).max(0.0)
310 } else if v_anchor.contains(VAnchor::CENTER) && !v_anchor.is_stretch() {
311 m.bottom + (slot_h - child_h) * 0.5
312 } else {
313 m.bottom
314 };
315
316 child.set_bounds(Rect::new(child_x, child_y, child_w, child_h));
317 }
318
319 Size::new(w, h)
320 }
321
322 fn paint(&mut self, _ctx: &mut dyn DrawCtx) {}
323
324 fn on_event(&mut self, _: &Event) -> EventResult { EventResult::Ignored }
325}
326
327pub struct Spacer {
336 bounds: Rect,
337 children: Vec<Box<dyn Widget>>,
338 base: WidgetBase,
339}
340
341impl Spacer {
342 pub fn new() -> Self {
343 Self { bounds: Rect::default(), children: Vec::new(), base: WidgetBase::new() }
344 }
345
346 pub fn with_margin(mut self, m: Insets) -> Self { self.base.margin = m; self }
347 pub fn with_h_anchor(mut self, h: HAnchor) -> Self { self.base.h_anchor = h; self }
348 pub fn with_v_anchor(mut self, v: VAnchor) -> Self { self.base.v_anchor = v; self }
349 pub fn with_min_size(mut self, s: Size) -> Self { self.base.min_size = s; self }
350 pub fn with_max_size(mut self, s: Size) -> Self { self.base.max_size = s; self }
351}
352
353impl Default for Spacer { fn default() -> Self { Self::new() } }
354
355impl Widget for Spacer {
356 fn type_name(&self) -> &'static str { "Spacer" }
357 fn bounds(&self) -> Rect { self.bounds }
358 fn set_bounds(&mut self, b: Rect) { self.bounds = b; }
359 fn children(&self) -> &[Box<dyn Widget>] { &self.children }
360 fn children_mut(&mut self) -> &mut Vec<Box<dyn Widget>> { &mut self.children }
361
362 fn margin(&self) -> Insets { self.base.margin }
363 fn h_anchor(&self) -> HAnchor { self.base.h_anchor }
364 fn v_anchor(&self) -> VAnchor { self.base.v_anchor }
365 fn min_size(&self) -> Size { self.base.min_size }
366 fn max_size(&self) -> Size { self.base.max_size }
367
368 fn layout(&mut self, available: Size) -> Size { available }
369
370 fn paint(&mut self, _ctx: &mut dyn DrawCtx) {}
371
372 fn on_event(&mut self, _: &Event) -> EventResult { EventResult::Ignored }
373}
374
375pub struct Separator {
385 bounds: Rect,
386 children: Vec<Box<dyn Widget>>,
387 base: WidgetBase,
388 vertical: bool,
389 line_inset: f64,
390 color: Option<Color>,
392}
393
394impl Separator {
395 pub fn horizontal() -> Self {
397 Self {
398 bounds: Rect::default(),
399 children: Vec::new(),
400 base: WidgetBase::new(),
401 vertical: false,
402 line_inset: 4.0,
403 color: None,
404 }
405 }
406
407 pub fn vertical() -> Self {
409 Self { vertical: true, ..Self::horizontal() }
410 }
411
412 pub fn with_line_inset(mut self, m: f64) -> Self { self.line_inset = m; self }
413 pub fn with_color(mut self, c: Color) -> Self { self.color = Some(c); self }
414
415 pub fn with_margin(mut self, m: Insets) -> Self { self.base.margin = m; self }
416 pub fn with_h_anchor(mut self, h: HAnchor) -> Self { self.base.h_anchor = h; self }
417 pub fn with_v_anchor(mut self, v: VAnchor) -> Self { self.base.v_anchor = v; self }
418 pub fn with_min_size(mut self, s: Size) -> Self { self.base.min_size = s; self }
419 pub fn with_max_size(mut self, s: Size) -> Self { self.base.max_size = s; self }
420}
421
422impl Widget for Separator {
423 fn type_name(&self) -> &'static str { "Separator" }
424 fn bounds(&self) -> Rect { self.bounds }
425 fn set_bounds(&mut self, b: Rect) { self.bounds = b; }
426 fn children(&self) -> &[Box<dyn Widget>] { &self.children }
427 fn children_mut(&mut self) -> &mut Vec<Box<dyn Widget>> { &mut self.children }
428
429 fn margin(&self) -> Insets { self.base.margin }
430 fn h_anchor(&self) -> HAnchor { self.base.h_anchor }
431 fn v_anchor(&self) -> VAnchor { self.base.v_anchor }
432 fn min_size(&self) -> Size { self.base.min_size }
433 fn max_size(&self) -> Size { self.base.max_size }
434
435 fn layout(&mut self, available: Size) -> Size {
436 if self.vertical {
437 Size::new(1.0 + self.line_inset * 2.0, available.height)
438 } else {
439 Size::new(available.width, 1.0 + self.line_inset * 2.0)
440 }
441 }
442
443 fn paint(&mut self, ctx: &mut dyn DrawCtx) {
444 let w = self.bounds.width;
445 let h = self.bounds.height;
446 let color = self.color.unwrap_or_else(|| ctx.visuals().separator);
447 ctx.set_fill_color(color);
448 ctx.begin_path();
449 if self.vertical {
450 ctx.rect(self.line_inset, 0.0, 1.0, h);
451 } else {
452 ctx.rect(0.0, self.line_inset, w, 1.0);
453 }
454 ctx.fill();
455 }
456
457 fn on_event(&mut self, _: &Event) -> EventResult { EventResult::Ignored }
458}