X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.g2d%2Fsrc%2Forg%2Fsimantics%2Fg2d%2Fparticipant%2FZoomToAreaHandler.java;fp=bundles%2Forg.simantics.g2d%2Fsrc%2Forg%2Fsimantics%2Fg2d%2Fparticipant%2FZoomToAreaHandler.java;h=e727564fd05379fdcdfd425ca0f51551de35b6f1;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/participant/ZoomToAreaHandler.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/participant/ZoomToAreaHandler.java new file mode 100644 index 000000000..e727564fd --- /dev/null +++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/participant/ZoomToAreaHandler.java @@ -0,0 +1,236 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +package org.simantics.g2d.participant; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Shape; +import java.awt.geom.Path2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +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.canvas.impl.SGNodeReflection.SGCleanup; +import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit; +import org.simantics.g2d.diagram.DiagramHints; +import org.simantics.g2d.diagram.handler.PickContext; +import org.simantics.g2d.diagram.participant.Selection; +import org.simantics.g2d.diagram.participant.pointertool.AbstractMode; +import org.simantics.g2d.participant.MouseUtil.MouseInfo; +import org.simantics.scenegraph.g2d.G2DParentNode; +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.MouseEvent.MouseButtonEvent; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseClickEvent; +import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent; +import org.simantics.scenegraph.g2d.events.command.CommandEvent; +import org.simantics.scenegraph.g2d.events.command.Commands; +import org.simantics.scenegraph.g2d.nodes.ShapeNode; +import org.simantics.utils.ObjectUtils; +import org.simantics.utils.page.MarginUtils; + +/** + * ZoomToAreaHandler starts an area zoom mode when a ZOOM_TO_AREA command is + * issued. + * + * @author Tuukka Lehtonen + */ +public class ZoomToAreaHandler extends AbstractCanvasParticipant { + + public final static Cursor ZOOM_CURSOR = new Cursor(Cursor.CROSSHAIR_CURSOR); + + @EventHandler(priority = 0) + public boolean handleZoomToArea(CommandEvent event) { + if (Commands.ZOOM_TO_AREA.equals( event.command )) { + if (!getContext().containsItemByClass(ZoomToAreaMode.class)) { + getContext().add( new ZoomToAreaMode() ); + setDirty(); + } + return true; + } + return false; + } + + class ZoomToAreaMode extends AbstractMode { + + @Dependency TransformUtil util; + @Dependency Selection selection; + @Dependency PickContext pickContext; + @Dependency KeyUtil keyUtil; + @Dependency MouseUtil mouseUtil; + @Dependency CanvasBoundsParticipant canvasBounds; + + public final BasicStroke STROKE = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 10f, new float[] {4,2}, 0); + + public static final int PAINT_PRIORITY = 30; + + Point2D startingPoint; + Point2D currentPoint; + IMouseCursorHandle cursor; + + public ZoomToAreaMode() { + super(0); + } + + @Override + public void addedToContext(ICanvasContext ctx) { + super.addedToContext(ctx); + IMouseCursorContext mctx = getContext().getMouseCursorContext(); + if (mctx != null) + cursor = mctx.setCursor(getMouseId(), ZOOM_CURSOR); + MouseInfo mi = mouseUtil.getMouseInfo(getMouseId()); + if (mi != null) + currentPoint = mi.canvasPosition; + } + + @Override + public void removedFromContext(ICanvasContext ctx) { + if (cursor != null) { + cursor.remove(); + cursor = null; + } + super.removedFromContext(ctx); + } + + @EventHandler(priority = 10) + public boolean handleEvent(Event e) { + if (e instanceof CommandEvent) { + CommandEvent ce = (CommandEvent) e; + if (ce.command.equals( Commands.CANCEL )){ + setDirty(); + remove(); + return true; + } + } else if (e instanceof MouseMovedEvent) { + MouseMovedEvent event = (MouseMovedEvent) e; + if (event.mouseId != getMouseId()) return false; + Point2D canvasPos = util.controlToCanvas(event.controlPosition, null); + if (!ObjectUtils.objectEquals(currentPoint, canvasPos)) + { + currentPoint = canvasPos; + update(getBox()); + setDirty(); + } + return false; + } else if (e instanceof MouseButtonEvent) { + MouseButtonEvent event = (MouseButtonEvent) e; + + if (event.mouseId != getMouseId()) return false; + if (event.button != MouseEvent.LEFT_BUTTON) return false; + + // Eat all other mouse button events besides press and click. + // Must use mouse clicks here because otherwise selection + // participants etc. might alter selections on the next incoming + // mouse click event, which only confuses the user. + if (e instanceof MouseClickEvent) { + Point2D canvasPos = util.controlToCanvas(event.controlPosition, null); + currentPoint = canvasPos; + + if (startingPoint == null) { + // Start marking the box + startingPoint = currentPoint; + setDirty(); + return true; + } + + Rectangle2D area = new Rectangle2D.Double(); + area.setFrameFromDiagonal(startingPoint, currentPoint); + + Rectangle2D controlArea = canvasBounds.getControlBounds(); + util.fitArea(controlArea, area, PanZoomRotateHandler.getZoomToFitMargins(getHintStack())); + + setDirty(); + remove(); + return true; + } + return true; + } + return false; + } + + /** + * Get selection box in control coordinates + * @return control coordinates + */ + protected Rectangle2D getBox() { + if (startingPoint == null) + return null; + Point2D p1 = startingPoint; + Point2D p2 = currentPoint; + double ax = p1.getX(); + double ay = p1.getY(); + double bx = p2.getX(); + double by = p2.getY(); + if (bx < ax) { + double temp = ax; + ax = bx; + bx = temp; + } + if (by < ay) { + double temp = ay; + ay = by; + by = temp; + } + return new Rectangle2D.Double(ax, ay, bx - ax, by - ay); + } + + protected Path2D getCrossHair(Rectangle2D controlBounds) { + Point2D controlPos = util.canvasToControl(currentPoint, null); + Path2D path = new Path2D.Double(); + path.moveTo(controlBounds.getMinX(), controlPos.getY()); + path.lineTo(controlBounds.getMaxX(), controlPos.getY()); + path.moveTo(controlPos.getX(), controlBounds.getMinY()); + path.lineTo(controlPos.getX(), controlBounds.getMaxY()); + return path; + } + + public synchronized Color getToolColor() + { + Color c = getHint(DiagramHints.KEY_SELECTION_FRAME_COLOR); + if (c!=null) return c; + return Color.BLACK; + } + + protected ShapeNode node = null; + + @SGInit + public void initSG(G2DParentNode parent) { + node = parent.addNode("zoom to area", ShapeNode.class); + node.setZIndex(PAINT_PRIORITY); + node.setStroke(STROKE); + node.setScaleStroke(true); + node.setColor(getToolColor()); + node.setFill(false); + } + + void update(Shape shape) { + if (node != null) { + node.setShape(shape); + } + } + + @SGCleanup + public void cleanupSG() { + if (node != null) { + node.remove(); + node = null; + } + } + } + +}