1use gpui::*;
2
3use crate::{
4 graph::Graph,
5 plugin::{
6 EventResult, FlowEvent, InitPluginContext, InputEvent, Plugin, PluginContext,
7 PluginRegistry, RenderContext, RenderLayer,
8 },
9 viewport::Viewport,
10};
11
12mod types;
13mod undo;
14
15pub use undo::{CanvasState, Command, CompositeCommand, History};
16
17pub use types::{Interaction, InteractionResult, InteractionState};
18
19pub struct FlowCanvas {
20 pub graph: Graph,
21
22 pub(crate) viewport: Viewport,
23
24 pub(crate) plugins_registry: PluginRegistry,
25
26 pub(crate) focus_handle: FocusHandle,
27
28 pub(crate) interaction: InteractionState,
29
30 pub history: History,
31
32 pub event_queue: Vec<FlowEvent>,
33}
34
35impl FlowCanvas {
50 pub fn new(graph: Graph, cx: &mut Context<Self>) -> Self {
51 let focus_handle = cx.focus_handle();
52 Self {
53 graph,
54 viewport: Viewport::new(),
55 plugins_registry: PluginRegistry::new(),
56 focus_handle,
57 interaction: InteractionState::new(),
58 history: History::new(),
59 event_queue: vec![],
60 }
61 }
62
63 pub fn plugin(mut self, plugin: impl Plugin + 'static) -> Self {
64 self.plugins_registry = self.plugins_registry.add(plugin);
65 self
66 }
67
68 pub fn init_plugins(&mut self) {
69 let mut ctx = InitPluginContext {
70 graph: &mut self.graph,
71 viewport: &mut self.viewport,
72 };
73
74 self.plugins_registry.plugins.sort_by_key(|p| -p.priority());
75
76 for plugin in &mut self.plugins_registry.plugins.iter_mut() {
77 plugin.setup(&mut ctx);
78 }
79 }
80
81 pub fn handle_event(&mut self, event: FlowEvent, cx: &mut Context<Self>) {
82 let event_queue = &mut self.event_queue;
83
84 let mut emit = |event: FlowEvent| {
85 event_queue.push(event);
86 };
87
88 let mut notify = || {
89 cx.notify();
90 };
91
92 if let Some(mut handler) = self.interaction.handler.take() {
94 let mut ctx = PluginContext::new(
95 &mut self.graph,
96 &mut self.viewport,
97 &mut self.interaction,
98 &mut self.history,
99 &mut emit,
100 &mut notify,
101 );
102 let mut fast_return = false;
103 let result = match &event {
104 FlowEvent::Input(InputEvent::MouseMove(ev)) => {
105 fast_return = true;
106 handler.on_mouse_move(ev, &mut ctx)
107 }
108
109 FlowEvent::Input(InputEvent::MouseUp(ev)) => {
110 fast_return = true;
111 handler.on_mouse_up(ev, &mut ctx)
112 }
113
114 _ => InteractionResult::Continue,
115 };
116
117 if fast_return {
118 match result {
119 InteractionResult::Continue => self.interaction.handler = Some(handler),
120
121 InteractionResult::End => {
122 self.interaction.handler = None;
123 }
124
125 InteractionResult::Replace(h) => {
126 self.interaction.handler = Some(h);
127 }
128 }
129 return;
130 }
131 }
132
133 let mut ctx = PluginContext::new(
134 &mut self.graph,
135 &mut self.viewport,
136 &mut self.interaction,
137 &mut self.history,
138 &mut emit,
139 &mut notify,
140 );
141
142 for plugin in &mut self.plugins_registry.plugins {
144 let result = plugin.on_event(&event, &mut ctx);
145 match result {
146 EventResult::Continue => {}
147 EventResult::Stop => break,
148 }
149 }
150 }
151
152 fn process_event_queue(&mut self, cx: &mut Context<Self>) {
153 while let Some(event) = self.event_queue.pop() {
154 let mut emit = |e| self.event_queue.push(e);
155
156 let mut notify = || {
157 cx.notify();
158 };
159
160 let mut ctx = PluginContext::new(
161 &mut self.graph,
162 &mut self.viewport,
163 &mut self.interaction,
164 &mut self.history,
165 &mut emit,
166 &mut notify,
167 );
168
169 for plugin in &mut self.plugins_registry.plugins {
170 let result = plugin.on_event(&event, &mut ctx);
171 match result {
172 EventResult::Continue => {}
173 EventResult::Stop => break,
174 }
175 }
176 }
177 }
178
179 fn on_key_down(&mut self, ev: &KeyDownEvent, _: &mut Window, cx: &mut Context<Self>) {
180 self.handle_event(FlowEvent::Input(InputEvent::KeyDown(ev.clone())), cx);
181 self.process_event_queue(cx);
182 }
183
184 fn on_key_up(&mut self, ev: &KeyUpEvent, _: &mut Window, cx: &mut Context<Self>) {
185 self.handle_event(FlowEvent::Input(InputEvent::KeyUp(ev.clone())), cx);
186 self.process_event_queue(cx);
187 }
188
189 fn on_mouse_down(&mut self, ev: &MouseDownEvent, _: &mut Window, cx: &mut Context<Self>) {
190 self.handle_event(FlowEvent::Input(InputEvent::MouseDown(ev.clone())), cx);
191 self.process_event_queue(cx);
192 }
193
194 fn on_mouse_move(&mut self, ev: &MouseMoveEvent, _: &mut Window, cx: &mut Context<Self>) {
195 self.handle_event(FlowEvent::Input(InputEvent::MouseMove(ev.clone())), cx);
196 self.process_event_queue(cx);
197 }
198
199 fn on_mouse_up(&mut self, ev: &MouseUpEvent, _: &mut Window, cx: &mut Context<Self>) {
200 self.handle_event(FlowEvent::Input(InputEvent::MouseUp(ev.clone())), cx);
201 self.process_event_queue(cx);
202 }
203
204 fn on_scroll_wheel(&mut self, ev: &ScrollWheelEvent, _: &mut Window, cx: &mut Context<Self>) {
205 self.handle_event(FlowEvent::Input(InputEvent::Wheel(ev.clone())), cx);
206 self.process_event_queue(cx);
207 }
208}
209
210impl Render for FlowCanvas {
211 fn render(&mut self, window: &mut Window, this_cx: &mut Context<Self>) -> impl IntoElement {
212 if self.viewport.window_bounds.is_none() {
214 self.viewport.window_bounds = Some(window.bounds());
215 }
216
217 let entity = this_cx.entity();
218
219 let graph = &self.graph;
220 let viewport = &self.viewport;
221
222 let mut layers: Vec<Vec<AnyElement>> =
223 (0..RenderLayer::ALL.len()).map(|_| Vec::new()).collect();
224
225 for plugin in self.plugins_registry.plugins.iter_mut() {
226 let layer = plugin.render_layer();
227
228 let mut ctx = RenderContext::new(graph, viewport, window, layer);
229
230 if let Some(el) = plugin.render(&mut ctx) {
231 layers[layer.index()].push(el);
232 }
233 }
234
235 if let Some(i) = self.interaction.handler.as_ref() {
236 let mut ctx = RenderContext::new(graph, viewport, window, RenderLayer::Interaction);
237
238 if let Some(el) = i.render(&mut ctx) {
239 layers[RenderLayer::Interaction.index()].push(el);
240 }
241 }
242
243 div()
244 .size_full()
245 .track_focus(&self.focus_handle)
246 .on_key_down(window.listener_for(&entity, Self::on_key_down))
247 .on_key_up(window.listener_for(&entity, Self::on_key_up))
248 .on_mouse_down(
249 MouseButton::Left,
250 window.listener_for(&entity, Self::on_mouse_down),
251 )
252 .on_mouse_move(window.listener_for(&entity, Self::on_mouse_move))
253 .on_mouse_up(
254 MouseButton::Left,
255 window.listener_for(&entity, Self::on_mouse_up),
256 )
257 .on_scroll_wheel(window.listener_for(&entity, Self::on_scroll_wheel))
258 .children(
259 RenderLayer::ALL
260 .iter()
261 .map(|layer| div().absolute().children(layers[layer.index()].drain(..))),
262 )
263 }
264}