Skip to main content

jellyflow_runtime/runtime/connection/
indicator.rs

1use jellyflow_core::interaction::NodeGraphConnectionMode;
2
3use super::{ConnectionHandleRef, ConnectionHandleValidity};
4
5/// Input for resolving XyFlow-style handle interaction indicator state.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub struct ConnectionHandleIndicatorInput {
8    pub handle: ConnectionHandleRef,
9    pub from: Option<ConnectionHandleRef>,
10    pub to: Option<ConnectionHandleRef>,
11    pub click_start: Option<ConnectionHandleRef>,
12    pub mode: NodeGraphConnectionMode,
13    pub target_feedback: ConnectionHandleValidity,
14    pub connectable: bool,
15    pub connectable_start: bool,
16    pub connectable_end: bool,
17}
18
19impl ConnectionHandleIndicatorInput {
20    pub fn new(handle: ConnectionHandleRef, mode: NodeGraphConnectionMode) -> Self {
21        Self {
22            handle,
23            from: None,
24            to: None,
25            click_start: None,
26            mode,
27            target_feedback: ConnectionHandleValidity::NoHandle,
28            connectable: true,
29            connectable_start: true,
30            connectable_end: true,
31        }
32    }
33
34    pub fn with_connection(
35        mut self,
36        from: Option<ConnectionHandleRef>,
37        to: Option<ConnectionHandleRef>,
38        target_feedback: ConnectionHandleValidity,
39    ) -> Self {
40        self.from = from;
41        self.to = to;
42        self.target_feedback = target_feedback;
43        self
44    }
45
46    pub fn with_click_start(mut self, click_start: Option<ConnectionHandleRef>) -> Self {
47        self.click_start = click_start;
48        self
49    }
50
51    pub fn with_connectability(
52        mut self,
53        connectable: bool,
54        connectable_start: bool,
55        connectable_end: bool,
56    ) -> Self {
57        self.connectable = connectable;
58        self.connectable_start = connectable_start;
59        self.connectable_end = connectable_end;
60        self
61    }
62}
63
64/// XyFlow-style per-handle interaction indicator state.
65#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
66pub struct ConnectionHandleIndicator {
67    pub connecting_from: bool,
68    pub connecting_to: bool,
69    pub click_connecting: bool,
70    pub connection_in_progress: bool,
71    pub click_connection_in_progress: bool,
72    pub possible_end_handle: bool,
73    pub valid: bool,
74    pub show_connection_indicator: bool,
75}
76
77/// Resolves the handle booleans used by XyFlow's Handle component.
78///
79/// This mirrors the class-state logic while staying renderer-neutral. Adapters can map the result
80/// to CSS classes, immediate-mode widget state, or GPU instance attributes.
81pub fn resolve_connection_handle_indicator(
82    input: ConnectionHandleIndicatorInput,
83) -> ConnectionHandleIndicator {
84    let connection_in_progress = input.from.is_some();
85    let click_connection_in_progress = input.click_start.is_some();
86    let connecting_from = input.from == Some(input.handle);
87    let connecting_to = input.to == Some(input.handle);
88    let click_connecting = input.click_start == Some(input.handle);
89    let possible_end_handle = input.from.is_none_or(|from| match input.mode {
90        NodeGraphConnectionMode::Strict => from.direction != input.handle.direction,
91        NodeGraphConnectionMode::Loose => {
92            from.node != input.handle.node || from.port != input.handle.port
93        }
94    });
95    let valid = connecting_to && input.target_feedback == ConnectionHandleValidity::Valid;
96    let show_connection_indicator = input.connectable
97        && (!connection_in_progress || possible_end_handle)
98        && if connection_in_progress || click_connection_in_progress {
99            input.connectable_end
100        } else {
101            input.connectable_start
102        };
103
104    ConnectionHandleIndicator {
105        connecting_from,
106        connecting_to,
107        click_connecting,
108        connection_in_progress,
109        click_connection_in_progress,
110        possible_end_handle,
111        valid,
112        show_connection_indicator,
113    }
114}