Skip to main content

jellyflow_runtime/runtime/selection/
compute.rs

1use crate::io::{NodeGraphInteractionState, NodeGraphSelectionMode, NodeGraphViewState};
2use crate::runtime::lookups::NodeGraphLookups;
3use crate::runtime::policy::resolve_node_interaction_policy;
4use crate::runtime::utils::{GetNodesInsideOptions, NodeInclusion, get_nodes_inside};
5use jellyflow_core::core::{CanvasRect, Graph};
6
7use super::additive::apply_additive_selection;
8use super::edges::selection_box_edges;
9use super::types::{
10    SelectionBoxDecision, SelectionBoxInput, SelectionBoxOptions, SelectionBoxResult,
11};
12
13/// Resolves the ordered selection state for a canvas-space marquee selection gesture.
14pub fn resolve_selection_box(
15    graph: &Graph,
16    lookups: &NodeGraphLookups,
17    view_state: &NodeGraphViewState,
18    interaction: &NodeGraphInteractionState,
19    input: SelectionBoxInput,
20) -> SelectionBoxDecision {
21    SelectionBoxDecision::new(compute_selection_box(
22        graph,
23        lookups,
24        view_state,
25        interaction,
26        input.rect,
27        input.options,
28    ))
29}
30
31/// Computes the ordered selection state for a canvas-space marquee selection box.
32pub fn compute_selection_box(
33    graph: &Graph,
34    lookups: &NodeGraphLookups,
35    view_state: &NodeGraphViewState,
36    interaction: &NodeGraphInteractionState,
37    rect: CanvasRect,
38    options: SelectionBoxOptions,
39) -> SelectionBoxResult {
40    let selection = interaction.selection_interaction();
41    if !selection.elements_selectable {
42        return apply_additive_selection(SelectionBoxResult::default(), graph, view_state, options);
43    }
44
45    let node_drag = interaction.node_drag_interaction();
46    let node_origin = node_drag.node_origin.normalized();
47    let mut nodes = get_nodes_inside(
48        lookups,
49        rect,
50        GetNodesInsideOptions {
51            inclusion: match selection.selection_mode {
52                NodeGraphSelectionMode::Full => NodeInclusion::Full,
53                NodeGraphSelectionMode::Partial => NodeInclusion::Partial,
54            },
55            node_origin: (node_origin.x, node_origin.y),
56            include_hidden: false,
57            fallback_size: options.fallback_size,
58        },
59    );
60    nodes.retain(|node| {
61        graph
62            .nodes
63            .get(node)
64            .is_some_and(|node| resolve_node_interaction_policy(node, interaction).selectable)
65    });
66    nodes.sort();
67    nodes.dedup();
68
69    let edges = selection_box_edges(
70        graph,
71        lookups,
72        interaction,
73        selection.box_select_edges,
74        &nodes,
75    );
76    apply_additive_selection(
77        SelectionBoxResult {
78            nodes,
79            edges,
80            groups: Vec::new(),
81        },
82        graph,
83        view_state,
84        options,
85    )
86}