anathema_default_widgets/stacks/
row.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::{LayoutChildren, PositionChildren, Widget, WidgetId};
8
9use crate::layout::Axis;
10use crate::stacks::Stack;
11
12pub struct Row(Stack);
13
14impl Default for Row {
15 fn default() -> Self {
16 Self(Stack(Axis::Horizontal))
17 }
18}
19
20impl Widget for Row {
21 fn layout<'bp>(
22 &mut self,
23 children: LayoutChildren<'_, 'bp>,
24 constraints: Constraints,
25 id: WidgetId,
26 ctx: &mut LayoutCtx<'_, 'bp>,
27 ) -> Result<Size> {
28 self.0.layout(children, constraints, id, ctx)
29 }
30
31 fn position<'bp>(
32 &mut self,
33 mut children: PositionChildren<'_, 'bp>,
34 _: WidgetId,
35 attribute_storage: &AttributeStorage<'bp>,
36 mut ctx: PositionCtx,
37 ) {
38 let y_offset = (ctx.inner_size.height / 2) as i32;
39
40 _ = children.each(|child, children| {
41 let size = child.size();
42 let child_height = size.height as i32;
43 let y = y_offset - child_height / 2;
44
45 let mut pos = ctx.pos;
46 pos.y += y;
47 child.position(children, pos, attribute_storage, ctx.viewport);
48 ctx.pos.x += size.width as i32;
49 ControlFlow::Continue(())
50 });
51 }
52}
53
54#[cfg(test)]
55mod test {
56
57 use crate::testing::TestRunner;
58
59 #[test]
60 fn basic_row() {
61 let tpl = "
62 row
63 text 'a'
64 border
65 text 'b'
66 ";
67
68 let expected = "
69 ╔════╗
70 ║ ┌─┐║
71 ║a│b│║
72 ║ └─┘║
73 ╚════╝
74 ";
75
76 TestRunner::new(tpl, (4, 3)).instance().render_assert(expected);
77 }
78}