1use crate::{
2 PrefabValue, PropsData, Scalar,
3 props::Props,
4 widget::{
5 WidgetId,
6 node::{WidgetNode, WidgetNodePrefab},
7 unit::{WidgetUnit, WidgetUnitData},
8 utils::{Rect, Transform},
9 },
10};
11use serde::{Deserialize, Serialize};
12use std::convert::TryFrom;
13
14#[derive(PropsData, Debug, Clone, Serialize, Deserialize)]
15#[props_data(crate::props::PropsData)]
16#[prefab(crate::Prefab)]
17pub struct FlexBoxItemLayout {
18 #[serde(default)]
19 #[serde(skip_serializing_if = "Option::is_none")]
20 pub basis: Option<Scalar>,
21 #[serde(default = "FlexBoxItemLayout::default_fill")]
22 pub fill: Scalar,
23 #[serde(default = "FlexBoxItemLayout::default_grow")]
24 pub grow: Scalar,
25 #[serde(default = "FlexBoxItemLayout::default_shrink")]
26 pub shrink: Scalar,
27 #[serde(default)]
28 pub margin: Rect,
29 #[serde(default)]
30 pub align: Scalar,
31}
32
33impl FlexBoxItemLayout {
34 fn default_fill() -> Scalar {
35 1.0
36 }
37
38 fn default_grow() -> Scalar {
39 1.0
40 }
41
42 fn default_shrink() -> Scalar {
43 1.0
44 }
45
46 pub fn cleared() -> Self {
47 Self {
48 fill: 0.0,
49 grow: 0.0,
50 shrink: 0.0,
51 ..Default::default()
52 }
53 }
54
55 pub fn no_growing_and_shrinking() -> Self {
56 Self {
57 grow: 0.0,
58 shrink: 1.0,
59 ..Default::default()
60 }
61 }
62}
63
64impl Default for FlexBoxItemLayout {
65 fn default() -> Self {
66 Self {
67 basis: None,
68 fill: Self::default_fill(),
69 grow: Self::default_grow(),
70 shrink: Self::default_shrink(),
71 margin: Default::default(),
72 align: 0.0,
73 }
74 }
75}
76
77#[derive(Debug, Default, Clone, Serialize, Deserialize)]
78pub struct FlexBoxItem {
79 #[serde(default)]
80 pub slot: WidgetUnit,
81 #[serde(default)]
82 pub layout: FlexBoxItemLayout,
83}
84
85impl TryFrom<FlexBoxItemNode> for FlexBoxItem {
86 type Error = ();
87
88 fn try_from(node: FlexBoxItemNode) -> Result<Self, Self::Error> {
89 let FlexBoxItemNode { slot, layout } = node;
90 Ok(Self {
91 slot: WidgetUnit::try_from(slot)?,
92 layout,
93 })
94 }
95}
96
97#[derive(Debug, Default, Clone)]
98pub struct FlexBoxItemNode {
99 pub slot: WidgetNode,
100 pub layout: FlexBoxItemLayout,
101}
102
103#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
104pub enum FlexBoxDirection {
105 #[default]
106 HorizontalLeftToRight,
107 HorizontalRightToLeft,
108 VerticalTopToBottom,
109 VerticalBottomToTop,
110}
111
112impl FlexBoxDirection {
113 pub fn is_horizontal(&self) -> bool {
114 *self == Self::HorizontalLeftToRight || *self == Self::HorizontalRightToLeft
115 }
116
117 pub fn is_vertical(&self) -> bool {
118 *self == Self::VerticalTopToBottom || *self == Self::VerticalBottomToTop
119 }
120
121 pub fn is_order_ascending(&self) -> bool {
122 *self == Self::HorizontalLeftToRight || *self == Self::VerticalTopToBottom
123 }
124
125 pub fn is_order_descending(&self) -> bool {
126 *self == Self::HorizontalRightToLeft || *self == Self::VerticalBottomToTop
127 }
128}
129
130#[derive(Debug, Default, Clone, Serialize, Deserialize)]
131pub struct FlexBox {
132 #[serde(default)]
133 pub id: WidgetId,
134 #[serde(default)]
135 #[serde(skip_serializing_if = "Vec::is_empty")]
136 pub items: Vec<FlexBoxItem>,
137 #[serde(default)]
138 pub direction: FlexBoxDirection,
139 #[serde(default)]
140 pub separation: Scalar,
141 #[serde(default)]
142 pub wrap: bool,
143 #[serde(default)]
144 pub transform: Transform,
145}
146
147impl WidgetUnitData for FlexBox {
148 fn id(&self) -> &WidgetId {
149 &self.id
150 }
151
152 fn get_children(&self) -> Vec<&WidgetUnit> {
153 self.items.iter().map(|item| &item.slot).collect()
154 }
155}
156
157impl TryFrom<FlexBoxNode> for FlexBox {
158 type Error = ();
159
160 fn try_from(node: FlexBoxNode) -> Result<Self, Self::Error> {
161 let FlexBoxNode {
162 id,
163 items,
164 direction,
165 separation,
166 wrap,
167 transform,
168 ..
169 } = node;
170 let items = items
171 .into_iter()
172 .map(FlexBoxItem::try_from)
173 .collect::<Result<_, _>>()?;
174 Ok(Self {
175 id,
176 items,
177 direction,
178 separation,
179 wrap,
180 transform,
181 })
182 }
183}
184
185#[derive(Debug, Default, Clone)]
186pub struct FlexBoxNode {
187 pub id: WidgetId,
188 pub props: Props,
189 pub items: Vec<FlexBoxItemNode>,
190 pub direction: FlexBoxDirection,
191 pub separation: Scalar,
192 pub wrap: bool,
193 pub transform: Transform,
194}
195
196impl FlexBoxNode {
197 pub fn remap_props<F>(&mut self, mut f: F)
198 where
199 F: FnMut(Props) -> Props,
200 {
201 let props = std::mem::take(&mut self.props);
202 self.props = (f)(props);
203 }
204}
205
206impl From<FlexBoxNode> for WidgetNode {
207 fn from(data: FlexBoxNode) -> Self {
208 Self::Unit(data.into())
209 }
210}
211
212#[derive(Debug, Default, Clone, Serialize, Deserialize)]
213pub(crate) struct FlexBoxNodePrefab {
214 #[serde(default)]
215 pub id: WidgetId,
216 #[serde(default)]
217 pub props: PrefabValue,
218 #[serde(default)]
219 #[serde(skip_serializing_if = "Vec::is_empty")]
220 pub items: Vec<FlexBoxItemNodePrefab>,
221 #[serde(default)]
222 pub direction: FlexBoxDirection,
223 #[serde(default)]
224 pub separation: Scalar,
225 #[serde(default)]
226 pub wrap: bool,
227 #[serde(default)]
228 pub transform: Transform,
229}
230
231#[derive(Debug, Default, Clone, Serialize, Deserialize)]
232pub(crate) struct FlexBoxItemNodePrefab {
233 #[serde(default)]
234 pub slot: WidgetNodePrefab,
235 #[serde(default)]
236 pub layout: FlexBoxItemLayout,
237}