Skip to main content

jellyflow_runtime/runtime/geometry/endpoints/
resolve.rs

1use jellyflow_core::core::{CanvasPoint, CanvasRect};
2
3use super::types::{
4    EdgeEndpointInput, EdgeEndpointPosition, EdgePosition, HandleBounds, HandlePosition,
5};
6
7pub fn edge_position(source: EdgeEndpointInput, target: EdgeEndpointInput) -> Option<EdgePosition> {
8    Some(EdgePosition {
9        source: handle_anchor_position(source.node_rect, source.handle, source.fallback_position)?,
10        target: handle_anchor_position(target.node_rect, target.handle, target.fallback_position)?,
11    })
12}
13
14pub fn handle_anchor_position(
15    node_rect: CanvasRect,
16    handle: Option<HandleBounds>,
17    fallback_position: HandlePosition,
18) -> Option<EdgeEndpointPosition> {
19    let (rect, position) = absolute_handle_rect(node_rect, handle, fallback_position)?;
20    let point = match position {
21        HandlePosition::Top => CanvasPoint {
22            x: rect.origin.x + rect.size.width * 0.5,
23            y: rect.origin.y,
24        },
25        HandlePosition::Right => CanvasPoint {
26            x: rect.origin.x + rect.size.width,
27            y: rect.origin.y + rect.size.height * 0.5,
28        },
29        HandlePosition::Bottom => CanvasPoint {
30            x: rect.origin.x + rect.size.width * 0.5,
31            y: rect.origin.y + rect.size.height,
32        },
33        HandlePosition::Left => CanvasPoint {
34            x: rect.origin.x,
35            y: rect.origin.y + rect.size.height * 0.5,
36        },
37    };
38
39    point
40        .is_finite()
41        .then_some(EdgeEndpointPosition { point, position })
42}
43
44pub fn handle_center_position(
45    node_rect: CanvasRect,
46    handle: Option<HandleBounds>,
47    fallback_position: HandlePosition,
48) -> Option<CanvasPoint> {
49    let (rect, _position) = absolute_handle_rect(node_rect, handle, fallback_position)?;
50    Some(CanvasPoint {
51        x: rect.origin.x + rect.size.width * 0.5,
52        y: rect.origin.y + rect.size.height * 0.5,
53    })
54}
55
56fn absolute_handle_rect(
57    node_rect: CanvasRect,
58    handle: Option<HandleBounds>,
59    fallback_position: HandlePosition,
60) -> Option<(CanvasRect, HandlePosition)> {
61    if !node_rect.is_positive_finite() {
62        return None;
63    }
64
65    let Some(handle) = handle else {
66        return Some((node_rect, fallback_position));
67    };
68
69    if !handle.rect.is_positive_finite() {
70        return None;
71    }
72
73    let rect = CanvasRect {
74        origin: CanvasPoint {
75            x: node_rect.origin.x + handle.rect.origin.x,
76            y: node_rect.origin.y + handle.rect.origin.y,
77        },
78        size: handle.rect.size,
79    };
80
81    rect.is_positive_finite().then_some((rect, handle.position))
82}