Seregon/StratoSDK

StratoSDK is a framework with a declarative approach similar to Flutter/React, written and designed entirely for Rust.

Rust/27.3 KB/No license
crates/strato-core/src/ui_node.rs
StratoSDK / crates / strato-core / src / ui_node.rs
1use crate::types::Color;
2 
3/// A node in the semantic UI tree.
4/// This decouples the description of the UI from its runtime instantiation.
5#[derive(Debug, Clone, PartialEq)]
6pub enum UiNode {
7 /// A widget with a name, properties, and children.
8 Widget(WidgetNode),
9 /// A text node.
10 Text(String),
11 /// A container for multiple nodes.
12 Fragment(Vec<UiNode>),
13}
14 
15/// Description of a widget.
16#[derive(Debug, Clone, PartialEq)]
17pub struct WidgetNode {
18 /// The name of the widget (e.g., "Container", "Button").
19 pub name: String,
20 /// Properties configuration.
21 pub props: Vec<(String, PropValue)>,
22 /// Child nodes.
23 pub children: Vec<UiNode>,
24}
25 
26/// Value of a property.
27/// Note: `Any` is restricted to callbacks and runtime handles.
28#[derive(Debug)]
29pub enum PropValue {
30 String(String),
31 Int(i64),
32 Float(f64),
33 Bool(bool),
34 Color(Color),
35 // Callbacks or IDs can be added here explicitly, e.g. Callback(usize)
36}
37 
38impl PartialEq for PropValue {
39 fn eq(&self, other: &Self) -> bool {
40 match (self, other) {
41 (PropValue::String(a), PropValue::String(b)) => a == b,
42 (PropValue::Int(a), PropValue::Int(b)) => a == b,
43 (PropValue::Float(a), PropValue::Float(b)) => a == b,
44 (PropValue::Bool(a), PropValue::Bool(b)) => a == b,
45 (PropValue::Color(a), PropValue::Color(b)) => a == b,
46 _ => false,
47 }
48 }
49}
50 
51impl Clone for PropValue {
52 fn clone(&self) -> Self {
53 match self {
54 PropValue::String(s) => PropValue::String(s.clone()),
55 PropValue::Int(i) => PropValue::Int(*i),
56 PropValue::Float(f) => PropValue::Float(*f),
57 PropValue::Bool(b) => PropValue::Bool(*b),
58 PropValue::Color(c) => PropValue::Color(*c),
59 }
60 }
61}
62 
63// Helpers for manual construction if needed (though macro handles this)
64impl UiNode {
65 pub fn widget(name: impl Into<String>) -> Self {
66 UiNode::Widget(WidgetNode {
67 name: name.into(),
68 props: Vec::new(),
69 children: Vec::new(),
70 })
71 }
72 
73 pub fn text(text: impl Into<String>) -> Self {
74 UiNode::Text(text.into())
75 }
76}
77 
78impl WidgetNode {
79 pub fn prop(mut self, name: impl Into<String>, value: PropValue) -> Self {
80 self.props.push((name.into(), value));
81 self
82 }
83 
84 pub fn child(mut self, node: UiNode) -> Self {
85 self.children.push(node);
86 self
87 }
88}
89 
90// Initial `From` implementations for easy conversion in macro generation
91impl From<String> for PropValue {
92 fn from(v: String) -> Self {
93 PropValue::String(v)
94 }
95}
96impl From<&str> for PropValue {
97 fn from(v: &str) -> Self {
98 PropValue::String(v.to_string())
99 }
100}
101impl From<i64> for PropValue {
102 fn from(v: i64) -> Self {
103 PropValue::Int(v)
104 }
105}
106impl From<i32> for PropValue {
107 fn from(v: i32) -> Self {
108 PropValue::Int(v as i64)
109 }
110}
111impl From<f64> for PropValue {
112 fn from(v: f64) -> Self {
113 PropValue::Float(v)
114 }
115}
116impl From<f32> for PropValue {
117 fn from(v: f32) -> Self {
118 PropValue::Float(v as f64)
119 }
120}
121impl From<bool> for PropValue {
122 fn from(v: bool) -> Self {
123 PropValue::Bool(v)
124 }
125}
126impl From<Color> for PropValue {
127 fn from(v: Color) -> Self {
128 PropValue::Color(v)
129 }
130}
131