1use crate::{
2 Prefab,
3 props::Props,
4 widget::{
5 component::{WidgetComponent, WidgetComponentPrefab},
6 unit::{WidgetUnitNode, WidgetUnitNodePrefab},
7 },
8};
9use serde::{Deserialize, Serialize};
10
11#[allow(clippy::large_enum_variant)]
12#[derive(Debug, Default, Clone)]
13pub enum WidgetNode {
14 #[default]
15 None,
16 Component(WidgetComponent),
17 Unit(WidgetUnitNode),
18 Tuple(Vec<WidgetNode>),
19}
20
21impl WidgetNode {
22 pub fn is_none(&self) -> bool {
23 match self {
24 Self::None => true,
25 Self::Unit(unit) => unit.is_none(),
26 Self::Tuple(v) => v.is_empty(),
27 _ => false,
28 }
29 }
30
31 pub fn is_some(&self) -> bool {
32 match self {
33 Self::None => false,
34 Self::Unit(unit) => unit.is_some(),
35 Self::Tuple(v) => !v.is_empty(),
36 _ => true,
37 }
38 }
39
40 pub fn as_component(&self) -> Option<&WidgetComponent> {
41 match self {
42 Self::Component(c) => Some(c),
43 _ => None,
44 }
45 }
46
47 pub fn as_unit(&self) -> Option<&WidgetUnitNode> {
48 match self {
49 Self::Unit(u) => Some(u),
50 _ => None,
51 }
52 }
53
54 pub fn as_tuple(&self) -> Option<&[WidgetNode]> {
55 match self {
56 Self::Tuple(v) => Some(v),
57 _ => None,
58 }
59 }
60
61 pub fn props(&self) -> Option<&Props> {
62 match self {
63 Self::Component(c) => Some(&c.props),
64 Self::Unit(u) => u.props(),
65 _ => None,
66 }
67 }
68
69 pub fn props_mut(&mut self) -> Option<&mut Props> {
70 match self {
71 Self::Component(c) => Some(&mut c.props),
72 Self::Unit(u) => u.props_mut(),
73 _ => None,
74 }
75 }
76
77 pub fn remap_props<F>(&mut self, f: F)
78 where
79 F: FnMut(Props) -> Props,
80 {
81 match self {
82 Self::Component(c) => c.remap_props(f),
83 Self::Unit(u) => u.remap_props(f),
84 _ => {}
85 }
86 }
87
88 pub fn shared_props(&self) -> Option<&Props> {
89 match self {
90 Self::Component(c) => c.shared_props.as_ref(),
91 _ => None,
92 }
93 }
94
95 pub fn shared_props_mut(&mut self) -> Option<&mut Props> {
96 match self {
97 Self::Component(c) => {
98 if c.shared_props.is_none() {
99 c.shared_props = Some(Default::default());
100 }
101 c.shared_props.as_mut()
102 }
103 _ => None,
104 }
105 }
106
107 pub fn remap_shared_props<F>(&mut self, f: F)
108 where
109 F: FnMut(Props) -> Props,
110 {
111 if let Self::Component(c) = self {
112 c.remap_shared_props(f);
113 }
114 }
115
116 pub fn pack_tuple<const N: usize>(data: [WidgetNode; N]) -> Self {
117 Self::Tuple(data.into())
118 }
119
120 pub fn unpack_tuple<const N: usize>(self) -> [WidgetNode; N] {
121 if let WidgetNode::Tuple(mut data) = self {
122 let mut iter = data.drain(..);
123 std::array::from_fn(|_| iter.next().unwrap_or_default())
124 } else {
125 std::array::from_fn(|_| WidgetNode::None)
126 }
127 }
128}
129
130impl From<()> for WidgetNode {
131 fn from(_: ()) -> Self {
132 Self::None
133 }
134}
135
136impl From<()> for Box<WidgetNode> {
137 fn from(_: ()) -> Self {
138 Box::new(WidgetNode::None)
139 }
140}
141
142impl From<WidgetComponent> for WidgetNode {
143 fn from(component: WidgetComponent) -> Self {
144 Self::Component(component)
145 }
146}
147
148impl From<WidgetUnitNode> for WidgetNode {
149 fn from(unit: WidgetUnitNode) -> Self {
150 Self::Unit(unit)
151 }
152}
153
154impl From<WidgetUnitNode> for Box<WidgetNode> {
155 fn from(unit: WidgetUnitNode) -> Self {
156 Box::new(WidgetNode::Unit(unit))
157 }
158}
159
160impl<const N: usize> From<[WidgetNode; N]> for WidgetNode {
161 fn from(data: [WidgetNode; N]) -> Self {
162 Self::pack_tuple(data)
163 }
164}
165
166#[derive(Debug, Default, Clone, Serialize, Deserialize)]
167pub(crate) enum WidgetNodePrefab {
168 #[default]
169 None,
170 Component(WidgetComponentPrefab),
171 Unit(WidgetUnitNodePrefab),
172 Tuple(Vec<WidgetNodePrefab>),
173}
174
175impl Prefab for WidgetNodePrefab {}