jellyflow_runtime/runtime/geometry/
edge_route.rs1use jellyflow_core::core::{Edge, EdgeLabelAnchor, EdgeRouteKind};
2use serde::{Deserialize, Serialize};
3
4use super::{
5 BezierEdgeOptions, EdgeHitTestOptions, EdgePath, EdgePosition, SmoothStepEdgeOptions,
6 bezier_edge_path, edge_path_contains_point, smoothstep_edge_path, straight_edge_path,
7};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
11#[serde(rename_all = "snake_case")]
12pub enum ResolvedEdgeRouteKind {
13 Straight,
14 Orthogonal,
15 Bezier,
16 SmoothStep,
17}
18
19impl From<EdgeRouteKind> for ResolvedEdgeRouteKind {
20 fn from(value: EdgeRouteKind) -> Self {
21 match value {
22 EdgeRouteKind::Straight => Self::Straight,
23 EdgeRouteKind::Orthogonal => Self::Orthogonal,
24 EdgeRouteKind::Bezier => Self::Bezier,
25 EdgeRouteKind::SmoothStep => Self::SmoothStep,
26 }
27 }
28}
29
30impl From<ResolvedEdgeRouteKind> for EdgeRouteKind {
31 fn from(value: ResolvedEdgeRouteKind) -> Self {
32 match value {
33 ResolvedEdgeRouteKind::Straight => Self::Straight,
34 ResolvedEdgeRouteKind::Orthogonal => Self::Orthogonal,
35 ResolvedEdgeRouteKind::Bezier => Self::Bezier,
36 ResolvedEdgeRouteKind::SmoothStep => Self::SmoothStep,
37 }
38 }
39}
40
41#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
43pub struct EdgeInteractionFacts {
44 pub selectable: bool,
45 pub selected: bool,
46 pub focusable: bool,
47 pub deletable: bool,
48 pub reconnect_source: bool,
49 pub reconnect_target: bool,
50}
51
52impl EdgeInteractionFacts {
53 pub fn can_reconnect(self) -> bool {
54 self.reconnect_source || self.reconnect_target
55 }
56}
57
58#[derive(Debug, Clone, PartialEq)]
60pub struct EdgeRouteFacts {
61 pub kind: ResolvedEdgeRouteKind,
62 pub endpoints: EdgePosition,
63 pub path: EdgePath,
64 pub label_anchor: EdgeLabelAnchor,
65 pub hit_test: EdgeHitTestOptions,
66 pub interaction: EdgeInteractionFacts,
67}
68
69impl EdgeRouteFacts {
70 pub fn with_hit_test(mut self, hit_test: EdgeHitTestOptions) -> Self {
71 self.hit_test = hit_test;
72 self
73 }
74
75 pub fn with_interaction(mut self, interaction: EdgeInteractionFacts) -> Self {
76 self.interaction = interaction;
77 self
78 }
79
80 pub fn contains_point(&self, point: jellyflow_core::core::CanvasPoint) -> bool {
81 edge_path_contains_point(&self.path, point, self.hit_test)
82 }
83}
84
85pub fn resolve_edge_route_path(edge: &Edge, endpoints: EdgePosition) -> Option<EdgeRouteFacts> {
87 let kind = edge
88 .view
89 .route_kind
90 .map(ResolvedEdgeRouteKind::from)
91 .unwrap_or(ResolvedEdgeRouteKind::Bezier);
92 let path = match kind {
93 ResolvedEdgeRouteKind::Straight => straight_edge_path(endpoints.source, endpoints.target),
94 ResolvedEdgeRouteKind::Orthogonal | ResolvedEdgeRouteKind::SmoothStep => {
95 smoothstep_edge_path(
96 endpoints.source,
97 endpoints.target,
98 SmoothStepEdgeOptions::default(),
99 )
100 }
101 ResolvedEdgeRouteKind::Bezier => bezier_edge_path(
102 endpoints.source,
103 endpoints.target,
104 BezierEdgeOptions::default(),
105 ),
106 }?;
107
108 Some(EdgeRouteFacts {
109 kind,
110 endpoints,
111 path,
112 label_anchor: edge.view.label_anchor.unwrap_or(EdgeLabelAnchor::Center),
113 hit_test: EdgeHitTestOptions::default(),
114 interaction: EdgeInteractionFacts {
115 selectable: false,
116 selected: false,
117 focusable: false,
118 deletable: false,
119 reconnect_source: false,
120 reconnect_target: false,
121 },
122 })
123}