raui_core/widget/unit/
mod.rs

1pub mod area;
2pub mod content;
3pub mod flex;
4pub mod grid;
5pub mod image;
6pub mod portal;
7pub mod size;
8pub mod text;
9
10use crate::{
11    props::Props,
12    widget::{
13        WidgetId,
14        node::WidgetNode,
15        unit::{
16            area::{AreaBox, AreaBoxNode, AreaBoxNodePrefab},
17            content::{ContentBox, ContentBoxNode, ContentBoxNodePrefab},
18            flex::{FlexBox, FlexBoxNode, FlexBoxNodePrefab},
19            grid::{GridBox, GridBoxNode, GridBoxNodePrefab},
20            image::{ImageBox, ImageBoxNode, ImageBoxNodePrefab},
21            portal::{PortalBox, PortalBoxNode, PortalBoxNodePrefab},
22            size::{SizeBox, SizeBoxNode, SizeBoxNodePrefab},
23            text::{TextBox, TextBoxNode, TextBoxNodePrefab},
24        },
25    },
26};
27use serde::{Deserialize, Serialize};
28use std::convert::TryFrom;
29
30#[derive(Debug, Default, Clone, Serialize, Deserialize)]
31pub struct WidgetUnitInspectionNode {
32    #[serde(default)]
33    pub id: WidgetId,
34    #[serde(default)]
35    #[serde(skip_serializing_if = "Vec::is_empty")]
36    pub children: Vec<WidgetUnitInspectionNode>,
37}
38
39pub trait WidgetUnitData {
40    fn id(&self) -> &WidgetId;
41
42    fn get_children(&self) -> Vec<&WidgetUnit> {
43        vec![]
44    }
45}
46
47#[derive(Debug, Default, Clone, Serialize, Deserialize)]
48pub enum WidgetUnit {
49    #[default]
50    None,
51    AreaBox(AreaBox),
52    PortalBox(PortalBox),
53    ContentBox(ContentBox),
54    FlexBox(FlexBox),
55    GridBox(GridBox),
56    SizeBox(SizeBox),
57    ImageBox(ImageBox),
58    TextBox(TextBox),
59}
60
61impl WidgetUnit {
62    pub fn is_none(&self) -> bool {
63        matches!(self, Self::None)
64    }
65
66    pub fn is_some(&self) -> bool {
67        !matches!(self, Self::None)
68    }
69
70    pub fn as_data(&self) -> Option<&dyn WidgetUnitData> {
71        match self {
72            Self::None => None,
73            Self::AreaBox(v) => Some(v as &dyn WidgetUnitData),
74            Self::PortalBox(v) => Some(v as &dyn WidgetUnitData),
75            Self::ContentBox(v) => Some(v as &dyn WidgetUnitData),
76            Self::FlexBox(v) => Some(v as &dyn WidgetUnitData),
77            Self::GridBox(v) => Some(v as &dyn WidgetUnitData),
78            Self::SizeBox(v) => Some(v as &dyn WidgetUnitData),
79            Self::ImageBox(v) => Some(v as &dyn WidgetUnitData),
80            Self::TextBox(v) => Some(v as &dyn WidgetUnitData),
81        }
82    }
83
84    pub fn inspect(&self) -> Option<WidgetUnitInspectionNode> {
85        self.as_data().map(|data| WidgetUnitInspectionNode {
86            id: data.id().to_owned(),
87            children: data
88                .get_children()
89                .into_iter()
90                .filter_map(|child| child.inspect())
91                .collect::<Vec<_>>(),
92        })
93    }
94}
95
96impl TryFrom<WidgetUnitNode> for WidgetUnit {
97    type Error = ();
98
99    fn try_from(node: WidgetUnitNode) -> Result<Self, Self::Error> {
100        match node {
101            WidgetUnitNode::None => Ok(Self::None),
102            WidgetUnitNode::AreaBox(n) => Ok(WidgetUnit::AreaBox(AreaBox::try_from(n)?)),
103            WidgetUnitNode::PortalBox(n) => Ok(WidgetUnit::PortalBox(PortalBox::try_from(n)?)),
104            WidgetUnitNode::ContentBox(n) => Ok(WidgetUnit::ContentBox(ContentBox::try_from(n)?)),
105            WidgetUnitNode::FlexBox(n) => Ok(WidgetUnit::FlexBox(FlexBox::try_from(n)?)),
106            WidgetUnitNode::GridBox(n) => Ok(WidgetUnit::GridBox(GridBox::try_from(n)?)),
107            WidgetUnitNode::SizeBox(n) => Ok(WidgetUnit::SizeBox(SizeBox::try_from(n)?)),
108            WidgetUnitNode::ImageBox(n) => Ok(WidgetUnit::ImageBox(ImageBox::try_from(n)?)),
109            WidgetUnitNode::TextBox(n) => Ok(WidgetUnit::TextBox(TextBox::try_from(n)?)),
110        }
111    }
112}
113
114impl TryFrom<WidgetNode> for WidgetUnit {
115    type Error = ();
116
117    fn try_from(node: WidgetNode) -> Result<Self, Self::Error> {
118        match node {
119            WidgetNode::None | WidgetNode::Tuple(_) => Ok(Self::None),
120            WidgetNode::Component(_) => Err(()),
121            WidgetNode::Unit(u) => Self::try_from(u),
122        }
123    }
124}
125
126#[derive(Debug, Default, Clone)]
127pub enum WidgetUnitNode {
128    #[default]
129    None,
130    AreaBox(AreaBoxNode),
131    PortalBox(PortalBoxNode),
132    ContentBox(ContentBoxNode),
133    FlexBox(FlexBoxNode),
134    GridBox(GridBoxNode),
135    SizeBox(SizeBoxNode),
136    ImageBox(ImageBoxNode),
137    TextBox(TextBoxNode),
138}
139
140impl WidgetUnitNode {
141    pub fn is_none(&self) -> bool {
142        matches!(self, Self::None)
143    }
144
145    pub fn is_some(&self) -> bool {
146        !matches!(self, Self::None)
147    }
148
149    pub fn props(&self) -> Option<&Props> {
150        match self {
151            Self::None | Self::AreaBox(_) | Self::PortalBox(_) => None,
152            Self::ContentBox(v) => Some(&v.props),
153            Self::FlexBox(v) => Some(&v.props),
154            Self::GridBox(v) => Some(&v.props),
155            Self::SizeBox(v) => Some(&v.props),
156            Self::ImageBox(v) => Some(&v.props),
157            Self::TextBox(v) => Some(&v.props),
158        }
159    }
160
161    pub fn props_mut(&mut self) -> Option<&mut Props> {
162        match self {
163            Self::None | Self::AreaBox(_) | Self::PortalBox(_) => None,
164            Self::ContentBox(v) => Some(&mut v.props),
165            Self::FlexBox(v) => Some(&mut v.props),
166            Self::GridBox(v) => Some(&mut v.props),
167            Self::SizeBox(v) => Some(&mut v.props),
168            Self::ImageBox(v) => Some(&mut v.props),
169            Self::TextBox(v) => Some(&mut v.props),
170        }
171    }
172
173    pub fn remap_props<F>(&mut self, f: F)
174    where
175        F: FnMut(Props) -> Props,
176    {
177        match self {
178            Self::None | Self::AreaBox(_) | Self::PortalBox(_) => {}
179            Self::ContentBox(v) => v.remap_props(f),
180            Self::FlexBox(v) => v.remap_props(f),
181            Self::GridBox(v) => v.remap_props(f),
182            Self::SizeBox(v) => v.remap_props(f),
183            Self::ImageBox(v) => v.remap_props(f),
184            Self::TextBox(v) => v.remap_props(f),
185        }
186    }
187}
188
189impl TryFrom<WidgetNode> for WidgetUnitNode {
190    type Error = ();
191
192    fn try_from(node: WidgetNode) -> Result<Self, Self::Error> {
193        if let WidgetNode::Unit(v) = node {
194            Ok(v)
195        } else {
196            Err(())
197        }
198    }
199}
200
201impl From<()> for WidgetUnitNode {
202    fn from(_: ()) -> Self {
203        Self::None
204    }
205}
206
207macro_rules! implement_from_unit {
208    { $( $type_name:ident => $variant_name:ident ),+ $(,)? } => {
209        $(
210            impl From<$type_name> for WidgetUnitNode {
211                fn from(unit: $type_name) -> Self {
212                    Self::$variant_name(unit)
213                }
214            }
215        )+
216    };
217}
218
219implement_from_unit! {
220    AreaBoxNode => AreaBox,
221    PortalBoxNode => PortalBox,
222    ContentBoxNode => ContentBox,
223    FlexBoxNode => FlexBox,
224    GridBoxNode => GridBox,
225    SizeBoxNode => SizeBox,
226    ImageBoxNode => ImageBox,
227    TextBoxNode => TextBox,
228}
229
230#[derive(Debug, Default, Clone, Serialize, Deserialize)]
231pub(crate) enum WidgetUnitNodePrefab {
232    #[default]
233    None,
234    AreaBox(AreaBoxNodePrefab),
235    PortalBox(PortalBoxNodePrefab),
236    ContentBox(ContentBoxNodePrefab),
237    FlexBox(FlexBoxNodePrefab),
238    GridBox(GridBoxNodePrefab),
239    SizeBox(SizeBoxNodePrefab),
240    ImageBox(ImageBoxNodePrefab),
241    TextBox(TextBoxNodePrefab),
242}