1use std::fmt::Display;
2
3use gpui::{Bounds, Pixels, Point, Size, px};
4use serde::{Deserialize, Serialize};
5use serde_json::json;
6
7use crate::Graph;
8
9pub const DEFAULT_NODE_WIDTH: Pixels = px(120.0);
10pub const DEFAULT_NODE_HEIGHT: Pixels = px(60.0);
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
13pub struct NodeId(pub u64);
14
15impl Display for NodeId {
16 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17 write!(f, "{}", self.0)
18 }
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct Node {
23 pub id: NodeId,
24 pub node_type: String,
25 pub x: Pixels,
26 pub y: Pixels,
27 pub size: Size<Pixels>,
28
29 pub inputs: Vec<PortId>,
30 pub outputs: Vec<PortId>,
31 pub data: serde_json::Value,
32}
33
34impl Node {
35 pub fn new(id: u64, x: f32, y: f32) -> Self {
36 Self {
37 id: NodeId(id),
38 node_type: String::new(),
39 x: x.into(),
40 y: y.into(),
41 size: Size {
42 width: DEFAULT_NODE_WIDTH,
43 height: DEFAULT_NODE_HEIGHT,
44 },
45 inputs: vec![],
46 outputs: vec![],
47 data: json!({}),
48 }
49 }
50
51 pub fn node_type(mut self, ty: impl Into<String>) -> Self {
52 self.node_type = ty.into();
53 self
54 }
55
56 pub fn point(&self) -> Point<Pixels> {
57 Point::new(self.x, self.y)
58 }
59
60 pub fn bounds(&self) -> Bounds<Pixels> {
61 Bounds::new(self.point(), self.size)
62 }
63
64 pub fn set_size(mut self, size: Size<Pixels>) -> Self {
65 self.size = size;
66 self
67 }
68
69 pub fn output(mut self, id: PortId) -> Self {
70 self.outputs.push(id);
71 self
72 }
73
74 pub fn input(mut self, id: PortId) -> Self {
75 self.inputs.push(id);
76 self
77 }
78}
79
80#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
81pub struct PortId(pub u64);
82
83#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
84pub enum PortKind {
85 Input,
86 Output,
87}
88
89#[derive(Debug, Clone, Serialize, Deserialize)]
90pub struct Port {
91 pub id: PortId,
92 pub kind: PortKind,
93 pub index: usize,
94 pub node_id: NodeId,
95}
96
97impl Port {
98 pub fn new_input(id: u64, node_id: u64, index: usize) -> Self {
99 Self {
100 id: PortId(id),
101 kind: PortKind::Input,
102 index,
103 node_id: NodeId(node_id),
104 }
105 }
106 pub fn new_output(id: u64, node_id: u64, index: usize) -> Self {
107 Self {
108 id: PortId(id),
109 kind: PortKind::Output,
110 index,
111 node_id: NodeId(node_id),
112 }
113 }
114}
115
116pub struct NodeBuilder {
117 node_type: String,
118 x: Pixels,
119 y: Pixels,
120 size: Size<Pixels>,
121 input_count: usize,
122 output_count: usize,
123 data: serde_json::Value,
124}
125
126impl NodeBuilder {
127 pub fn new(node_type: impl Into<String>) -> Self {
128 Self {
129 node_type: node_type.into(),
130 x: px(0.0),
131 y: px(0.0),
132 size: Size {
133 width: DEFAULT_NODE_WIDTH,
134 height: DEFAULT_NODE_HEIGHT,
135 },
136 input_count: 0,
137 output_count: 0,
138 data: serde_json::Value::Null,
139 }
140 }
141
142 pub fn position(mut self, x: f32, y: f32) -> Self {
143 self.x = x.into();
144 self.y = y.into();
145 self
146 }
147
148 pub fn size(mut self, w: f32, h: f32) -> Self {
149 self.size = Size {
150 width: w.into(),
151 height: h.into(),
152 };
153 self
154 }
155
156 pub fn input(mut self) -> Self {
157 self.input_count += 1;
158 self
159 }
160
161 pub fn output(mut self) -> Self {
162 self.output_count += 1;
163 self
164 }
165
166 pub fn data(mut self, data: serde_json::Value) -> Self {
167 self.data = data;
168 self
169 }
170
171 pub fn build(self, graph: &mut Graph) -> NodeId {
172 let node_id = graph.next_node_id();
173
174 let mut inputs = Vec::new();
175 let mut outputs = Vec::new();
176
177 for i in 0..self.input_count {
179 let port_id = graph.next_port_id();
180
181 graph.ports.insert(
182 port_id,
183 Port {
184 id: port_id,
185 kind: PortKind::Input,
186 index: i,
187 node_id,
188 },
189 );
190
191 inputs.push(port_id);
192 }
193
194 for i in 0..self.output_count {
196 let port_id = graph.next_port_id();
197
198 graph.ports.insert(
199 port_id,
200 Port {
201 id: port_id,
202 kind: PortKind::Output,
203 index: i,
204 node_id,
205 },
206 );
207
208 outputs.push(port_id);
209 }
210
211 let node = Node {
212 id: node_id,
213 node_type: self.node_type,
214 x: self.x,
215 y: self.y,
216 size: self.size,
217 inputs,
218 outputs,
219 data: self.data,
220 };
221
222 graph.nodes.insert(node_id, node);
223 let order = graph.node_order_mut();
224 order.push(node_id);
225
226 node_id
227 }
228}