Skip to main content

ferrum_flow/plugin/
utils.rs

1use std::collections::HashMap;
2
3use gpui::{KeyDownEvent, Pixels, Point};
4
5use crate::{
6    Edge, EdgeId, Graph, NodeId, Port, PortId, RendererRegistry, Viewport, canvas::PortLayoutCache,
7};
8
9/// Primary shortcut modifier: ⌘ on macOS, Ctrl on other platforms.
10pub fn primary_platform_modifier(ev: &KeyDownEvent) -> bool {
11    #[cfg(target_os = "macos")]
12    {
13        ev.keystroke.modifiers.platform
14    }
15    #[cfg(not(target_os = "macos"))]
16    {
17        ev.keystroke.modifiers.control
18    }
19}
20
21pub fn is_node_visible(graph: &Graph, viewport: &Viewport, node_id: &NodeId) -> bool {
22    let Some(node) = graph.get_node(node_id) else {
23        return false;
24    };
25
26    viewport.is_node_visible(node)
27}
28
29pub fn is_edge_visible(graph: &Graph, viewport: &Viewport, edge: &Edge) -> bool {
30    let Edge {
31        source_port,
32        target_port,
33        ..
34    } = edge;
35
36    let Some(Port { node_id: n1, .. }) = graph.ports.get(source_port) else {
37        return false;
38    };
39
40    let Some(Port { node_id: n2, .. }) = graph.ports.get(target_port) else {
41        return false;
42    };
43
44    let node1_visible = graph
45        .get_node(n1)
46        .map(|n| viewport.is_node_visible(n))
47        .unwrap_or(false);
48
49    let node2_visible = graph
50        .get_node(n2)
51        .map(|n| viewport.is_node_visible(n))
52        .unwrap_or(false);
53
54    node1_visible || node2_visible
55}
56
57pub fn port_offset_cached(
58    cache: &PortLayoutCache,
59    node_id: &NodeId,
60    port_id: &PortId,
61) -> Option<Point<Pixels>> {
62    cache.map.get(node_id)?.get(port_id).copied()
63}
64
65pub fn cache_node_port_offset(
66    graph: &Graph,
67    renderers: &RendererRegistry,
68    cache: &mut PortLayoutCache,
69    node_id: &NodeId,
70) {
71    if cache.map.contains_key(node_id) {
72        return;
73    }
74
75    let Some(node) = graph.get_node(node_id) else {
76        return;
77    };
78
79    let renderer = renderers.get(&node.node_type);
80
81    let mut result = HashMap::new();
82
83    for port in graph.ports.values().filter(|p| p.node_id == node.id) {
84        let pos = renderer.port_offset(node, port, graph);
85        result.insert(port.id, pos);
86    }
87
88    cache.map.insert(node.id, result);
89}
90
91pub fn cache_all_node_port_offset(
92    graph: &Graph,
93    renderers: &RendererRegistry,
94    cache: &mut PortLayoutCache,
95) {
96    let node_ids: Vec<NodeId> = graph.nodes().iter().map(|(id, _)| *id).collect();
97
98    for node_id in node_ids {
99        cache_node_port_offset(graph, renderers, cache, &node_id);
100    }
101}
102
103pub fn cache_port_offset_with_edge(
104    graph: &Graph,
105    renderers: &RendererRegistry,
106    cache: &mut PortLayoutCache,
107    edge_id: &EdgeId,
108) {
109    let Some(edge) = graph.edges.get(edge_id) else {
110        return;
111    };
112
113    cache_port_offset_with_port(graph, renderers, cache, &edge.source_port);
114    cache_port_offset_with_port(graph, renderers, cache, &edge.target_port);
115}
116
117pub fn cache_port_offset_with_port(
118    graph: &Graph,
119    renderers: &RendererRegistry,
120    cache: &mut PortLayoutCache,
121    port_id: &PortId,
122) {
123    let Some(port) = graph.ports.get(port_id) else {
124        return;
125    };
126
127    cache_node_port_offset(graph, renderers, cache, &port.node_id);
128}