/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ /* * * @author Toni Kalajainen */ package org.simantics.g2d.participant; import java.awt.Cursor; import java.awt.geom.Point2D; import org.simantics.g2d.canvas.ICanvasContext; import org.simantics.g2d.canvas.IMouseCursorContext; import org.simantics.g2d.canvas.IMouseCursorHandle; import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant; import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency; import org.simantics.g2d.participant.MouseUtil.MouseInfo; import org.simantics.scenegraph.g2d.events.Event; import org.simantics.scenegraph.g2d.events.MouseEvent; import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler; import org.simantics.scenegraph.g2d.events.KeyEvent.KeyReleasedEvent; import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent; import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent; import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent; import org.simantics.scenegraph.g2d.events.MouseEvent.MouseWheelMovedEvent; import org.simantics.scenegraph.g2d.nodes.NavigationNode; import org.simantics.utils.datastructures.hints.IHintContext.Key; import org.simantics.utils.datastructures.hints.IHintContext.KeyOf; /** * Mouse pan & zoom * * Keyboard pan & zoom & zoom to fit etc * * This interactor depends on : - TransformUtil - MouseUtil - KeyUtil - * PanZoomRotateHandler * * TODO Add rotate mode * * @deprecated this logic has been moved into scenegraph {@link NavigationNode}. * Using this participant will cause double navigation. */ @Deprecated public class MousePanZoomInteractor extends AbstractCanvasParticipant { @Dependency TransformUtil util; @Dependency MouseUtil mice; @Dependency KeyUtil keys; @Dependency PanZoomRotateHandler pzr; /** Event priority for initiating pan / zoom */ public final static int MOUSE_PAN_PRIORITY = Integer.MAX_VALUE - 2000; /** Event priority when panning is enabled */ public final static int PAN_PRIORITY = Integer.MAX_VALUE - 1000; public final static int ZOOM_PRIORITY = Integer.MAX_VALUE - 1000 +1; /** Cursor when panning */ public final static Cursor PAN_CURSOR = new Cursor(Cursor.MOVE_CURSOR); /** Cursor when panning */ public final static Cursor ZOOM_CURSOR = new Cursor(Cursor.N_RESIZE_CURSOR); /** Is pan enabled */ public final static Key KEY_MOUSE_PAN_ENABLED = new KeyOf(Boolean.class); /** Is zoom enabled */ public final static Key KEY_MOUSE_ZOOM_ENABLED = new KeyOf(Boolean.class); /** are mouse wheel action enabled */ public final static Key KEY_MOUSE_WHEEL_ZOOM_PAN_ENABLED = new KeyOf(Boolean.class); /** The speed of mouse zoom , eg 0..100..X */ public final static Key KEY_MOUSE_ZOOM_SPEED = new KeyOf(Double.class); /** Default mouse zoom speed */ public final static double DEFAULT_MOUSE_ZOOM_SPEED = 100; /** The speed of mouse zoom , eg 0..100..X */ public final static Key KEY_MOUSE_WHEEL_ZOOM_SPEED = new KeyOf(Double.class); /** Default mouse zoom speed */ public final static double DEFAULT_MOUSE_WHEEL_ZOOM_SPEED = 1000; /** The speed of mouse zoom , eg 0..100..X */ public final static Key KEY_MOUSE_WHEEL_TRANSLATE_AMOUNT = new KeyOf(Double.class); /** Default mouse zoom speed */ public final static double DEFAULT_MOUSE_WHEEL_TRANSLATE_AMOUNT = 10; @Override public void addedToContext(ICanvasContext ctx) { super.addedToContext(ctx); // Set Default values setHint(KEY_MOUSE_ZOOM_SPEED, DEFAULT_MOUSE_ZOOM_SPEED); setHint(KEY_MOUSE_ZOOM_ENABLED, true); setHint(KEY_MOUSE_PAN_ENABLED, true); setHint(KEY_MOUSE_WHEEL_ZOOM_PAN_ENABLED, true); setHint(KEY_MOUSE_WHEEL_ZOOM_SPEED, DEFAULT_MOUSE_WHEEL_ZOOM_SPEED); setHint(KEY_MOUSE_WHEEL_TRANSLATE_AMOUNT, DEFAULT_MOUSE_WHEEL_TRANSLATE_AMOUNT); } /** * Inits mouse pan and zoom interactors. * Eats mouse presses if shift is pressed. * * @param e * @return */ @EventHandler(priority = MOUSE_PAN_PRIORITY) public boolean handleEvent(MouseEvent e) { assertDependencies(); if (e.context instanceof MouseUtil) return false; if ((e instanceof MouseButtonPressedEvent) && (e.stateMask & MouseEvent.SHIFT_MASK) != 0 && ((MouseButtonPressedEvent)e).button==MouseEvent.LEFT_BUTTON) return true; // Mouse pan & zoom if (e instanceof MouseMovedEvent) { MouseMovedEvent mme = (MouseMovedEvent) e; MouseInfo mi = mice.getMouseInfo(mme.mouseId); if (mi == null) return false; if ((e.stateMask & MouseEvent.SHIFT_MASK) != 0 & mi.isMouseButtonPressed(MouseEvent.LEFT_BUTTON)) { if (!isPanEnabled()) return false; if (!isPanning()) { getContext().add( new PanMode(mme.mouseId, mme.controlPosition, MouseEvent.LEFT_BUTTON) ); } return true; } if (mi.isMouseButtonPressed(MouseEvent.MIDDLE_BUTTON)) { if (!isPanEnabled()) return false; if (!isPanning()) { getContext().add( new PanMode(mme.mouseId, mme.controlPosition, MouseEvent.MIDDLE_BUTTON) ); } return true; } if ((e.stateMask & MouseEvent.SHIFT_MASK) != 0 & mi.isMouseButtonPressed(MouseEvent.RIGHT_BUTTON)) { if (!isZoomEnabled()) return false; if (!isZooming()) { Point2D diagramPosition = util.getInverseTransform().transform(mme.controlPosition, new Point2D.Double()); getContext().add( new ZoomMode(mme.mouseId, mme.controlPosition, diagramPosition, MouseEvent.RIGHT_BUTTON) ); } return true; } } // Mouse wheel zoom / scroll if (e instanceof MouseWheelMovedEvent) { if (!isMouseWheelZoomPanEnabled()) return false; MouseWheelMovedEvent we = (MouseWheelMovedEvent) e; //if (!mm.isMouseButtonPressed(we.mouseId, MouseEvent.MIDDLE_BUTTON)) /* if (!ctrl()) { if (we.scrollType == MouseWheelMovedEvent.WHEEL_UNIT_SCROLL) { double dy = we.wheelRotation * getMouseWheelTranslateAmount(); if (shift()) util.translateWithControlCoordinates(new Point2D.Double(dy, 0)); else util.translateWithControlCoordinates(new Point2D.Double(0, dy)); return true; } } else */ { if (we.scrollType == MouseWheelMovedEvent.WHEEL_UNIT_SCROLL) { double dy = we.wheelRotation; double zoom = getMouseWheelZoomSpeed(); double base = 1.00 + (zoom / 10000); double scaleFactor = Math.pow(base, dy); scaleFactor = pzr.limitScaleFactor(scaleFactor); util.zoomAroundControlPoint(scaleFactor, we.controlPosition); //ti.zoom(scaleFactor); return true; } } } return false; } public boolean isPanEnabled() { Boolean h = getHint(KEY_MOUSE_PAN_ENABLED); if (h==null) return false; return h; } public boolean isPanning() { return !getContext().getItemsByClass(PanMode.class).isEmpty(); } public boolean isZooming() { return !getContext().getItemsByClass(ZoomMode.class).isEmpty(); } public boolean isZoomEnabled() { Boolean h = getHint(KEY_MOUSE_ZOOM_ENABLED); if (h==null) return false; return h; } public boolean isMouseWheelZoomPanEnabled() { Boolean h = getHint(KEY_MOUSE_WHEEL_ZOOM_PAN_ENABLED); if (h==null) return false; return h; } /** * is Shift key down * @return */ /*public boolean shift() { return keys.isKeyPressed(KeyEvent.VK_SHIFT); } public boolean ctrl() { return keys.isKeyPressed(KeyEvent.VK_CONTROL); }*/ public double getMouseZoomSpeed() { Double h = getHint(KEY_MOUSE_ZOOM_SPEED); if (h==null) return DEFAULT_MOUSE_ZOOM_SPEED; return h; } public double getMouseWheelZoomSpeed() { Double h = getHint(KEY_MOUSE_WHEEL_ZOOM_SPEED); if (h==null) return DEFAULT_MOUSE_WHEEL_ZOOM_SPEED; return h; } public double getMouseWheelTranslateAmount() { Double h = getHint(KEY_MOUSE_WHEEL_TRANSLATE_AMOUNT); if (h==null) return DEFAULT_MOUSE_WHEEL_TRANSLATE_AMOUNT; return h; } /** * Shift and left mouse button is pressed, do panning */ class PanMode extends AbstractCanvasParticipant { @Dependency TransformUtil util; final int mouseId; int releaseButton; // Mouse system coordinates Point2D mousePos; IMouseCursorHandle cursor; public PanMode(int mouseId, Point2D mousePos, int releaseButton) { super(); this.mouseId = mouseId; this.mousePos = new Point2D.Double(mousePos.getX(), mousePos.getY()); this.releaseButton = releaseButton; } @Override public void addedToContext(ICanvasContext ctx) { super.addedToContext(ctx); IMouseCursorContext mctx = getContext().getMouseCursorContext(); if (mctx!=null) cursor = mctx.setCursor(mouseId, PAN_CURSOR); } @EventHandler(priority = PAN_PRIORITY) public boolean handleEvent(Event e) { if (e instanceof MouseButtonReleasedEvent) { MouseButtonReleasedEvent mpe = (MouseButtonReleasedEvent) e; if (mpe.button == releaseButton && mpe.mouseId == mouseId) { remove(); return false; } } if (e instanceof KeyReleasedEvent) { KeyReleasedEvent ke = (KeyReleasedEvent) e; if (ke.keyCode == java.awt.event.KeyEvent.VK_SHIFT) { remove(); return false; } } if (e instanceof MouseMovedEvent) { if (e.getContext() instanceof MouseUtil) return true; MouseMovedEvent mme = (MouseMovedEvent) e; if (mme.mouseId == mouseId) { Point2D oldPos = mousePos; Point2D newPos = mme.controlPosition; double dx = newPos.getX() - oldPos.getX(); double dy = newPos.getY() - oldPos.getY(); if (dx==0 && dy==0) return true; this.mousePos.setLocation(newPos); util.translateWithControlCoordinates(new Point2D.Double(dx, dy)); return true; } } return false; } @Override public void removedFromContext(ICanvasContext ctx) { if (cursor!=null) { cursor.remove(); cursor = null; } super.removedFromContext(ctx); } } /** * Shift and right mouse button is pressed, do zooming */ class ZoomMode extends AbstractCanvasParticipant { final int mouseId; int releaseButton; // Mouse system coordinates Point2D prevMousePos; Point2D origControlMousePos; Point2D origDiagramMousePos; IMouseCursorHandle cursor; public ZoomMode(int mouseId, Point2D controlMousePos, Point2D mouseDiagramPos, int releaseButton) { super(); this.mouseId = mouseId; this.prevMousePos = (Point2D) controlMousePos.clone(); this.origControlMousePos = (Point2D) controlMousePos.clone(); this.origDiagramMousePos = (Point2D) mouseDiagramPos.clone(); this.releaseButton = releaseButton; } @Override public void addedToContext(ICanvasContext ctx) { super.addedToContext(ctx); IMouseCursorContext mctx = getContext().getMouseCursorContext(); if (mctx!=null) cursor = mctx.setCursor(mouseId, ZOOM_CURSOR); } @EventHandler(priority = ZOOM_PRIORITY) public boolean handleEvent(Event e) { if (e instanceof MouseButtonReleasedEvent) { MouseButtonReleasedEvent mpe = (MouseButtonReleasedEvent) e; if (mpe.button == releaseButton && mpe.mouseId == mouseId) { remove(); return false; } } if (e instanceof KeyReleasedEvent) { KeyReleasedEvent ke = (KeyReleasedEvent) e; if (ke.keyCode == java.awt.event.KeyEvent.VK_SHIFT) { remove(); return false; } } if (e instanceof MouseMovedEvent) { if (e.getContext() instanceof MouseUtil) return true; MouseMovedEvent mme = (MouseMovedEvent) e; if (mme.mouseId == mouseId) { Point2D oldPos = prevMousePos; Point2D newPos = mme.controlPosition; double dy = newPos.getY() - oldPos.getY(); // double dx = newPos.getX() - oldPos.getX(); this.prevMousePos.setLocation(newPos); double zoomSpeed = getMouseZoomSpeed(); double base = 1.00 + (zoomSpeed / 10000); double scaleFactor = Math.pow(base, -dy); scaleFactor = pzr.limitScaleFactor(scaleFactor); util.zoomAroundDiagramPoint(scaleFactor, origDiagramMousePos); return true; } } return false; } @Override public void removedFromContext(ICanvasContext ctx) { if (cursor!=null) { cursor.remove(); cursor = null; } super.removedFromContext(ctx); } } }