anathema_default_widgets/
expand.rs1use std::ops::ControlFlow;
2
3use anathema_geometry::Size;
4use anathema_value_resolver::AttributeStorage;
5use anathema_widgets::error::Result;
6use anathema_widgets::layout::{Constraints, LayoutCtx, PositionCtx};
7use anathema_widgets::paint::{PaintCtx, SizePos};
8use anathema_widgets::{LayoutForEach, PaintChildren, PositionChildren, Widget, WidgetId};
9
10use crate::layout::{Axis, single_layout};
11
12#[derive(Debug, Default)]
13pub struct Expand;
14
15impl Widget for Expand {
16 fn layout<'bp>(
17 &mut self,
18 children: LayoutForEach<'_, 'bp>,
19 constraints: Constraints,
20 id: WidgetId,
21 ctx: &mut LayoutCtx<'_, 'bp>,
22 ) -> Result<Size> {
23 let mut size = single_layout(children, constraints, ctx)?;
24
25 let attributes = ctx.attribute_storage.get(id);
26 match attributes.get_as::<Axis>("axis") {
27 Some(Axis::Horizontal) => size.width = constraints.max_width(),
28 Some(Axis::Vertical) => size.height = constraints.max_height(),
29 None => {
30 size.width = constraints.max_width();
31 size.height = constraints.max_height();
32 }
33 }
34
35 Ok(size)
36 }
37
38 fn position<'bp>(
39 &mut self,
40 mut children: PositionChildren<'_, 'bp>,
41 _attributes: WidgetId,
42 attribute_storage: &AttributeStorage<'bp>,
43 ctx: PositionCtx,
44 ) {
45 _ = children.each(|node, children| {
46 node.position(children, ctx.pos, attribute_storage, ctx.viewport);
47 ControlFlow::Break(())
48 });
49 }
50
51 fn paint<'bp>(
52 &mut self,
53 mut children: PaintChildren<'_, 'bp>,
54 _: WidgetId,
55 attribute_storage: &AttributeStorage<'bp>,
56 mut ctx: PaintCtx<'_, SizePos>,
57 ) {
58 _ = children.each(|child, children| {
59 let ctx = ctx.to_unsized();
60 child.paint(children, ctx, attribute_storage);
61 ControlFlow::Break(())
62 });
63 }
64}
65
66#[cfg(test)]
67mod test {
68 use crate::testing::TestRunner;
69
70 #[test]
71 fn hstack_expand_nospace() {
72 let tpl = "
73 border
74 container [width:12]
75 hstack
76 expand
77 text 'this is text'
78 ";
79
80 let expected = "
81 ╔══════════════╗
82 ║┌────────────┐║
83 ║│this is text│║
84 ║│ │║
85 ║└────────────┘║
86 ╚══════════════╝
87 ";
88
89 let mut runner = TestRunner::new(tpl, (14, 4));
90 let mut runner = runner.instance();
91 runner.render_assert(expected);
92 }
93
94 #[test]
95 fn vstack_expand_nospace() {
96 let tpl = "
97 border
98 container [height:1]
99 vstack
100 expand
101 text 'this is text'
102 ";
103
104 let expected = "
105 ╔═════════════════╗
106 ║┌───────────────┐║
107 ║│this is text │║
108 ║└───────────────┘║
109 ║ ║
110 ╚═════════════════╝
111 ";
112
113 let mut runner = TestRunner::new(tpl, (17, 4));
114 let mut runner = runner.instance();
115 runner.render_assert(expected);
116 }
117}