1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.g2d.participant;
\r
14 import java.awt.BasicStroke;
\r
15 import java.awt.Color;
\r
16 import java.awt.Cursor;
\r
17 import java.awt.Shape;
\r
18 import java.awt.geom.Path2D;
\r
19 import java.awt.geom.Point2D;
\r
20 import java.awt.geom.Rectangle2D;
\r
22 import org.simantics.g2d.canvas.ICanvasContext;
\r
23 import org.simantics.g2d.canvas.IMouseCursorContext;
\r
24 import org.simantics.g2d.canvas.IMouseCursorHandle;
\r
25 import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant;
\r
26 import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;
\r
27 import org.simantics.g2d.canvas.impl.SGNodeReflection.SGCleanup;
\r
28 import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit;
\r
29 import org.simantics.g2d.diagram.DiagramHints;
\r
30 import org.simantics.g2d.diagram.handler.PickContext;
\r
31 import org.simantics.g2d.diagram.participant.Selection;
\r
32 import org.simantics.g2d.diagram.participant.pointertool.AbstractMode;
\r
33 import org.simantics.g2d.participant.MouseUtil.MouseInfo;
\r
34 import org.simantics.scenegraph.g2d.G2DParentNode;
\r
35 import org.simantics.scenegraph.g2d.events.Event;
\r
36 import org.simantics.scenegraph.g2d.events.MouseEvent;
\r
37 import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler;
\r
38 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonEvent;
\r
39 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseClickEvent;
\r
40 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent;
\r
41 import org.simantics.scenegraph.g2d.events.command.CommandEvent;
\r
42 import org.simantics.scenegraph.g2d.events.command.Commands;
\r
43 import org.simantics.scenegraph.g2d.nodes.ShapeNode;
\r
44 import org.simantics.utils.ObjectUtils;
\r
45 import org.simantics.utils.page.MarginUtils;
\r
48 * ZoomToAreaHandler starts an area zoom mode when a ZOOM_TO_AREA command is
\r
51 * @author Tuukka Lehtonen
\r
53 public class ZoomToAreaHandler extends AbstractCanvasParticipant {
\r
55 public final static Cursor ZOOM_CURSOR = new Cursor(Cursor.CROSSHAIR_CURSOR);
\r
57 @EventHandler(priority = 0)
\r
58 public boolean handleZoomToArea(CommandEvent event) {
\r
59 if (Commands.ZOOM_TO_AREA.equals( event.command )) {
\r
60 if (!getContext().containsItemByClass(ZoomToAreaMode.class)) {
\r
61 getContext().add( new ZoomToAreaMode() );
\r
69 class ZoomToAreaMode extends AbstractMode {
\r
71 @Dependency TransformUtil util;
\r
72 @Dependency Selection selection;
\r
73 @Dependency PickContext pickContext;
\r
74 @Dependency KeyUtil keyUtil;
\r
75 @Dependency MouseUtil mouseUtil;
\r
76 @Dependency CanvasBoundsParticipant canvasBounds;
\r
78 public final BasicStroke STROKE = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 10f, new float[] {4,2}, 0);
\r
80 public static final int PAINT_PRIORITY = 30;
\r
82 Point2D startingPoint;
\r
83 Point2D currentPoint;
\r
84 IMouseCursorHandle cursor;
\r
86 public ZoomToAreaMode() {
\r
91 public void addedToContext(ICanvasContext ctx) {
\r
92 super.addedToContext(ctx);
\r
93 IMouseCursorContext mctx = getContext().getMouseCursorContext();
\r
95 cursor = mctx.setCursor(getMouseId(), ZOOM_CURSOR);
\r
96 MouseInfo mi = mouseUtil.getMouseInfo(getMouseId());
\r
98 currentPoint = mi.canvasPosition;
\r
102 public void removedFromContext(ICanvasContext ctx) {
\r
103 if (cursor != null) {
\r
107 super.removedFromContext(ctx);
\r
110 @EventHandler(priority = 10)
\r
111 public boolean handleEvent(Event e) {
\r
112 if (e instanceof CommandEvent) {
\r
113 CommandEvent ce = (CommandEvent) e;
\r
114 if (ce.command.equals( Commands.CANCEL )){
\r
119 } else if (e instanceof MouseMovedEvent) {
\r
120 MouseMovedEvent event = (MouseMovedEvent) e;
\r
121 if (event.mouseId != getMouseId()) return false;
\r
122 Point2D canvasPos = util.controlToCanvas(event.controlPosition, null);
\r
123 if (!ObjectUtils.objectEquals(currentPoint, canvasPos))
\r
125 currentPoint = canvasPos;
\r
130 } else if (e instanceof MouseButtonEvent) {
\r
131 MouseButtonEvent event = (MouseButtonEvent) e;
\r
133 if (event.mouseId != getMouseId()) return false;
\r
134 if (event.button != MouseEvent.LEFT_BUTTON) return false;
\r
136 // Eat all other mouse button events besides press and click.
\r
137 // Must use mouse clicks here because otherwise selection
\r
138 // participants etc. might alter selections on the next incoming
\r
139 // mouse click event, which only confuses the user.
\r
140 if (e instanceof MouseClickEvent) {
\r
141 Point2D canvasPos = util.controlToCanvas(event.controlPosition, null);
\r
142 currentPoint = canvasPos;
\r
144 if (startingPoint == null) {
\r
145 // Start marking the box
\r
146 startingPoint = currentPoint;
\r
151 Rectangle2D area = new Rectangle2D.Double();
\r
152 area.setFrameFromDiagonal(startingPoint, currentPoint);
\r
154 Rectangle2D controlArea = canvasBounds.getControlBounds();
\r
155 util.fitArea(controlArea, area, PanZoomRotateHandler.getZoomToFitMargins(getHintStack()));
\r
167 * Get selection box in control coordinates
\r
168 * @return control coordinates
\r
170 protected Rectangle2D getBox() {
\r
171 if (startingPoint == null)
\r
173 Point2D p1 = startingPoint;
\r
174 Point2D p2 = currentPoint;
\r
175 double ax = p1.getX();
\r
176 double ay = p1.getY();
\r
177 double bx = p2.getX();
\r
178 double by = p2.getY();
\r
189 return new Rectangle2D.Double(ax, ay, bx - ax, by - ay);
\r
192 protected Path2D getCrossHair(Rectangle2D controlBounds) {
\r
193 Point2D controlPos = util.canvasToControl(currentPoint, null);
\r
194 Path2D path = new Path2D.Double();
\r
195 path.moveTo(controlBounds.getMinX(), controlPos.getY());
\r
196 path.lineTo(controlBounds.getMaxX(), controlPos.getY());
\r
197 path.moveTo(controlPos.getX(), controlBounds.getMinY());
\r
198 path.lineTo(controlPos.getX(), controlBounds.getMaxY());
\r
202 public synchronized Color getToolColor()
\r
204 Color c = getHint(DiagramHints.KEY_SELECTION_FRAME_COLOR);
\r
205 if (c!=null) return c;
\r
206 return Color.BLACK;
\r
209 protected ShapeNode node = null;
\r
212 public void initSG(G2DParentNode parent) {
\r
213 node = parent.addNode("zoom to area", ShapeNode.class);
\r
214 node.setZIndex(PAINT_PRIORITY);
\r
215 node.setStroke(STROKE);
\r
216 node.setScaleStroke(true);
\r
217 node.setColor(getToolColor());
\r
218 node.setFill(false);
\r
221 void update(Shape shape) {
\r
222 if (node != null) {
\r
223 node.setShape(shape);
\r
228 public void cleanupSG() {
\r
229 if (node != null) {
\r