Skip to main content

jellyflow_runtime/runtime/resize/
store.rs

1use crate::runtime::events::{
2    NodeGraphGestureEvent, NodeResizeEnd, NodeResizeEndOutcome, NodeResizeStart, NodeResizeUpdate,
3};
4use crate::runtime::store::{DispatchError, DispatchOutcome, NodeGraphStore};
5
6use super::planner::{plan_node_pointer_resize_with_policy_extent, plan_node_resize_with_context};
7use super::session::{NodeResizeSession, NodeResizeSessionUpdateRequest};
8use super::types::{
9    NodePointerResizeRequest, NodeResizeContext, NodeResizePlan, NodeResizeRequest,
10};
11
12#[derive(Debug, Clone)]
13pub struct NodeResizeSessionUpdateOutcome {
14    pub update: NodeResizeUpdate,
15    pub dispatch: DispatchOutcome,
16}
17
18#[derive(Debug, Clone)]
19pub struct NodeResizeSessionOutcome {
20    pub start: NodeResizeStart,
21    pub update: Option<NodeResizeSessionUpdateOutcome>,
22    pub end: NodeResizeEnd,
23}
24
25impl NodeResizeSessionOutcome {
26    pub fn end_outcome(&self) -> NodeResizeEndOutcome {
27        self.end.outcome
28    }
29
30    pub fn committed_update(&self) -> Option<&NodeResizeSessionUpdateOutcome> {
31        self.update.as_ref()
32    }
33}
34
35impl NodeGraphStore {
36    /// Plans a node resize update against the store's current graph.
37    pub fn plan_node_resize(&self, request: NodeResizeRequest) -> Option<NodeResizePlan> {
38        plan_node_resize_with_context(self.graph(), self.resize_context(), request)
39    }
40
41    /// Commits a node resize update through the normal store dispatch path.
42    pub fn apply_node_resize(
43        &mut self,
44        request: NodeResizeRequest,
45    ) -> Result<Option<DispatchOutcome>, DispatchError> {
46        let Some(plan) = self.plan_node_resize(request) else {
47            return Ok(None);
48        };
49        self.dispatch_transaction(plan.transaction()).map(Some)
50    }
51
52    /// Plans a pointer-driven node resize update against the store's current graph.
53    pub fn plan_node_pointer_resize(
54        &self,
55        request: NodePointerResizeRequest,
56    ) -> Option<NodeResizePlan> {
57        let interaction = self.resolved_interaction_state();
58        let node_drag = interaction.node_drag_interaction();
59        let node_origin = node_drag.node_origin.normalized();
60        plan_node_pointer_resize_with_policy_extent(
61            self.graph(),
62            NodeResizeContext::new((node_origin.x, node_origin.y)),
63            node_drag.node_extent,
64            request,
65        )
66    }
67
68    /// Commits a pointer-driven node resize update through the normal store dispatch path.
69    pub fn apply_node_pointer_resize(
70        &mut self,
71        request: NodePointerResizeRequest,
72    ) -> Result<Option<DispatchOutcome>, DispatchError> {
73        let Some(plan) = self.plan_node_pointer_resize(request) else {
74            return Ok(None);
75        };
76        self.dispatch_transaction(plan.transaction()).map(Some)
77    }
78
79    /// Emits the start event for a headless pointer-driven node resize session.
80    pub fn start_node_resize_session(&mut self, session: NodeResizeSession) {
81        self.emit_gesture(NodeGraphGestureEvent::NodeResizeStart(session.start()));
82    }
83
84    /// Commits one pointer-driven session update and emits the derived resize update event.
85    pub fn apply_node_resize_session_update(
86        &mut self,
87        session: NodeResizeSession,
88        request: NodeResizeSessionUpdateRequest,
89    ) -> Result<Option<NodeResizeSessionUpdateOutcome>, DispatchError> {
90        let Some(plan) = self.plan_node_pointer_resize(session.pointer_resize_request(request))
91        else {
92            return Ok(None);
93        };
94        let update = session.update(&plan, request);
95        let dispatch = self.dispatch_transaction(plan.transaction())?;
96        self.emit_gesture(NodeGraphGestureEvent::NodeResizeUpdate(update.clone()));
97
98        Ok(Some(NodeResizeSessionUpdateOutcome { update, dispatch }))
99    }
100
101    /// Emits the end event for a headless pointer-driven node resize session.
102    pub fn finish_node_resize_session(
103        &mut self,
104        session: NodeResizeSession,
105        pointer: jellyflow_core::core::CanvasPoint,
106        outcome: NodeResizeEndOutcome,
107    ) {
108        self.emit_gesture(NodeGraphGestureEvent::NodeResizeEnd(
109            session.end(pointer, outcome),
110        ));
111    }
112
113    /// Runs a one-update pointer resize session through start, commit/update, and end events.
114    pub fn apply_node_resize_session(
115        &mut self,
116        session: NodeResizeSession,
117        request: NodeResizeSessionUpdateRequest,
118    ) -> Result<NodeResizeSessionOutcome, DispatchError> {
119        let start = session.start();
120        self.emit_gesture(NodeGraphGestureEvent::NodeResizeStart(start.clone()));
121        let update = self.apply_node_resize_session_update(session, request)?;
122        let outcome = if update.is_some() {
123            NodeResizeEndOutcome::Committed
124        } else {
125            NodeResizeEndOutcome::NoOp
126        };
127        let end = session.end(request.current, outcome);
128        self.emit_gesture(NodeGraphGestureEvent::NodeResizeEnd(end.clone()));
129
130        Ok(NodeResizeSessionOutcome { start, update, end })
131    }
132
133    fn resize_context(&self) -> NodeResizeContext {
134        let interaction = self.resolved_interaction_state();
135        let node_drag = interaction.node_drag_interaction();
136        let node_origin = node_drag.node_origin.normalized();
137        NodeResizeContext::new((node_origin.x, node_origin.y))
138    }
139}