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(ZoomControlsPlugin::new())
38                    .plugin(FocusSelectionPlugin::new())
39                    .plugin(FitAllGraphPlugin::new())
40                    .plugin(ClipboardPlugin::new())
41                    .plugin(ContextMenuPlugin::new())
42                    .node_renderer("number", NumberNode {})
43                    .build()
44            })
45        })
46        .unwrap();
47    });
48}
49
50pub struct NumberNode;
51
52impl NodeRenderer for NumberNode {
53    fn render(&self, node: &Node, ctx: &mut RenderContext) -> AnyElement {
54        let screen = ctx.viewport.world_to_screen(node.point());
55        let node_x = screen.x;
56        let node_y = screen.y;
57
58        div()
59            .absolute()
60            .left(node_x)
61            .top(node_y)
62            .w(node.size.width * ctx.viewport.zoom)
63            .h(node.size.height * ctx.viewport.zoom)
64            .bg(rgb(0x505078))
65            .child(div().child("Number Node").text_color(white()))
66            .into_any()
67    }
68
69    fn port_render(&self, node: &Node, port: &Port, ctx: &mut RenderContext) -> Option<AnyElement> {
70        let size = port.size;
71        let position = port_screen_position(node, port.id, &ctx)?;
72
73        Some(
74            div()
75                .absolute()
76                .left(position.x - size.width / 2.0 * ctx.viewport.zoom)
77                .top(position.y - size.height / 2.0 * ctx.viewport.zoom)
78                .w(size.width * ctx.viewport.zoom)
79                .h(size.height * ctx.viewport.zoom)
80                .rounded_full()
81                .border_1()
82                .border_color(rgb(0x1A192B))
83                .bg(white())
84                .into_any(),
85        )
86    }
87}