raui_core/widget/unit/
flex.rs

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
56impl Default for FlexBoxItemLayout {
57    fn default() -> Self {
58        Self {
59            basis: None,
60            fill: Self::default_fill(),
61            grow: Self::default_grow(),
62            shrink: Self::default_shrink(),
63            margin: Default::default(),
64            align: 0.0,
65        }
66    }
67}
68
69#[derive(Debug, Default, Clone, Serialize, Deserialize)]
70pub struct FlexBoxItem {
71    #[serde(default)]
72    pub slot: WidgetUnit,
73    #[serde(default)]
74    pub layout: FlexBoxItemLayout,
75}
76
77impl TryFrom<FlexBoxItemNode> for FlexBoxItem {
78    type Error = ();
79
80    fn try_from(node: FlexBoxItemNode) -> Result<Self, Self::Error> {
81        let FlexBoxItemNode { slot, layout } = node;
82        Ok(Self {
83            slot: WidgetUnit::try_from(slot)?,
84            layout,
85        })
86    }
87}
88
89#[derive(Debug, Default, Clone)]
90pub struct FlexBoxItemNode {
91    pub slot: WidgetNode,
92    pub layout: FlexBoxItemLayout,
93}
94
95#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
96pub enum FlexBoxDirection {
97    #[default]
98    HorizontalLeftToRight,
99    HorizontalRightToLeft,
100    VerticalTopToBottom,
101    VerticalBottomToTop,
102}
103
104impl FlexBoxDirection {
105    pub fn is_horizontal(&self) -> bool {
106        *self == Self::HorizontalLeftToRight || *self == Self::HorizontalRightToLeft
107    }
108
109    pub fn is_vertical(&self) -> bool {
110        *self == Self::VerticalTopToBottom || *self == Self::VerticalBottomToTop
111    }
112
113    pub fn is_order_ascending(&self) -> bool {
114        *self == Self::HorizontalLeftToRight || *self == Self::VerticalTopToBottom
115    }
116
117    pub fn is_order_descending(&self) -> bool {
118        *self == Self::HorizontalRightToLeft || *self == Self::VerticalBottomToTop
119    }
120}
121
122#[derive(Debug, Default, Clone, Serialize, Deserialize)]
123pub struct FlexBox {
124    #[serde(default)]
125    pub id: WidgetId,
126    #[serde(default)]
127    #[serde(skip_serializing_if = "Vec::is_empty")]
128    pub items: Vec<FlexBoxItem>,
129    #[serde(default)]
130    pub direction: FlexBoxDirection,
131    #[serde(default)]
132    pub separation: Scalar,
133    #[serde(default)]
134    pub wrap: bool,
135    #[serde(default)]
136    pub transform: Transform,
137}
138
139impl WidgetUnitData for FlexBox {
140    fn id(&self) -> &WidgetId {
141        &self.id
142    }
143
144    fn get_children(&self) -> Vec<&WidgetUnit> {
145        self.items.iter().map(|item| &item.slot).collect()
146    }
147}
148
149impl TryFrom<FlexBoxNode> for FlexBox {
150    type Error = ();
151
152    fn try_from(node: FlexBoxNode) -> Result<Self, Self::Error> {
153        let FlexBoxNode {
154            id,
155            items,
156            direction,
157            separation,
158            wrap,
159            transform,
160            ..
161        } = node;
162        let items = items
163            .into_iter()
164            .map(FlexBoxItem::try_from)
165            .collect::<Result<_, _>>()?;
166        Ok(Self {
167            id,
168            items,
169            direction,
170            separation,
171            wrap,
172            transform,
173        })
174    }
175}
176
177#[derive(Debug, Default, Clone)]
178pub struct FlexBoxNode {
179    pub id: WidgetId,
180    pub props: Props,
181    pub items: Vec<FlexBoxItemNode>,
182    pub direction: FlexBoxDirection,
183    pub separation: Scalar,
184    pub wrap: bool,
185    pub transform: Transform,
186}
187
188impl FlexBoxNode {
189    pub fn remap_props<F>(&mut self, mut f: F)
190    where
191        F: FnMut(Props) -> Props,
192    {
193        let props = std::mem::take(&mut self.props);
194        self.props = (f)(props);
195    }
196}
197
198impl From<FlexBoxNode> for WidgetNode {
199    fn from(data: FlexBoxNode) -> Self {
200        Self::Unit(data.into())
201    }
202}
203
204#[derive(Debug, Default, Clone, Serialize, Deserialize)]
205pub(crate) struct FlexBoxNodePrefab {
206    #[serde(default)]
207    pub id: WidgetId,
208    #[serde(default)]
209    pub props: PrefabValue,
210    #[serde(default)]
211    #[serde(skip_serializing_if = "Vec::is_empty")]
212    pub items: Vec<FlexBoxItemNodePrefab>,
213    #[serde(default)]
214    pub direction: FlexBoxDirection,
215    #[serde(default)]
216    pub separation: Scalar,
217    #[serde(default)]
218    pub wrap: bool,
219    #[serde(default)]
220    pub transform: Transform,
221}
222
223#[derive(Debug, Default, Clone, Serialize, Deserialize)]
224pub(crate) struct FlexBoxItemNodePrefab {
225    #[serde(default)]
226    pub slot: WidgetNodePrefab,
227    #[serde(default)]
228    pub layout: FlexBoxItemLayout,
229}