fission_core/ui/widgets/
container.rs1use crate::lowering::{LoweringContext, NodeBuilder};
2use crate::ui::traits::Lower;
3use crate::ui::Node;
4use fission_ir::{
5 op::{BoxShadow, Color, Fill, LayoutOp, Op, PaintOp, Stroke},
6 NodeId,
7};
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct Container {
29 pub id: Option<NodeId>,
31 pub child: Option<Box<Node>>,
33
34 pub width: Option<f32>,
38 pub height: Option<f32>,
40 pub min_width: Option<f32>,
42 pub max_width: Option<f32>,
44 pub min_height: Option<f32>,
46 pub max_height: Option<f32>,
48 pub padding: [f32; 4],
50 pub flex_grow: f32,
52 pub flex_shrink: f32,
54
55 pub background_color: Option<Color>,
59 pub border_color: Option<Color>,
61 pub border_width: f32,
63 pub border_radius: f32,
65 pub shadow: Option<BoxShadow>,
67}
68
69impl Default for Container {
70 fn default() -> Self {
71 Self {
72 id: None,
73 child: None,
74 width: None,
75 height: None,
76 min_width: None,
77 max_width: None,
78 min_height: None,
79 max_height: None,
80 padding: [0.0; 4],
81 flex_grow: 0.0,
82 flex_shrink: 1.0,
83 background_color: None,
84 border_color: None,
85 border_width: 0.0,
86 border_radius: 0.0,
87 shadow: None,
88 }
89 }
90}
91impl Container {
92 pub fn new(child: Node) -> Self {
93 Self {
94 child: Some(Box::new(child)),
95 ..Default::default()
96 }
97 }
98
99 pub fn id(mut self, id: NodeId) -> Self {
100 self.id = Some(id);
101 self
102 }
103
104 pub fn size(mut self, w: f32, h: f32) -> Self {
105 self.width = Some(w);
106 self.height = Some(h);
107 self
108 }
109
110 pub fn width(mut self, w: f32) -> Self {
111 self.width = Some(w);
112 self
113 }
114
115 pub fn height(mut self, h: f32) -> Self {
116 self.height = Some(h);
117 self
118 }
119
120 pub fn min_width(mut self, w: f32) -> Self {
121 self.min_width = Some(w);
122 self
123 }
124
125 pub fn max_width(mut self, w: f32) -> Self {
126 self.max_width = Some(w);
127 self
128 }
129
130 pub fn min_height(mut self, h: f32) -> Self {
131 self.min_height = Some(h);
132 self
133 }
134
135 pub fn max_height(mut self, h: f32) -> Self {
136 self.max_height = Some(h);
137 self
138 }
139
140 pub fn padding_all(mut self, p: f32) -> Self {
141 self.padding = [p; 4];
142 self
143 }
144
145 pub fn flex_grow(mut self, grow: f32) -> Self {
146 self.flex_grow = grow;
147 self
148 }
149
150 pub fn flex_shrink(mut self, shrink: f32) -> Self {
151 self.flex_shrink = shrink;
152 self
153 }
154
155 pub fn bg(mut self, color: Color) -> Self {
156 self.background_color = Some(color);
157 self
158 }
159
160 pub fn border(mut self, color: Color, width: f32) -> Self {
161 self.border_color = Some(color);
162 self.border_width = width;
163 self
164 }
165
166 pub fn border_radius(mut self, radius: f32) -> Self {
167 self.border_radius = radius;
168 self
169 }
170
171 pub fn shadow(mut self, shadow: BoxShadow) -> Self {
172 self.shadow = Some(shadow);
173 self
174 }
175
176 pub fn into_node(self) -> Node {
177 Node::Container(self)
178 }
179}
180
181impl Lower for Container {
182 fn lower(&self, cx: &mut LoweringContext) -> NodeId {
183 let id = self.id.unwrap_or_else(|| cx.next_node_id());
184 cx.push_scope(id);
185
186 let mut children_ids = Vec::new();
187
188 if self.background_color.is_some() || self.border_color.is_some() || self.shadow.is_some() {
190 let paint = NodeBuilder::new(cx.next_node_id(), Op::Paint(PaintOp::DrawRect {
191 fill: self.background_color.map(|c| Fill { color: c }),
192 stroke: self.border_color.map(|c| Stroke { color: c, width: self.border_width }),
193 corner_radius: self.border_radius,
194 shadow: self.shadow,
195 })).build(cx);
196 children_ids.push(paint);
197 }
198
199 if let Some(child) = &self.child {
201 children_ids.push(child.lower(cx));
202 }
203
204 cx.pop_scope();
205
206 let mut layout = NodeBuilder::new(id, Op::Layout(LayoutOp::Box {
207 width: self.width,
208 height: self.height,
209 min_width: self.min_width,
210 max_width: self.max_width,
211 min_height: self.min_height,
212 max_height: self.max_height,
213 padding: self.padding,
214 flex_grow: self.flex_grow,
215 flex_shrink: self.flex_shrink,
216 aspect_ratio: None,
217 }));
218
219 for cid in children_ids {
220 layout.add_child(cid);
221 }
222
223 layout.build(cx)
224 }
225}