Skip to main content

extension/
extension.rs

1use ferrum_flow::*;
2use gpui::{
3    AnyElement, AppContext as _, Application, Element as _, ParentElement as _, Styled,
4    WindowOptions, div, rgb, white,
5};
6use serde_json::json;
7
8fn main() {
9    Application::new().run(|cx| {
10        let mut graph = Graph::new();
11
12        graph
13            .create_node("number")
14            .position(100.0, 100.0)
15            .size(300.0, 150.0)
16            .output()
17            .data(json!({ "label": "Number Node" }))
18            .build(&mut graph);
19
20        graph
21            .create_node("")
22            .position(300.0, 400.0)
23            .input()
24            .build(&mut graph);
25
26        graph
27            .create_node("undefined")
28            .position(500.0, 500.0)
29            .input()
30            .output()
31            .build(&mut graph);
32
33        cx.open_window(WindowOptions::default(), |window, cx| {
34            cx.new(|ctx| {
35                FlowCanvas::builder(graph, ctx, window)
36                    .plugins_core()
37                    .plugin(SnapGuidesPlugin::new())
38                    .plugin(ZoomControlsPlugin::new())
39                    .plugin(FocusSelectionPlugin::new())
40                    .plugin(FitAllGraphPlugin::new())
41                    .plugin(ClipboardPlugin::new())
42                    .plugin(ContextMenuPlugin::new())
43                    .node_renderer("number", NumberNode {})
44                    .build()
45            })
46        })
47        .unwrap();
48    });
49}
50
51pub struct NumberNode;
52
53impl NodeRenderer for NumberNode {
54    fn render(&self, node: &Node, ctx: &mut RenderContext) -> AnyElement {
55        let screen = ctx.viewport.world_to_screen(node.point());
56        let node_x = screen.x;
57        let node_y = screen.y;
58
59        div()
60            .absolute()
61            .left(node_x)
62            .top(node_y)
63            .w(node.size.width * ctx.viewport.zoom)
64            .h(node.size.height * ctx.viewport.zoom)
65            .bg(rgb(0x505078))
66            .child(div().child("Number Node").text_color(white()))
67            .into_any()
68    }
69
70    fn port_render(&self, node: &Node, port: &Port, ctx: &mut RenderContext) -> Option<AnyElement> {
71        let size = port.size;
72        let position = port_screen_position(node, port.id, &ctx)?;
73
74        Some(
75            div()
76                .absolute()
77                .left(position.x - size.width / 2.0 * ctx.viewport.zoom)
78                .top(position.y - size.height / 2.0 * ctx.viewport.zoom)
79                .w(size.width * ctx.viewport.zoom)
80                .h(size.height * ctx.viewport.zoom)
81                .rounded_full()
82                .border_1()
83                .border_color(rgb(0x1A192B))
84                .bg(white())
85                .into_any(),
86        )
87    }
88}