1use serde::{Deserialize, Serialize};
2
3mod authoring;
4mod connection;
5mod graph;
6mod layout_facts;
7mod node;
8mod rendering;
9mod selection;
10mod viewport;
11
12pub use connection::ConformanceConnectionTargetFromHandlesInput;
13pub use layout_facts::{
14 ConformanceEdgeEndpointPosition, ConformanceLayoutEdgePosition,
15 ConformanceLayoutEdgeRouteFacts, ConformanceLayoutFactsConnectionTargetExpectation,
16 ConformanceLayoutFactsExpectation,
17};
18
19use crate::io::NodeGraphKeyCode;
20use crate::runtime::auto_pan::{AutoPanRequest, SelectionAutoPanRequest};
21use crate::runtime::connection::{
22 ConnectEdgeRequest, ConnectionEndIntent, ConnectionLifecycleResult, ConnectionTargetInput,
23 ReconnectEdgeRequest, ResolvedConnectionTarget,
24};
25use crate::runtime::drag::{NodeNudgeRequest, PointerGestureClaim};
26use crate::runtime::events::{ConnectStart, NodeGraphGestureEvent};
27use crate::runtime::measurement::NodeMeasurement;
28use crate::runtime::rendering::RenderingQueryResult;
29use crate::runtime::resize::{NodePointerResizeRequest, NodeResizeRequest};
30use crate::runtime::selection::NodePointerDownInput;
31use crate::runtime::selection::SelectionBoxInput;
32use crate::runtime::viewport::{
33 ViewportAnimationFrame, ViewportAnimationPlan, ViewportAnimationRequest,
34 ViewportDoubleClickZoomInput, ViewportDragPanInput, ViewportGestureContext,
35 ViewportGestureRejection, ViewportPanInertiaFrame, ViewportPanInertiaRequest,
36 ViewportPanRequest, ViewportScrollInput, ViewportZoomRequest,
37};
38use crate::schema::NodeActionDescriptor;
39use jellyflow_core::core::{CanvasPoint, CanvasSize, EdgeId, GroupId, NodeId};
40use jellyflow_core::ops::GraphTransaction;
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
43#[allow(clippy::large_enum_variant)]
44#[serde(tag = "kind", content = "data", rename_all = "snake_case")]
45pub enum ConformanceAction {
46 DispatchTransaction {
53 transaction: GraphTransaction,
54 },
55 ApplyNodeDrag {
56 node: NodeId,
57 to: CanvasPoint,
58 },
59 ApplyNodeDragSession {
60 node: NodeId,
61 start: CanvasPoint,
62 to: CanvasPoint,
63 },
64 AssertNodePosition {
65 node: NodeId,
66 expected: CanvasPoint,
67 },
68 ApplyNodeResize {
69 request: NodeResizeRequest,
70 },
71 ApplyNodePointerResize {
72 request: NodePointerResizeRequest,
73 },
74 ApplyNodePointerResizeSession {
75 request: NodePointerResizeRequest,
76 },
77 ApplyNodePointerDown {
78 input: NodePointerDownInput,
79 #[serde(default, skip_serializing_if = "Option::is_none")]
80 expected_claim: Option<PointerGestureClaim>,
81 },
82 ApplySelectionBox {
83 input: SelectionBoxInput,
84 },
85 AssertConnectionTarget {
86 input: ConnectionTargetInput,
87 expected: ResolvedConnectionTarget,
88 },
89 AssertConnectionTargetFromHandles {
90 input: ConformanceConnectionTargetFromHandlesInput,
91 expected: ResolvedConnectionTarget,
92 },
93 AssertConnectionLifecycle {
94 start: ConnectStart,
95 #[serde(default, skip_serializing_if = "Option::is_none")]
96 hover: Option<ResolvedConnectionTarget>,
97 intent: ConnectionEndIntent,
98 expected: ConnectionLifecycleResult,
99 },
100 ApplyConnectEdge {
101 request: ConnectEdgeRequest,
102 },
103 ApplyConnectEdgeSession {
104 start: ConnectStart,
105 request: ConnectEdgeRequest,
106 },
107 ApplyReconnectEdge {
108 request: ReconnectEdgeRequest,
109 },
110 ApplyNodeNudge {
111 request: NodeNudgeRequest,
112 },
113 ApplyDeleteSelection,
114 ApplyDeleteSelectionForKey {
115 key: NodeGraphKeyCode,
116 },
117 ApplyAutoPan {
118 request: AutoPanRequest,
119 },
120 ApplySelectionAutoPan {
121 request: SelectionAutoPanRequest,
122 },
123 ReportNodeMeasurement {
124 measurement: NodeMeasurement,
125 },
126 AssertLayoutFacts {
127 viewport_size: CanvasSize,
128 expected: ConformanceLayoutFactsExpectation,
129 },
130 ApplyViewportPan {
131 request: ViewportPanRequest,
132 },
133 ApplyViewportPanConstrained {
134 request: ViewportPanRequest,
135 viewport_size: CanvasSize,
136 },
137 ApplyViewportZoom {
138 request: ViewportZoomRequest,
139 },
140 ApplyViewportZoomConstrained {
141 request: ViewportZoomRequest,
142 viewport_size: CanvasSize,
143 },
144 ApplyViewportAnimationFrame {
145 request: ViewportAnimationRequest,
146 elapsed_seconds: f32,
147 },
148 ApplyViewportAnimationFrames {
149 request: ViewportAnimationRequest,
150 elapsed_seconds: Vec<f32>,
151 },
152 AssertViewportAnimationFrame {
153 request: ViewportAnimationRequest,
154 elapsed_seconds: f32,
155 expected: ViewportAnimationFrame,
156 },
157 ApplyViewportPanInertiaFrame {
158 request: ViewportPanInertiaRequest,
159 elapsed_seconds: f32,
160 },
161 ApplyViewportPanInertiaFrames {
162 request: ViewportPanInertiaRequest,
163 elapsed_seconds: Vec<f32>,
164 },
165 AssertViewportPanInertiaFrame {
166 request: ViewportPanInertiaRequest,
167 elapsed_seconds: f32,
168 expected: ViewportPanInertiaFrame,
169 },
170 ExpectViewportPanInertiaRejected {
171 request: ViewportPanInertiaRequest,
172 },
173 AssertViewportDoubleClickZoom {
174 input: ViewportDoubleClickZoomInput,
175 #[serde(default, skip_serializing_if = "Option::is_none")]
176 expected: Option<ViewportAnimationPlan>,
177 #[serde(default, skip_serializing_if = "Option::is_none")]
178 expect_rejection: Option<ViewportGestureRejection>,
179 },
180 ApplyViewportScrollGesture {
181 context: ViewportGestureContext,
182 input: ViewportScrollInput,
183 #[serde(default, skip_serializing_if = "Option::is_none")]
184 expect_rejection: Option<ViewportGestureRejection>,
185 },
186 ApplyViewportDragPanGesture {
187 context: ViewportGestureContext,
188 input: ViewportDragPanInput,
189 #[serde(default, skip_serializing_if = "Option::is_none")]
190 expect_rejection: Option<ViewportGestureRejection>,
191 },
192 ApplyViewportDragPanSession {
193 context: ViewportGestureContext,
194 input: ViewportDragPanInput,
195 #[serde(default, skip_serializing_if = "Option::is_none")]
196 expect_rejection: Option<ViewportGestureRejection>,
197 },
198 SetViewport {
199 pan: CanvasPoint,
200 zoom: f32,
201 },
202 AssertRenderingQuery {
203 viewport_size: CanvasSize,
204 expected: RenderingQueryResult,
205 },
206 SetSelection {
207 nodes: Vec<NodeId>,
208 edges: Vec<EdgeId>,
209 groups: Vec<GroupId>,
210 },
211 EmitGesture {
212 event: NodeGraphGestureEvent,
213 },
214 AssertNodeActionAvailability {
215 action: NodeActionDescriptor,
216 #[serde(default)]
217 expect_enabled: bool,
218 },
219}
220
221impl ConformanceAction {
222 pub fn kind(&self) -> &'static str {
223 graph::kind(self)
224 .or_else(|| authoring::kind(self))
225 .or_else(|| node::kind(self))
226 .or_else(|| selection::kind(self))
227 .or_else(|| connection::kind(self))
228 .or_else(|| layout_facts::kind(self))
229 .or_else(|| viewport::kind(self))
230 .or_else(|| rendering::kind(self))
231 .expect("all conformance action variants must have a kind")
232 }
233}