1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use crate::{Lower, LoweringContext, Node, NodeBuilder};
use fission_ir::{FlexDirection, LayoutOp, NodeId, Op, Semantics};
use fission_ir::op::{FlexWrap, AlignItems, JustifyContent};
use serde::{Deserialize, Serialize};
/// A horizontal flex container that lays out children in a row.
///
/// Children are arranged left-to-right (in LTR locales). Use `align_items` to
/// control cross-axis (vertical) alignment and `justify_content` for main-axis
/// (horizontal) distribution.
///
/// # Example
///
/// ```rust,ignore
/// Row {
/// children: vec![
/// Icon::path("M12 2L2 22h20L12 2z").into_node().into(),
/// Text::new("Warning").into_node().into(),
/// ],
/// gap: Some(8.0),
/// align_items: AlignItems::Center,
/// justify_content: JustifyContent::Start,
/// ..Default::default()
/// }
/// ```
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Row {
/// Explicit node identity.
pub id: Option<NodeId>,
/// The child widgets laid out left-to-right.
pub children: Vec<Node>,
/// Custom semantics for accessibility.
pub semantics: Option<Semantics>,
/// Flex grow factor.
pub flex_grow: f32,
/// Flex shrink factor.
pub flex_shrink: f32,
/// Spacing between children in layout points.
pub gap: Option<f32>,
/// Whether children wrap to a new line when they overflow.
pub wrap: FlexWrap,
/// Cross-axis (vertical) alignment of children (default: `Center`).
pub align_items: AlignItems,
/// Main-axis (horizontal) distribution of children (default: `Start`).
pub justify_content: JustifyContent,
}
impl Default for Row {
fn default() -> Self {
Self {
id: None,
children: Vec::new(),
semantics: None,
flex_grow: 0.0,
flex_shrink: 1.0,
gap: None,
wrap: FlexWrap::NoWrap,
align_items: AlignItems::Center,
justify_content: JustifyContent::Start,
}
}
}
impl Row {
pub fn children(mut self, children: Vec<Node>) -> Self {
self.children = children;
self
}
pub fn flex_grow(mut self, flex_grow: f32) -> Self {
self.flex_grow = flex_grow;
self
}
pub fn gap(mut self, gap: f32) -> Self {
self.gap = Some(gap);
self
}
pub fn align_items(mut self, align: AlignItems) -> Self {
self.align_items = align;
self
}
pub fn justify_content(mut self, justify: JustifyContent) -> Self {
self.justify_content = justify;
self
}
pub fn into_node(self) -> Node {
Node::Row(self)
}
}
impl Lower for Row {
fn lower(&self, cx: &mut LoweringContext) -> NodeId {
let layout_id = self.id.unwrap_or_else(|| cx.next_node_id());
cx.push_scope(layout_id);
let mut builder = NodeBuilder::new(
layout_id,
Op::Layout(LayoutOp::Flex {
direction: FlexDirection::Row,
wrap: self.wrap,
flex_grow: self.flex_grow,
flex_shrink: self.flex_shrink,
padding: [0.0; 4],
gap: self.gap,
align_items: self.align_items,
justify_content: self.justify_content,
}),
);
for child in &self.children {
builder.add_child(child.lower(cx));
}
cx.pop_scope();
let layout_id = builder.build(cx);
if let Some(s) = &self.semantics {
let mut semantics_builder =
NodeBuilder::new(cx.next_node_id(), Op::Semantics(s.clone()));
semantics_builder.add_child(layout_id);
return semantics_builder.build(cx);
}
layout_id
}
}