1use super::traits::{Lower, LowerDyn};
8use super::widgets::{
9 Align, Button, Checkbox, Clip, Column, Container, GestureDetector, FocusScope, Grid, GridItem, Icon, Image, LazyColumn, Overlay, Positioned, Radio, Row, SafeArea, Scroll, Slider, Spacer,
10 Switch, Text, TextInput, Transform, Video, ZStack,
11};
12use crate::lowering::LoweringContext;
13use fission_ir::{NodeId, Op, StructuralOp};
14use serde::{Deserialize, Serialize};
15use std::sync::Arc;
16
17#[derive(Clone, Debug, Serialize, Deserialize)]
39pub enum Node {
40 Row(Row),
42 Column(Column),
44 Align(Align),
46 FocusScope(FocusScope),
48 Clip(Clip),
50 Text(Text),
52 Transform(Transform),
54 Button(Button),
56 TextInput(TextInput),
58 Scroll(Scroll),
60 Image(Image),
62 Video(Video),
64 ZStack(ZStack),
66 Overlay(Overlay),
68 Container(Container),
70 GestureDetector(GestureDetector),
72 Grid(Grid),
74 GridItem(GridItem),
76 Checkbox(Checkbox),
78 Switch(Switch),
80 Radio(Radio),
82 SafeArea(SafeArea),
84 Positioned(Positioned),
86 Spacer(Spacer),
88 Slider(Slider),
90 LazyColumn(LazyColumn),
92 Icon(Icon),
94 Custom(CustomNode),
96}
97
98impl Node {
99 pub fn lower(&self, cx: &mut LoweringContext) -> NodeId {
100 match self {
101 Node::Row(w) => w.lower(cx),
102 Node::Column(w) => w.lower(cx),
103 Node::Align(w) => w.lower(cx),
104 Node::FocusScope(w) => w.lower(cx),
105 Node::Clip(w) => w.lower(cx),
106 Node::Text(w) => w.lower(cx),
107 Node::Transform(w) => w.lower(cx),
108 Node::Button(w) => w.lower(cx),
109 Node::TextInput(w) => w.lower(cx),
110 Node::Scroll(w) => w.lower(cx),
111 Node::Image(w) => w.lower(cx),
112 Node::Video(w) => w.lower(cx),
113 Node::ZStack(w) => w.lower(cx),
114 Node::Overlay(w) => w.lower(cx),
115 Node::Container(w) => w.lower(cx),
116 Node::GestureDetector(w) => w.lower(cx),
117 Node::Grid(w) => w.lower(cx),
118 Node::GridItem(w) => w.lower(cx),
119 Node::Checkbox(w) => w.lower(cx),
120 Node::Switch(w) => w.lower(cx),
121 Node::Radio(w) => w.lower(cx),
122 Node::SafeArea(w) => w.lower(cx),
123 Node::Positioned(w) => w.lower(cx),
124 Node::Spacer(w) => w.lower(cx),
125 Node::Slider(w) => w.lower(cx),
126 Node::LazyColumn(w) => w.lower(cx),
127 Node::Icon(w) => w.lower(cx),
128 Node::Custom(w) => {
129 let lowerer = w.lowerer.as_ref().expect("CustomNode lowerer must be set");
130 let child_id = lowerer.lower_dyn(cx);
131 let wrapper = cx.next_node_id();
132 let mut builder = crate::lowering::NodeBuilder::new(
133 wrapper,
134 Op::Structural(StructuralOp::Group {
135 stable_hash: lowerer.stable_key(),
136 }),
137 );
138 builder.add_child(child_id);
139 builder.build(cx)
140 }
141 }
142 }
143}
144
145impl From<Row> for Node {
146 fn from(w: Row) -> Self {
147 Node::Row(w)
148 }
149}
150impl From<Column> for Node {
151 fn from(w: Column) -> Self {
152 Node::Column(w)
153 }
154}
155impl From<Align> for Node {
156 fn from(w: Align) -> Self {
157 Node::Align(w)
158 }
159}
160impl From<FocusScope> for Node {
161 fn from(w: FocusScope) -> Self {
162 Node::FocusScope(w)
163 }
164}
165impl From<Clip> for Node {
166 fn from(w: Clip) -> Self {
167 Node::Clip(w)
168 }
169}
170impl From<Text> for Node {
171 fn from(w: Text) -> Self {
172 Node::Text(w)
173 }
174}
175impl From<Transform> for Node {
176 fn from(w: Transform) -> Self {
177 Node::Transform(w)
178 }
179}
180impl From<Button> for Node {
181 fn from(w: Button) -> Self {
182 Node::Button(w)
183 }
184}
185impl From<TextInput> for Node {
186 fn from(w: TextInput) -> Self {
187 Node::TextInput(w)
188 }
189}
190impl From<Scroll> for Node {
191 fn from(w: Scroll) -> Self {
192 Node::Scroll(w)
193 }
194}
195impl From<Image> for Node {
196 fn from(w: Image) -> Self {
197 Node::Image(w)
198 }
199}
200impl From<ZStack> for Node {
201 fn from(w: ZStack) -> Self {
202 Node::ZStack(w)
203 }
204}
205impl From<Overlay> for Node {
206 fn from(w: Overlay) -> Self {
207 Node::Overlay(w)
208 }
209}
210impl From<Container> for Node {
211 fn from(w: Container) -> Self {
212 Node::Container(w)
213 }
214}
215impl From<GestureDetector> for Node {
216 fn from(w: GestureDetector) -> Self {
217 Node::GestureDetector(w)
218 }
219}
220impl From<Grid> for Node {
221 fn from(w: Grid) -> Self {
222 Node::Grid(w)
223 }
224}
225impl From<GridItem> for Node {
226 fn from(w: GridItem) -> Self {
227 Node::GridItem(w)
228 }
229}
230impl From<Checkbox> for Node {
231 fn from(w: Checkbox) -> Self {
232 Node::Checkbox(w)
233 }
234}
235impl From<Switch> for Node {
236 fn from(w: Switch) -> Self {
237 Node::Switch(w)
238 }
239}
240impl From<Radio> for Node {
241 fn from(w: Radio) -> Self {
242 Node::Radio(w)
243 }
244}
245impl From<SafeArea> for Node {
246 fn from(w: SafeArea) -> Self {
247 Node::SafeArea(w)
248 }
249}
250impl From<Positioned> for Node {
251 fn from(w: Positioned) -> Self {
252 Node::Positioned(w)
253 }
254}
255impl From<Spacer> for Node {
256 fn from(w: Spacer) -> Self {
257 Node::Spacer(w)
258 }
259}
260impl From<Slider> for Node {
261 fn from(w: Slider) -> Self {
262 Node::Slider(w)
263 }
264}
265impl From<LazyColumn> for Node {
266 fn from(w: LazyColumn) -> Self {
267 Node::LazyColumn(w)
268 }
269}
270impl From<Icon> for Node {
271 fn from(w: Icon) -> Self {
272 Node::Icon(w)
273 }
274}
275
276#[derive(Clone, Debug, Serialize, Deserialize)]
292pub struct CustomNode {
293 pub debug_tag: String,
295 #[serde(skip)]
297 pub lowerer: Option<Arc<dyn LowerDyn>>,
298}