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    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}