jellyflow_runtime/runtime/store/view/
state.rs1use crate::io::NodeGraphViewState;
2use crate::runtime::events::ViewChange;
3use crate::runtime::viewport::{
4 ViewportConstraints, ViewportPanRequest, ViewportTransform, ViewportZoomRequest,
5 constrain_viewport, pan_viewport, zoom_viewport,
6};
7use jellyflow_core::core::{CanvasPoint, CanvasSize, EdgeId, GroupId, NodeId};
8
9use super::super::NodeGraphStore;
10use super::changes::ViewStateMutationKind;
11
12impl NodeGraphStore {
13 pub fn view_state(&self) -> &NodeGraphViewState {
14 &self.view_state
15 }
16
17 pub fn replace_view_state(&mut self, view_state: NodeGraphViewState) {
21 self.update_view_state_if_changed(
22 |current| *current = view_state,
23 ViewStateMutationKind::FullState,
24 );
25 }
26
27 pub fn update_view_state(&mut self, f: impl FnOnce(&mut NodeGraphViewState)) {
29 self.update_view_state_if_changed(f, ViewStateMutationKind::FullState);
30 }
31
32 pub fn set_viewport(&mut self, pan: CanvasPoint, zoom: f32) {
34 self.update_view_state_if_changed(
35 |view_state| view_state.set_viewport(pan, zoom),
36 ViewStateMutationKind::Viewport,
37 );
38 }
39
40 pub fn apply_viewport_pan(&mut self, request: ViewportPanRequest) -> Option<ViewportTransform> {
42 let current = ViewportTransform::from_view_state(&self.view_state)?;
43 let next = constrain_viewport(
44 pan_viewport(current, request)?,
45 ViewportConstraints::unconstrained(),
46 )?;
47 self.set_viewport(next.pan, next.zoom);
48 Some(next)
49 }
50
51 pub fn apply_viewport_pan_constrained(
53 &mut self,
54 request: ViewportPanRequest,
55 viewport_size: CanvasSize,
56 ) -> Option<ViewportTransform> {
57 let current = ViewportTransform::from_view_state(&self.view_state)?;
58 let next = constrain_viewport(
59 pan_viewport(current, request)?,
60 self.viewport_constraints(viewport_size),
61 )?;
62 self.set_viewport(next.pan, next.zoom);
63 Some(next)
64 }
65
66 pub fn apply_viewport_zoom(
68 &mut self,
69 request: ViewportZoomRequest,
70 ) -> Option<ViewportTransform> {
71 let current = ViewportTransform::from_view_state(&self.view_state)?;
72 let next = constrain_viewport(
73 zoom_viewport(current, request)?,
74 ViewportConstraints::unconstrained(),
75 )?;
76 self.set_viewport(next.pan, next.zoom);
77 Some(next)
78 }
79
80 pub fn apply_viewport_zoom_constrained(
82 &mut self,
83 request: ViewportZoomRequest,
84 viewport_size: CanvasSize,
85 ) -> Option<ViewportTransform> {
86 let current = ViewportTransform::from_view_state(&self.view_state)?;
87 let next = constrain_viewport(
88 zoom_viewport(current, request)?,
89 self.viewport_constraints(viewport_size),
90 )?;
91 self.set_viewport(next.pan, next.zoom);
92 Some(next)
93 }
94
95 pub fn set_selection(&mut self, nodes: Vec<NodeId>, edges: Vec<EdgeId>, groups: Vec<GroupId>) {
97 self.update_view_state_if_changed(
98 |view_state| view_state.set_selection(nodes, edges, groups),
99 ViewStateMutationKind::Selection,
100 );
101 }
102
103 fn update_view_state_if_changed(
104 &mut self,
105 mutate: impl FnOnce(&mut NodeGraphViewState),
106 kind: ViewStateMutationKind,
107 ) {
108 let before = self.view_state.clone();
109 mutate(&mut self.view_state);
110 kind.sanitize(&self.graph, &mut self.view_state);
111 let after = self.view_state.clone();
112
113 if !kind.changed(&before, &after) {
114 return;
115 }
116
117 let changes = kind.collect_changes(&before, &after);
118 self.publish_view_state_change(before, after, changes);
119 }
120
121 fn viewport_constraints(&self, viewport_size: CanvasSize) -> ViewportConstraints {
122 match self
123 .resolved_interaction_state()
124 .pan_interaction()
125 .translate_extent
126 {
127 Some(translate_extent) => {
128 ViewportConstraints::with_translate_extent(viewport_size, translate_extent)
129 }
130 None => ViewportConstraints::unconstrained(),
131 }
132 }
133
134 fn publish_view_state_change(
135 &mut self,
136 before: NodeGraphViewState,
137 after: NodeGraphViewState,
138 changes: Vec<ViewChange>,
139 ) {
140 self.publish_view_changed(&before, &after, &changes);
141 }
142}