use crate::io::{NodeGraphPanInteraction, NodeGraphPanOnScrollMode, NodeGraphZoomInteraction};
use crate::runtime::events::ViewportMoveKind;
use jellyflow_core::core::CanvasPoint;
use super::super::transform::{ViewportPanRequest, ViewportZoomRequest, valid_zoom};
use super::shared::{
effective_pan_on_drag_buttons, effective_pan_on_scroll_enabled, pan_on_drag_enabled,
};
use super::types::{
ViewportGestureContext, ViewportGestureIntent, ViewportGestureRejection, ViewportScrollInput,
};
pub fn resolve_viewport_scroll_gesture(
pan: &NodeGraphPanInteraction<'_>,
zoom: &NodeGraphZoomInteraction,
context: ViewportGestureContext,
input: ViewportScrollInput,
) -> Result<ViewportGestureIntent, ViewportGestureRejection> {
if context.user_selection_active {
return Err(ViewportGestureRejection::UserSelectionActive);
}
if !input.delta.is_finite() || !input.anchor_screen.is_finite() {
return Err(ViewportGestureRejection::InvalidInput);
}
if !any_viewport_gesture_enabled(pan, zoom, context) {
return Err(ViewportGestureRejection::AllViewportGesturesDisabled);
}
let pan_on_scroll = effective_pan_on_scroll_enabled(pan.pan_on_scroll, context);
let zoom_scroll = context.zoom_activation_key_pressed || zoom.zoom_on_scroll;
let pinch_zoom = input.ctrl_key && zoom.zoom_on_pinch;
if input.ctrl_key && !zoom.zoom_on_pinch {
return Err(ViewportGestureRejection::PinchDisabled);
}
if pinch_zoom {
return zoom_intent(ViewportMoveKind::ZoomPinch, input);
}
if pan_on_scroll && !context.zoom_activation_key_pressed {
if !pan.pan_on_scroll_speed.is_finite() {
return Err(ViewportGestureRejection::InvalidInput);
}
return Ok(ViewportGestureIntent::Pan {
kind: ViewportMoveKind::PanScroll,
request: ViewportPanRequest::new(scroll_pan_delta(pan, input.delta)),
});
}
if zoom_scroll {
return zoom_intent(ViewportMoveKind::ZoomWheel, input);
}
Err(ViewportGestureRejection::WheelDisabled)
}
fn any_viewport_gesture_enabled(
pan: &NodeGraphPanInteraction<'_>,
zoom: &NodeGraphZoomInteraction,
context: ViewportGestureContext,
) -> bool {
effective_pan_on_scroll_enabled(pan.pan_on_scroll, context)
|| pan_on_drag_enabled(effective_pan_on_drag_buttons(pan.pan_on_drag, context))
|| zoom.zoom_on_scroll
|| zoom.zoom_on_pinch
|| zoom.zoom_on_double_click
}
fn scroll_pan_delta(pan: &NodeGraphPanInteraction<'_>, delta: CanvasPoint) -> CanvasPoint {
let delta = match pan.pan_on_scroll_mode {
NodeGraphPanOnScrollMode::Free => delta,
NodeGraphPanOnScrollMode::Horizontal => CanvasPoint { x: delta.x, y: 0.0 },
NodeGraphPanOnScrollMode::Vertical => CanvasPoint { x: 0.0, y: delta.y },
};
CanvasPoint {
x: -delta.x * pan.pan_on_scroll_speed,
y: -delta.y * pan.pan_on_scroll_speed,
}
}
fn zoom_intent(
kind: ViewportMoveKind,
input: ViewportScrollInput,
) -> Result<ViewportGestureIntent, ViewportGestureRejection> {
if !valid_zoom(input.target_zoom) || !valid_zoom(input.min_zoom) || !valid_zoom(input.max_zoom)
{
return Err(ViewportGestureRejection::InvalidInput);
}
Ok(ViewportGestureIntent::Zoom {
kind,
request: ViewportZoomRequest::new(
input.anchor_screen,
input.target_zoom,
input.min_zoom,
input.max_zoom,
),
})
}