fission_core/ui/widgets/
grid.rs1use crate::internal::InternalLower;
2use crate::lowering::{InternalIrBuilder, InternalLoweringCx};
3use crate::ui::Widget;
4use fission_ir::{
5 op::{GridPlacement, GridTrack, LayoutOp, Op},
6 WidgetId,
7};
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Default, Clone, Serialize, Deserialize)]
31pub struct Grid {
32 pub id: Option<WidgetId>,
34 pub children: Vec<Widget>,
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
50impl InternalLower for Grid {
51 fn lower(&self, cx: &mut InternalLoweringCx) -> WidgetId {
52 let id = self.id.map(Into::into).unwrap_or_else(|| cx.next_node_id());
53 cx.push_scope(id);
54
55 let mut builder = InternalIrBuilder::new(
56 id,
57 Op::Layout(LayoutOp::Grid {
58 columns: self.columns.clone(),
59 rows: self.rows.clone(),
60 column_gap: self.column_gap,
61 row_gap: self.row_gap,
62 padding: self.padding,
63 }),
64 );
65
66 for child in &self.children {
67 builder.add_child(child.lower(cx));
68 }
69
70 cx.pop_scope();
71 builder.build(cx)
72 }
73}
74
75#[derive(Debug, Clone, Serialize, Deserialize)]
88pub struct GridItem {
89 pub id: Option<WidgetId>,
91 pub child: Widget,
93 pub row_start: GridPlacement,
95 pub row_end: GridPlacement,
97 pub col_start: GridPlacement,
99 pub col_end: GridPlacement,
101}
102
103impl Default for GridItem {
104 fn default() -> Self {
105 Self {
106 id: None,
107 child: crate::ui::Row::default().into(),
109 row_start: GridPlacement::Auto,
110 row_end: GridPlacement::Auto,
111 col_start: GridPlacement::Auto,
112 col_end: GridPlacement::Auto,
113 }
114 }
115}
116
117impl GridItem {
118 pub fn new(child: impl Into<Widget>) -> Self {
119 Self {
120 child: child.into(),
121 ..Default::default()
122 }
123 }
124
125 pub fn cell(mut self, row: i16, col: i16) -> Self {
126 self.row_start = GridPlacement::Line(row);
127 self.col_start = GridPlacement::Line(col);
128 self
129 }
130
131 pub fn span(mut self, row_span: u16, col_span: u16) -> Self {
132 self.row_end = GridPlacement::Span(row_span);
133 self.col_end = GridPlacement::Span(col_span);
134 self
135 }
136}
137
138impl InternalLower for GridItem {
139 fn lower(&self, cx: &mut InternalLoweringCx) -> WidgetId {
140 let id = self.id.map(Into::into).unwrap_or_else(|| cx.next_node_id());
141 cx.push_scope(id);
142
143 let child_id = self.child.lower(cx);
144
145 cx.pop_scope();
146
147 let mut builder = InternalIrBuilder::new(
148 id,
149 Op::Layout(LayoutOp::GridItem {
150 row_start: self.row_start,
151 row_end: self.row_end,
152 col_start: self.col_start,
153 col_end: self.col_end,
154 }),
155 );
156 builder.add_child(child_id);
157 builder.build(cx)
158 }
159}