X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.g2d%2Fsrc%2Forg%2Fsimantics%2Fg2d%2Fparticipant%2FMousePanZoomInteractor.java;fp=bundles%2Forg.simantics.g2d%2Fsrc%2Forg%2Fsimantics%2Fg2d%2Fparticipant%2FMousePanZoomInteractor.java;h=53b25678dc619e8207fc5e05d6df061708ec83d0;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/participant/MousePanZoomInteractor.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/participant/MousePanZoomInteractor.java new file mode 100644 index 000000000..53b25678d --- /dev/null +++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/participant/MousePanZoomInteractor.java @@ -0,0 +1,434 @@ +/******************************************************************************* + * 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); + } + } + +}