// SVG Monitor JavaScript Module for RobotMonitor // Handles mouse events for zoom and pan (simplified version of svgEditor.js) let svgElement = null; let dotNetRef = null; let isInitialized = false; /** * Initialize the SVG monitor with event listeners * @param {SVGElement} svg - The SVG element * @param {DotNetObjectReference} dotNet - Reference to Blazor component */ export function initMonitor(svg, dotNet) { svgElement = svg; dotNetRef = dotNet; if (!svgElement || !dotNetRef) { console.error('SVG Monitor: Invalid initialization parameters'); return; } // Mouse events (only zoom and pan) svgElement.addEventListener('mousemove', handleMouseMove); svgElement.addEventListener('mousedown', handleMouseDown); svgElement.addEventListener('mouseup', handleMouseUp); svgElement.addEventListener('wheel', handleWheel, { passive: false }); svgElement.addEventListener('contextmenu', handleContextMenu); // Prevent default drag behavior svgElement.addEventListener('dragstart', (e) => e.preventDefault()); isInitialized = true; console.log('SVG Monitor initialized'); } /** * Dispose the monitor and remove event listeners */ export function disposeMonitor() { if (svgElement) { svgElement.removeEventListener('mousemove', handleMouseMove); svgElement.removeEventListener('mousedown', handleMouseDown); svgElement.removeEventListener('mouseup', handleMouseUp); svgElement.removeEventListener('wheel', handleWheel); svgElement.removeEventListener('contextmenu', handleContextMenu); } svgElement = null; dotNetRef = null; isInitialized = false; console.log('SVG Monitor disposed'); } /** * Convert screen coordinates to SVG coordinates * @param {number} screenX - Screen X coordinate * @param {number} screenY - Screen Y coordinate * @returns {{x: number, y: number}} SVG coordinates */ function screenToSvg(screenX, screenY) { if (!svgElement) return { x: 0, y: 0 }; const pt = svgElement.createSVGPoint(); pt.x = screenX; pt.y = screenY; const ctm = svgElement.getScreenCTM(); if (!ctm) return { x: 0, y: 0 }; const svgPt = pt.matrixTransform(ctm.inverse()); return { x: svgPt.x, y: svgPt.y }; } /** * Export screenToSvg for use from Blazor * @param {number} screenX - Screen X coordinate * @param {number} screenY - Screen Y coordinate * @returns {number[]} SVG coordinates as [x, y] */ export function screenToSvgArray(screenX, screenY) { const coords = screenToSvg(screenX, screenY); return [coords.x, coords.y]; } /** * Handle mouse move event * @param {MouseEvent} e */ function handleMouseMove(e) { if (!dotNetRef) return; const svgCoords = screenToSvg(e.clientX, e.clientY); // Pass SVG coordinates and screen coordinates for panning dotNetRef.invokeMethodAsync('OnMouseMove', svgCoords.x, svgCoords.y, e.clientX, e.clientY); } /** * Handle mouse down event * @param {MouseEvent} e */ function handleMouseDown(e) { if (!dotNetRef) return; const svgCoords = screenToSvg(e.clientX, e.clientY); // Middle mouse button (button 1) - start pan // Also pass screen coordinates for incremental pan calculation dotNetRef.invokeMethodAsync('OnMouseDown', svgCoords.x, svgCoords.y, e.button, e.clientX, e.clientY); } /** * Handle mouse up event * @param {MouseEvent} e */ function handleMouseUp(e) { if (!dotNetRef) return; const svgCoords = screenToSvg(e.clientX, e.clientY); dotNetRef.invokeMethodAsync('OnMouseUp', svgCoords.x, svgCoords.y, e.button); } /** * Handle mouse wheel event (zoom) * @param {WheelEvent} e */ function handleWheel(e) { if (!dotNetRef) return; e.preventDefault(); const svgCoords = screenToSvg(e.clientX, e.clientY); dotNetRef.invokeMethodAsync('OnWheel', svgCoords.x, svgCoords.y, e.deltaY); } /** * Handle context menu (right click) * @param {MouseEvent} e */ function handleContextMenu(e) { // Prevent default context menu e.preventDefault(); }