fission_core/ui/widgets/
grid.rs1use crate::lowering::{LoweringContext, NodeBuilder};
2use crate::ui::traits::Lower;
3use crate::ui::Node;
4use fission_ir::{
5 op::{GridPlacement, GridTrack, LayoutOp, Op},
6 NodeId,
7};
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Default, Clone, Serialize, Deserialize)]
31pub struct Grid {
32 pub id: Option<NodeId>,
34 pub children: Vec<Node>,
36 pub columns: Vec<GridTrack>,
38 pub rows: Vec<GridTrack>,
40 pub column_gap: Option<f32>,
42 pub row_gap: Option<f32>,
44 pub padding: [f32; 4],
46}
47
48impl Grid {
49 pub fn into_node(self) -> crate::ui::Node {
50 crate::ui::Node::Grid(self)
51 }
52}
53
54impl Lower for Grid {
55 fn lower(&self, cx: &mut LoweringContext) -> NodeId {
56 let id = self.id.unwrap_or_else(|| cx.next_node_id());
57 cx.push_scope(id);
58
59 let mut builder = NodeBuilder::new(
60 id,
61 Op::Layout(LayoutOp::Grid {
62 columns: self.columns.clone(),
63 rows: self.rows.clone(),
64 column_gap: self.column_gap,
65 row_gap: self.row_gap,
66 padding: self.padding,
67 }),
68 );
69
70 for child in &self.children {
71 builder.add_child(child.lower(cx));
72 }
73
74 cx.pop_scope();
75 builder.build(cx)
76 }
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize)]
92pub struct GridItem {
93 pub id: Option<NodeId>,
95 pub child: Box<Node>,
97 pub row_start: GridPlacement,
99 pub row_end: GridPlacement,
101 pub col_start: GridPlacement,
103 pub col_end: GridPlacement,
105}
106
107impl Default for GridItem {
108 fn default() -> Self {
109 Self {
110 id: None,
111 child: Box::new(Node::Row(crate::ui::Row::default())),
113 row_start: GridPlacement::Auto,
114 row_end: GridPlacement::Auto,
115 col_start: GridPlacement::Auto,
116 col_end: GridPlacement::Auto,
117 }
118 }
119}
120
121impl GridItem {
122 pub fn new(child: Node) -> Self {
123 Self {
124 child: Box::new(child),
125 ..Default::default()
126 }
127 }
128
129 pub fn cell(mut self, row: i16, col: i16) -> Self {
130 self.row_start = GridPlacement::Line(row);
131 self.col_start = GridPlacement::Line(col);
132 self
133 }
134
135 pub fn span(mut self, row_span: u16, col_span: u16) -> Self {
136 self.row_end = GridPlacement::Span(row_span);
137 self.col_end = GridPlacement::Span(col_span);
138 self
139 }
140
141 pub fn into_node(self) -> Node {
142 Node::GridItem(self)
143 }
144}
145
146impl Lower for GridItem {
147 fn lower(&self, cx: &mut LoweringContext) -> NodeId {
148 let id = self.id.unwrap_or_else(|| cx.next_node_id());
149 cx.push_scope(id);
150
151 let child_id = self.child.lower(cx);
152
153 cx.pop_scope();
154
155 let mut builder = NodeBuilder::new(
156 id,
157 Op::Layout(LayoutOp::GridItem {
158 row_start: self.row_start,
159 row_end: self.row_end,
160 col_start: self.col_start,
161 col_end: self.col_end,
162 })
163 );
164 builder.add_child(child_id);
165 builder.build(cx)
166 }
167}