-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.g2d.participant;\r
-\r
-\r
-import static org.simantics.g2d.canvas.Hints.KEY_CANVAS_TRANSFORM;\r
-\r
-import java.awt.Graphics2D;\r
-import java.awt.geom.AffineTransform;\r
-import java.awt.geom.NoninvertibleTransformException;\r
-import java.awt.geom.Path2D;\r
-import java.awt.geom.Point2D;\r
-import java.awt.geom.Rectangle2D;\r
-\r
-import org.simantics.g2d.canvas.Hints;\r
-import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant;\r
-import org.simantics.g2d.canvas.impl.HintReflection.HintListener;\r
-import org.simantics.g2d.scenegraph.SceneGraphConstants;\r
-import org.simantics.g2d.utils.GeometryUtils;\r
-import org.simantics.scenegraph.g2d.IG2DNode;\r
-import org.simantics.scenegraph.utils.NodeUtil;\r
-import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
-import org.simantics.utils.datastructures.hints.IHintObservable;\r
-import org.simantics.utils.page.MarginUtils.Margins;\r
-\r
-/**\r
- * This class contains utilities for coordinate conversions between control\r
- * and canvas.\r
- * \r
- * @author Toni Kalajainen\r
- * @author J-P Laine\r
- * @author Tuukka Lehtonen\r
- */\r
-public class TransformUtil extends AbstractCanvasParticipant {\r
-\r
- /** Set dirty if transform changes */\r
- @HintListener(Class=Hints.class, Field="KEY_CANVAS_TRANSFORM")\r
- public void transformChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {\r
- if (oldValue != null && oldValue.equals(newValue)) return;\r
- //System.out.println("TransformUtil: CANVAS TRANSFORM CHANGED TO " + newValue);\r
- setDirty();\r
- }\r
-\r
- /**\r
- * Get viewport rectangle.\r
- * Transforms controlRect to area on canvas.\r
- * \r
- * @param controlRect rectangle on control\r
- * @return area on canvas\r
- */\r
- public Path2D toCanvasArea(Rectangle2D controlRect)\r
- {\r
- Point2D p[] = toCanvasCorners(controlRect);\r
-\r
- Path2D path = new Path2D.Double();\r
- path.moveTo(p[0].getX(), p[0].getY());\r
- path.lineTo(p[1].getX(), p[1].getY());\r
- path.lineTo(p[2].getX(), p[2].getY());\r
- path.lineTo(p[3].getX(), p[3].getY());\r
- path.closePath();\r
-\r
- return path;\r
- }\r
-\r
- /**\r
- * Returns 4 canvas corders in order: top-left, top-right, bottom-right, bottom-left\r
- * @param controlRect rectangle on control\r
- * @return area on canvas\r
- */\r
- public Point2D[] toCanvasCorners(Rectangle2D controlRect)\r
- {\r
- // at·control point = canvas point\r
- AffineTransform at = getHint(KEY_CANVAS_TRANSFORM);\r
- if (at==null) at = new AffineTransform();\r
-\r
- try {\r
- at = at.createInverse();\r
- } catch (NoninvertibleTransformException e) {\r
- }\r
-\r
- // Get corners\r
- Point2D p1 = new Point2D.Double(controlRect.getMinX(), controlRect.getMinY());\r
- Point2D p2 = new Point2D.Double(controlRect.getMaxX(), controlRect.getMinY());\r
- Point2D p3 = new Point2D.Double(controlRect.getMaxX(), controlRect.getMaxY());\r
- Point2D p4 = new Point2D.Double(controlRect.getMinX(), controlRect.getMaxY());\r
-\r
-\r
- // Convert corners\r
- at.transform(p1, p1);\r
- at.transform(p2, p2);\r
- at.transform(p3, p3);\r
- at.transform(p4, p4);\r
-\r
- return new Point2D[] {p1, p2, p3, p4};\r
- }\r
-\r
- /**\r
- * Converts control rectangle to a rectangle on canvas that contains control rect.\r
- * @param controlRect rectangle on control\r
- * @return rectangle on canvas that contains control rect\r
- */\r
- public Rectangle2D toCanvasRect(Rectangle2D controlRect)\r
- {\r
- AffineTransform at = getHint(KEY_CANVAS_TRANSFORM);\r
- if (at==null)\r
- return (Rectangle2D) controlRect.clone();\r
-\r
- Path2D path = toCanvasArea(controlRect);\r
- return path.getBounds2D();\r
- }\r
-\r
- /**\r
- * Transforms from canvas coordinate system to canvas coordinate system (also diagram)\r
- * @param g2d\r
- */\r
- public void controlToCanvas(Graphics2D g2d)\r
- {\r
- AffineTransform at = getHint(KEY_CANVAS_TRANSFORM);\r
- if (at==null) return;\r
- g2d.transform(at);\r
- }\r
-\r
- /**\r
- * Transforms coordinate system of g2d from canvas to control\r
- * @param g2d\r
- */\r
- public void canvasToControl(Graphics2D g2d)\r
- {\r
- AffineTransform at = getHint(KEY_CANVAS_TRANSFORM);\r
- if (at==null) return;\r
- try {\r
- g2d.transform(at.createInverse());\r
- } catch (NoninvertibleTransformException e) {\r
- }\r
- }\r
-\r
- /**\r
- * Convert control point to canvas point\r
- * @param g2d\r
- */\r
- public Point2D controlToCanvas(Point2D control, Point2D canvas)\r
- {\r
- AffineTransform at = getInverseTransform();\r
- if (canvas==null) canvas = new Point2D.Double();\r
- if (at==null) {\r
- canvas.setLocation(control);\r
- return canvas;\r
- }\r
- at.transform(control, canvas);\r
- return canvas;\r
- }\r
-\r
- /**\r
- * Convert canvas point to control\r
- * @param g2d\r
- */\r
- public Point2D canvasToControl(Point2D canvas, Point2D control)\r
- {\r
- AffineTransform at = getHint(KEY_CANVAS_TRANSFORM);\r
- if (control==null) control = new Point2D.Double();\r
- if (at==null) {\r
- control.setLocation(canvas);\r
- return canvas;\r
- }\r
- at.transform(canvas, control);\r
- return control;\r
- }\r
-\r
- /**\r
- * Convert canvas vector to control vector\r
- * @param g2d\r
- */\r
- public Point2D canvasVectorToControlVector(Point2D canvas, Point2D control)\r
- {\r
- AffineTransform at = getHint(KEY_CANVAS_TRANSFORM);\r
- if (control==null) control = new Point2D.Double();\r
- if (at==null) {\r
- control.setLocation(canvas);\r
- return canvas;\r
- }\r
- double x = canvas.getX();\r
- double y = canvas.getY();\r
-\r
- double m00 = at.getScaleX();\r
- double m11 = at.getScaleY();\r
- double m01 = at.getShearX();\r
- double m10 = at.getShearY();\r
-\r
- control.setLocation(\r
- x * m00 + y * m01,\r
- x * m10 + y * m11\r
- );\r
- return control;\r
- }\r
-\r
- /**\r
- * Convert control vector to canvas vector\r
- * @param g2d\r
- */\r
- public Point2D controlVectorToCanvasVector(Point2D control, Point2D canvas)\r
- {\r
- AffineTransform at = getInverseTransform();\r
- if (canvas==null) canvas = new Point2D.Double();\r
- if (at==null) {\r
- canvas.setLocation(control);\r
- return canvas;\r
- }\r
- double x = control.getX();\r
- double y = control.getY();\r
-\r
- double m00 = at.getScaleX();\r
- double m11 = at.getScaleY();\r
- double m01 = at.getShearX();\r
- double m10 = at.getShearY();\r
-\r
- canvas.setLocation(\r
- x * m00 + y * m01,\r
- x * m10 + y * m11\r
- );\r
- return canvas;\r
- }\r
- /**\r
- * Get a transform that converts\r
- * diagram coordinates to control coordinates.\r
- * \r
- * @return transform a clone\r
- */\r
- public AffineTransform getTransform()\r
- {\r
- AffineTransform at = getHint(KEY_CANVAS_TRANSFORM);\r
- if (at==null) return new AffineTransform();\r
- return (AffineTransform) at.clone();\r
- }\r
-\r
- /**\r
- * Get a transform that converts\r
- * diagram vector to control vector.\r
- * \r
- * @return transform a clone\r
- */\r
- public AffineTransform getVectorTransform()\r
- {\r
- AffineTransform at = getHint(KEY_CANVAS_TRANSFORM);\r
- if (at==null) return new AffineTransform();\r
- double m00 = at.getScaleX();\r
- double m11 = at.getScaleY();\r
- double m01 = at.getShearX();\r
- double m10 = at.getShearY();\r
- return new AffineTransform(m00, m10, m01, m11, 0, 0);\r
- }\r
-\r
-\r
- /**\r
- * Transforms control coordinates to diagram coordinates.\r
- * \r
- * @return inverted transform or <code>null</code> if inversion failed\r
- */\r
- public AffineTransform getInverseTransform()\r
- {\r
- AffineTransform at = getTransform();\r
- if (at==null) return null;\r
- try {\r
- at = at.createInverse();\r
- return at;\r
- } catch (NoninvertibleTransformException e) {\r
- return null;\r
- }\r
- }\r
-\r
- /**\r
- * Tries to invert the specified {@link AffineTransform}.\r
- * \r
- * @parameter at the transform to invert\r
- * @return inverted transform or <code>null</code> if inversion failed\r
- */\r
- public AffineTransform getInverseTransform(AffineTransform at)\r
- {\r
- if (at == null)\r
- return null;\r
- try {\r
- return at.createInverse();\r
- } catch (NoninvertibleTransformException e) {\r
- return null;\r
- }\r
- }\r
-\r
- /**\r
- * Transforms control vector to diagram vector\r
- * @return a clone\r
- */\r
- public AffineTransform getInverseVectorTransform()\r
- {\r
- AffineTransform at = getTransform();\r
- if (at==null) return null;\r
- try {\r
- at = at.createInverse();\r
- double m00 = at.getScaleX();\r
- double m11 = at.getScaleY();\r
- double m01 = at.getShearX();\r
- double m10 = at.getShearY();\r
- return new AffineTransform(m00, m10, m01, m11, 0, 0);\r
- } catch (NoninvertibleTransformException e) {\r
- return null;\r
- }\r
- }\r
-\r
-\r
- public void setTransform(AffineTransform at)\r
- {\r
- assert(at.getShearX()!=Double.POSITIVE_INFINITY && at.getShearX()!=Double.NEGATIVE_INFINITY);\r
- assert(at.getShearY()!=Double.POSITIVE_INFINITY && at.getShearY()!=Double.NEGATIVE_INFINITY);\r
- AffineTransform old = getHint(KEY_CANVAS_TRANSFORM);\r
- if(at.equals(old) == false) { // Send event only if the transform has really changed\r
- setHint(KEY_CANVAS_TRANSFORM, at);\r
-\r
- IG2DNode node = NodeUtil.findNodeById(getContext().getSceneGraph(), SceneGraphConstants.NAVIGATION_NODE_PATH);\r
- if (node != null)\r
- // This is not in hintListener, because we don't want to update\r
- // transform if it already came for scenegraph.\r
- node.setTransform(at);\r
- }\r
- }\r
-\r
- public void zoom(double scaleFactor)\r
- {\r
- if (scaleFactor==1.0) return;\r
- AffineTransform diagramToControl = getTransform();\r
- diagramToControl.scale(scaleFactor, scaleFactor);\r
- setTransform(diagramToControl);\r
- }\r
-\r
- public void rotate(Point2D centerPointCanvas, double angle)\r
- {\r
- if (angle==0.0) return; // and modulos too\r
- AffineTransform diagramToControl = getTransform();\r
- diagramToControl.rotate(-angle, centerPointCanvas.getX(), centerPointCanvas.getY());\r
- setTransform(diagramToControl);\r
- }\r
-\r
- public void restoreOrientation(Point2D centerPointCanvas)\r
- {\r
- AffineTransform res = new AffineTransform();\r
- AffineTransform at = getTransform();\r
- double m01 = at.getShearX();\r
- double m11 = at.getScaleY();\r
- double theta = Math.atan2(m01, m11);\r
- at.rotate(-theta, centerPointCanvas.getX(), centerPointCanvas.getY());\r
- res.translate(at.getTranslateX(), at.getTranslateY());\r
- res.scale(at.getScaleX(), at.getScaleY());\r
- setTransform(res);\r
- }\r
-\r
- /**\r
- * Get rotate in radians.\r
- * @return\r
- */\r
- public double getRotate() {\r
- AffineTransform at = getTransform();\r
- double m01 = at.getShearX();\r
- double m11 = at.getScaleY();\r
- return Math.atan2(m01, m11);\r
- }\r
-\r
- /**\r
- * Zoom the view port\r
- * @param scaleFactor amount to zoom\r
- * @param aroundPoint The center point of zoom in diagram coordinates\r
- */\r
- public void zoomAroundDiagramPoint(double scaleFactor, Point2D aroundPoint)\r
- {\r
- AffineTransform diagramToControl = getTransform();\r
- // convert to control point\r
- aroundPoint = diagramToControl.transform(aroundPoint, new Point2D.Double());\r
- zoomAroundControlPoint(scaleFactor, aroundPoint);\r
- }\r
-\r
- /**\r
- * Zoom the view port\r
- * @param scaleFactor amount to zoom\r
- * @param centerPoint the control point to zoom around\r
- */\r
- public void zoomAroundControlPoint(double scaleFactor, Point2D centerPoint)\r
- {\r
- if (scaleFactor==1.0) return;\r
- AffineTransform diagramToControl = getTransform();\r
- try {\r
- Point2D pointBeforeScale = diagramToControl.inverseTransform(centerPoint, new Point2D.Double());\r
- diagramToControl.scale(scaleFactor, scaleFactor);\r
- Point2D pointAfterScale = diagramToControl.inverseTransform(centerPoint, new Point2D.Double());\r
- double _dx = pointAfterScale.getX() - pointBeforeScale.getX();\r
- double _dy = pointAfterScale.getY() - pointBeforeScale.getY();\r
- diagramToControl.translate(_dx, _dy);\r
- } catch (NoninvertibleTransformException e1) {\r
- }\r
- setTransform(diagramToControl);\r
- }\r
-\r
- /**\r
- * Transform the viewport. The transform values are in diagram coordinates\r
- * @param dx\r
- * @param dy\r
- */\r
- public void translateWithCanvasCoordinates(double dx, double dy)\r
- {\r
- AffineTransform controlToDiagram = getTransform();\r
- controlToDiagram.translate(dx, dy);\r
- setTransform(controlToDiagram);\r
- }\r
-\r
- /**\r
- * Transform the viewport. The transform values are in control coordinates\r
- * @param dx\r
- * @param dy\r
- */\r
- public void translateWithControlCoordinates(Point2D offset)\r
- {\r
- if (offset.getX()==0 && offset.getY()==0) return;\r
- AffineTransform at = getInverseTransform();\r
- offset = at.transform(offset, new Point2D.Double());\r
- translateWithCanvasCoordinates(offset.getX()-at.getTranslateX(), offset.getY()-at.getTranslateY());\r
- }\r
-\r
- /**\r
- * Get scale ratio between control and canvas\r
- * @param pt\r
- * @return\r
- */\r
- public Point2D getScale(Point2D pt)\r
- {\r
- AffineTransform at = getTransform();\r
- return GeometryUtils.getScaleXY(at, pt);\r
- }\r
-\r
- /**\r
- * Modifies transform to make canvas area fully visible.\r
- * @param controlArea\r
- * @param diagramArea\r
- * @param margins margins\r
- */\r
- public void fitArea(Rectangle2D controlArea, Rectangle2D diagramArea, Margins margins)\r
- {\r
- AffineTransform fitTx = org.simantics.scenegraph.utils.GeometryUtils.fitArea(controlArea, diagramArea, margins);\r
- //System.out.println("fitArea(" + controlArea + ", " + diagramArea + ", " + margins + "): " + fitTx);\r
- setTransform(fitTx);\r
- }\r
-\r
-}\r
+/*******************************************************************************
+ * 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 static org.simantics.g2d.canvas.Hints.KEY_CANVAS_TRANSFORM;
+
+import java.awt.Graphics2D;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.geom.Path2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+import org.simantics.g2d.canvas.Hints;
+import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant;
+import org.simantics.g2d.canvas.impl.HintReflection.HintListener;
+import org.simantics.g2d.scenegraph.SceneGraphConstants;
+import org.simantics.g2d.utils.GeometryUtils;
+import org.simantics.scenegraph.g2d.IG2DNode;
+import org.simantics.scenegraph.utils.NodeUtil;
+import org.simantics.utils.datastructures.hints.IHintContext.Key;
+import org.simantics.utils.datastructures.hints.IHintObservable;
+import org.simantics.utils.page.MarginUtils.Margins;
+
+/**
+ * This class contains utilities for coordinate conversions between control
+ * and canvas.
+ *
+ * @author Toni Kalajainen
+ * @author J-P Laine
+ * @author Tuukka Lehtonen
+ */
+public class TransformUtil extends AbstractCanvasParticipant {
+
+ /** Set dirty if transform changes */
+ @HintListener(Class=Hints.class, Field="KEY_CANVAS_TRANSFORM")
+ public void transformChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {
+ if (oldValue != null && oldValue.equals(newValue)) return;
+ //System.out.println("TransformUtil: CANVAS TRANSFORM CHANGED TO " + newValue);
+ setDirty();
+ }
+
+ /**
+ * Get viewport rectangle.
+ * Transforms controlRect to area on canvas.
+ *
+ * @param controlRect rectangle on control
+ * @return area on canvas
+ */
+ public Path2D toCanvasArea(Rectangle2D controlRect)
+ {
+ Point2D p[] = toCanvasCorners(controlRect);
+
+ Path2D path = new Path2D.Double();
+ path.moveTo(p[0].getX(), p[0].getY());
+ path.lineTo(p[1].getX(), p[1].getY());
+ path.lineTo(p[2].getX(), p[2].getY());
+ path.lineTo(p[3].getX(), p[3].getY());
+ path.closePath();
+
+ return path;
+ }
+
+ /**
+ * Returns 4 canvas corders in order: top-left, top-right, bottom-right, bottom-left
+ * @param controlRect rectangle on control
+ * @return area on canvas
+ */
+ public Point2D[] toCanvasCorners(Rectangle2D controlRect)
+ {
+ // at·control point = canvas point
+ AffineTransform at = getHint(KEY_CANVAS_TRANSFORM);
+ if (at==null) at = new AffineTransform();
+
+ try {
+ at = at.createInverse();
+ } catch (NoninvertibleTransformException e) {
+ }
+
+ // Get corners
+ Point2D p1 = new Point2D.Double(controlRect.getMinX(), controlRect.getMinY());
+ Point2D p2 = new Point2D.Double(controlRect.getMaxX(), controlRect.getMinY());
+ Point2D p3 = new Point2D.Double(controlRect.getMaxX(), controlRect.getMaxY());
+ Point2D p4 = new Point2D.Double(controlRect.getMinX(), controlRect.getMaxY());
+
+
+ // Convert corners
+ at.transform(p1, p1);
+ at.transform(p2, p2);
+ at.transform(p3, p3);
+ at.transform(p4, p4);
+
+ return new Point2D[] {p1, p2, p3, p4};
+ }
+
+ /**
+ * Converts control rectangle to a rectangle on canvas that contains control rect.
+ * @param controlRect rectangle on control
+ * @return rectangle on canvas that contains control rect
+ */
+ public Rectangle2D toCanvasRect(Rectangle2D controlRect)
+ {
+ AffineTransform at = getHint(KEY_CANVAS_TRANSFORM);
+ if (at==null)
+ return (Rectangle2D) controlRect.clone();
+
+ Path2D path = toCanvasArea(controlRect);
+ return path.getBounds2D();
+ }
+
+ /**
+ * Transforms from canvas coordinate system to canvas coordinate system (also diagram)
+ * @param g2d
+ */
+ public void controlToCanvas(Graphics2D g2d)
+ {
+ AffineTransform at = getHint(KEY_CANVAS_TRANSFORM);
+ if (at==null) return;
+ g2d.transform(at);
+ }
+
+ /**
+ * Transforms coordinate system of g2d from canvas to control
+ * @param g2d
+ */
+ public void canvasToControl(Graphics2D g2d)
+ {
+ AffineTransform at = getHint(KEY_CANVAS_TRANSFORM);
+ if (at==null) return;
+ try {
+ g2d.transform(at.createInverse());
+ } catch (NoninvertibleTransformException e) {
+ }
+ }
+
+ /**
+ * Convert control point to canvas point
+ * @param g2d
+ */
+ public Point2D controlToCanvas(Point2D control, Point2D canvas)
+ {
+ AffineTransform at = getInverseTransform();
+ if (canvas==null) canvas = new Point2D.Double();
+ if (at==null) {
+ canvas.setLocation(control);
+ return canvas;
+ }
+ at.transform(control, canvas);
+ return canvas;
+ }
+
+ /**
+ * Convert canvas point to control
+ * @param g2d
+ */
+ public Point2D canvasToControl(Point2D canvas, Point2D control)
+ {
+ AffineTransform at = getHint(KEY_CANVAS_TRANSFORM);
+ if (control==null) control = new Point2D.Double();
+ if (at==null) {
+ control.setLocation(canvas);
+ return canvas;
+ }
+ at.transform(canvas, control);
+ return control;
+ }
+
+ /**
+ * Convert canvas vector to control vector
+ * @param g2d
+ */
+ public Point2D canvasVectorToControlVector(Point2D canvas, Point2D control)
+ {
+ AffineTransform at = getHint(KEY_CANVAS_TRANSFORM);
+ if (control==null) control = new Point2D.Double();
+ if (at==null) {
+ control.setLocation(canvas);
+ return canvas;
+ }
+ double x = canvas.getX();
+ double y = canvas.getY();
+
+ double m00 = at.getScaleX();
+ double m11 = at.getScaleY();
+ double m01 = at.getShearX();
+ double m10 = at.getShearY();
+
+ control.setLocation(
+ x * m00 + y * m01,
+ x * m10 + y * m11
+ );
+ return control;
+ }
+
+ /**
+ * Convert control vector to canvas vector
+ * @param g2d
+ */
+ public Point2D controlVectorToCanvasVector(Point2D control, Point2D canvas)
+ {
+ AffineTransform at = getInverseTransform();
+ if (canvas==null) canvas = new Point2D.Double();
+ if (at==null) {
+ canvas.setLocation(control);
+ return canvas;
+ }
+ double x = control.getX();
+ double y = control.getY();
+
+ double m00 = at.getScaleX();
+ double m11 = at.getScaleY();
+ double m01 = at.getShearX();
+ double m10 = at.getShearY();
+
+ canvas.setLocation(
+ x * m00 + y * m01,
+ x * m10 + y * m11
+ );
+ return canvas;
+ }
+ /**
+ * Get a transform that converts
+ * diagram coordinates to control coordinates.
+ *
+ * @return transform a clone
+ */
+ public AffineTransform getTransform()
+ {
+ AffineTransform at = getHint(KEY_CANVAS_TRANSFORM);
+ if (at==null) return new AffineTransform();
+ return (AffineTransform) at.clone();
+ }
+
+ /**
+ * Get a transform that converts
+ * diagram vector to control vector.
+ *
+ * @return transform a clone
+ */
+ public AffineTransform getVectorTransform()
+ {
+ AffineTransform at = getHint(KEY_CANVAS_TRANSFORM);
+ if (at==null) return new AffineTransform();
+ double m00 = at.getScaleX();
+ double m11 = at.getScaleY();
+ double m01 = at.getShearX();
+ double m10 = at.getShearY();
+ return new AffineTransform(m00, m10, m01, m11, 0, 0);
+ }
+
+
+ /**
+ * Transforms control coordinates to diagram coordinates.
+ *
+ * @return inverted transform or <code>null</code> if inversion failed
+ */
+ public AffineTransform getInverseTransform()
+ {
+ AffineTransform at = getTransform();
+ if (at==null) return null;
+ try {
+ at = at.createInverse();
+ return at;
+ } catch (NoninvertibleTransformException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Tries to invert the specified {@link AffineTransform}.
+ *
+ * @parameter at the transform to invert
+ * @return inverted transform or <code>null</code> if inversion failed
+ */
+ public AffineTransform getInverseTransform(AffineTransform at)
+ {
+ if (at == null)
+ return null;
+ try {
+ return at.createInverse();
+ } catch (NoninvertibleTransformException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Transforms control vector to diagram vector
+ * @return a clone
+ */
+ public AffineTransform getInverseVectorTransform()
+ {
+ AffineTransform at = getTransform();
+ if (at==null) return null;
+ try {
+ at = at.createInverse();
+ double m00 = at.getScaleX();
+ double m11 = at.getScaleY();
+ double m01 = at.getShearX();
+ double m10 = at.getShearY();
+ return new AffineTransform(m00, m10, m01, m11, 0, 0);
+ } catch (NoninvertibleTransformException e) {
+ return null;
+ }
+ }
+
+
+ public void setTransform(AffineTransform at)
+ {
+ assert(at.getShearX()!=Double.POSITIVE_INFINITY && at.getShearX()!=Double.NEGATIVE_INFINITY);
+ assert(at.getShearY()!=Double.POSITIVE_INFINITY && at.getShearY()!=Double.NEGATIVE_INFINITY);
+ AffineTransform old = getHint(KEY_CANVAS_TRANSFORM);
+ if(at.equals(old) == false) { // Send event only if the transform has really changed
+ setHint(KEY_CANVAS_TRANSFORM, at);
+
+ IG2DNode node = NodeUtil.findNodeById(getContext().getSceneGraph(), SceneGraphConstants.NAVIGATION_NODE_PATH);
+ if (node != null)
+ // This is not in hintListener, because we don't want to update
+ // transform if it already came for scenegraph.
+ node.setTransform(at);
+ }
+ }
+
+ public void zoom(double scaleFactor)
+ {
+ if (scaleFactor==1.0) return;
+ AffineTransform diagramToControl = getTransform();
+ diagramToControl.scale(scaleFactor, scaleFactor);
+ setTransform(diagramToControl);
+ }
+
+ public void rotate(Point2D centerPointCanvas, double angle)
+ {
+ if (angle==0.0) return; // and modulos too
+ AffineTransform diagramToControl = getTransform();
+ diagramToControl.rotate(-angle, centerPointCanvas.getX(), centerPointCanvas.getY());
+ setTransform(diagramToControl);
+ }
+
+ public void restoreOrientation(Point2D centerPointCanvas)
+ {
+ AffineTransform res = new AffineTransform();
+ AffineTransform at = getTransform();
+ double m01 = at.getShearX();
+ double m11 = at.getScaleY();
+ double theta = Math.atan2(m01, m11);
+ at.rotate(-theta, centerPointCanvas.getX(), centerPointCanvas.getY());
+ res.translate(at.getTranslateX(), at.getTranslateY());
+ res.scale(at.getScaleX(), at.getScaleY());
+ setTransform(res);
+ }
+
+ /**
+ * Get rotate in radians.
+ * @return
+ */
+ public double getRotate() {
+ AffineTransform at = getTransform();
+ double m01 = at.getShearX();
+ double m11 = at.getScaleY();
+ return Math.atan2(m01, m11);
+ }
+
+ /**
+ * Zoom the view port
+ * @param scaleFactor amount to zoom
+ * @param aroundPoint The center point of zoom in diagram coordinates
+ */
+ public void zoomAroundDiagramPoint(double scaleFactor, Point2D aroundPoint)
+ {
+ AffineTransform diagramToControl = getTransform();
+ // convert to control point
+ aroundPoint = diagramToControl.transform(aroundPoint, new Point2D.Double());
+ zoomAroundControlPoint(scaleFactor, aroundPoint);
+ }
+
+ /**
+ * Zoom the view port
+ * @param scaleFactor amount to zoom
+ * @param centerPoint the control point to zoom around
+ */
+ public void zoomAroundControlPoint(double scaleFactor, Point2D centerPoint)
+ {
+ if (scaleFactor==1.0) return;
+ AffineTransform diagramToControl = getTransform();
+ try {
+ Point2D pointBeforeScale = diagramToControl.inverseTransform(centerPoint, new Point2D.Double());
+ diagramToControl.scale(scaleFactor, scaleFactor);
+ Point2D pointAfterScale = diagramToControl.inverseTransform(centerPoint, new Point2D.Double());
+ double _dx = pointAfterScale.getX() - pointBeforeScale.getX();
+ double _dy = pointAfterScale.getY() - pointBeforeScale.getY();
+ diagramToControl.translate(_dx, _dy);
+ } catch (NoninvertibleTransformException e1) {
+ }
+ setTransform(diagramToControl);
+ }
+
+ /**
+ * Transform the viewport. The transform values are in diagram coordinates
+ * @param dx
+ * @param dy
+ */
+ public void translateWithCanvasCoordinates(double dx, double dy)
+ {
+ AffineTransform controlToDiagram = getTransform();
+ controlToDiagram.translate(dx, dy);
+ setTransform(controlToDiagram);
+ }
+
+ /**
+ * Transform the viewport. The transform values are in control coordinates
+ * @param dx
+ * @param dy
+ */
+ public void translateWithControlCoordinates(Point2D offset)
+ {
+ if (offset.getX()==0 && offset.getY()==0) return;
+ AffineTransform at = getInverseTransform();
+ offset = at.transform(offset, new Point2D.Double());
+ translateWithCanvasCoordinates(offset.getX()-at.getTranslateX(), offset.getY()-at.getTranslateY());
+ }
+
+ /**
+ * Get scale ratio between control and canvas
+ * @param pt
+ * @return
+ */
+ public Point2D getScale(Point2D pt)
+ {
+ AffineTransform at = getTransform();
+ return GeometryUtils.getScaleXY(at, pt);
+ }
+
+ /**
+ * Modifies transform to make canvas area fully visible.
+ * @param controlArea
+ * @param diagramArea
+ * @param margins margins
+ */
+ public void fitArea(Rectangle2D controlArea, Rectangle2D diagramArea, Margins margins)
+ {
+ AffineTransform fitTx = org.simantics.scenegraph.utils.GeometryUtils.fitArea(controlArea, diagramArea, margins);
+ //System.out.println("fitArea(" + controlArea + ", " + diagramArea + ", " + margins + "): " + fitTx);
+ setTransform(fitTx);
+ }
+
+}