]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.g2d/src/org/simantics/g2d/elementclass/connection/EdgeClass.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / elementclass / connection / EdgeClass.java
diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/elementclass/connection/EdgeClass.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/elementclass/connection/EdgeClass.java
new file mode 100644 (file)
index 0000000..2a8dc18
--- /dev/null
@@ -0,0 +1,381 @@
+/*******************************************************************************\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.elementclass.connection;\r
+\r
+import java.awt.Shape;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.Path2D;\r
+import java.awt.geom.Point2D;\r
+import java.awt.geom.Rectangle2D;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.element.ElementClass;\r
+import org.simantics.g2d.element.ElementHints;\r
+import org.simantics.g2d.element.IElement;\r
+import org.simantics.g2d.element.handler.BendsHandler;\r
+import org.simantics.g2d.element.handler.InternalSize;\r
+import org.simantics.g2d.element.handler.LifeCycle;\r
+import org.simantics.g2d.element.handler.Move;\r
+import org.simantics.g2d.element.handler.Outline;\r
+import org.simantics.g2d.element.handler.Parent;\r
+import org.simantics.g2d.element.handler.Transform;\r
+import org.simantics.g2d.element.handler.impl.ConfigurableEdgeVisuals;\r
+import org.simantics.g2d.element.handler.impl.ConnectionSelectionOutline;\r
+import org.simantics.g2d.element.handler.impl.FillColorImpl;\r
+import org.simantics.g2d.element.handler.impl.ParentImpl;\r
+import org.simantics.g2d.element.handler.impl.ShapePick;\r
+import org.simantics.g2d.element.handler.impl.SimpleElementLayers;\r
+import org.simantics.g2d.elementclass.PlainElementPropertySetter;\r
+import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
+import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;\r
+\r
+/**\r
+ * @author Toni Kalajainen\r
+ */\r
+public class EdgeClass {\r
+\r
+    /**\r
+     * A {@link Transform} and {@link Move} implementation suitable for edges\r
+     * which are connected to nodes and cannot be moved by themselves.\r
+     * \r
+     * <p>\r
+     * The {@link Transform} implementation is a simple one with support for a\r
+     * parent element through {@link ElementHints#KEY_PARENT_ELEMENT}. The\r
+     * {@link Move} implementation in turn is a stub which does nothing to make\r
+     * edges immovable.\r
+     * \r
+     * <p>\r
+     * FIXME: The more correct solution would be not to have a {@link Move}\r
+     * handler at all but much the current participant code is very highly\r
+     * dependent on having a single {@link Move} handler available that this\r
+     * workaround seems better at this point.\r
+     * \r
+     * @author Tuukka Lehtonen\r
+     */\r
+    public static class FixedTransform implements Transform, Move {\r
+\r
+        private static final long serialVersionUID = 2287402413442694915L;\r
+\r
+        public static final FixedTransform INSTANCE = new FixedTransform();\r
+        public static final AffineTransform IDENTITY = new AffineTransform();\r
+\r
+        @Override\r
+        public AffineTransform getTransform(IElement e) {\r
+            AffineTransform local = e.getHint(ElementHints.KEY_TRANSFORM);\r
+            if (local == null)\r
+                local = IDENTITY;\r
+\r
+            Parent p = e.getElementClass().getAtMostOneItemOfClass(Parent.class);\r
+            if (p == null)\r
+                return local;\r
+\r
+            IElement parentElement = p.getParent(e);\r
+            if (parentElement == null)\r
+                return local;\r
+\r
+            AffineTransform parentTransform = parentElement.getElementClass().getSingleItem(Transform.class).getTransform(parentElement);\r
+            if (parentTransform.isIdentity())\r
+                return local;\r
+\r
+            AffineTransform result = new AffineTransform(local);\r
+            result.preConcatenate(parentTransform);\r
+            return result;\r
+        }\r
+\r
+        @Override\r
+        public void setTransform(IElement e, AffineTransform at) {\r
+            assert at != null;\r
+            e.setHint(ElementHints.KEY_TRANSFORM, at);\r
+        }\r
+\r
+        @Override\r
+        public Point2D getPosition(IElement e) {\r
+            AffineTransform at = e.getHint(ElementHints.KEY_TRANSFORM);\r
+            if (at == null)\r
+                return new Point2D.Double();\r
+            return new Point2D.Double(at.getTranslateX(), at.getTranslateY());\r
+        }\r
+\r
+        @Override\r
+        public void moveTo(IElement e, double x, double y) {\r
+            // Don't allow moving.\r
+        }\r
+    }\r
+\r
+    // TODO scale, rotate, move, transform\r
+    public static final ElementClass STRAIGHT =\r
+        ElementClass.compile(\r
+                EdgeSceneGraph.INSTANCE,\r
+                EdgeHandler.INSTANCE,\r
+                ConfigurableEdgeVisuals.DEFAULT,\r
+                FillColorImpl.RED,\r
+                FixedTransform.INSTANCE,\r
+                ShapePick.INSTANCE,\r
+                ConnectionSelectionOutline.INSTANCE,\r
+                SimpleElementLayers.INSTANCE,\r
+                ParentImpl.INSTANCE,\r
+                new PlainElementPropertySetter(EdgeSceneGraph.KEY_SG_NODE)\r
+        ).setId("EdgeClass.STRAIGHT");\r
+\r
+\r
+    public static class EdgeHandler implements BendsHandler, Outline, LifeCycle, InternalSize {\r
+\r
+        private static final long serialVersionUID = -5949432471958957382L;\r
+\r
+        public static final EdgeHandler INSTANCE = new EdgeHandler();\r
+\r
+        public static final Key KEY_PATH = new KeyOf(Path2D.class, "PATH");\r
+        public static final Key KEY_BOUNDS = new KeyOf(Rectangle2D.class, "BOUNDS");\r
+        public static final Key KEY_ANGLETYPE = new KeyOf(AngleType.class);\r
+        public static final Key KEY_BENDS = new KeyOf(ArrayList.class, "BENDS");\r
+\r
+        public static class BendImpl implements Bend {\r
+            Point2D pos;\r
+        }\r
+\r
+        /**\r
+         * Reads bends, builds path, and writes it to KEY_PATH\r
+         * @param e\r
+         */\r
+        /*\r
+               private void buildPath(IElement e)\r
+               {\r
+                       ArrayList<Point2D> points = new ArrayList<Point2D>();\r
+                       ElementUtils.getBends(e, points);\r
+                       Path2D path = GeometryUtils.buildPath(points);\r
+                       e.setHint(KEY_PATH, path);\r
+                       e.setHint(KEY_BOUNDS, path.getBounds2D());\r
+               }*/\r
+\r
+        @Override\r
+        public void setAngleType(IElement e, AngleType angleType) {\r
+            e.setHint(KEY_ANGLETYPE, angleType);\r
+        }\r
+\r
+        @Override\r
+        public AngleType getAngleType(IElement e) {\r
+            return e.getHint(KEY_ANGLETYPE);\r
+        }\r
+\r
+        @Override\r
+        public Shape getElementShape(IElement e) {\r
+            // Path2DOutlineShape no longer needed with ConnectionSelectionOutline\r
+            // that uses Stroke.createStrokedShape.\r
+            //return new Path2DOutlineShape((Path2D)e.getHint(KEY_PATH));\r
+            return e.getHint(KEY_PATH);\r
+        }\r
+/*\r
+               @Override\r
+               public AffineTransform getTransform(IElement e) {\r
+                       AffineTransform at = GeometryUtils.IDENTITY;\r
+                       assert(at.isIdentity());\r
+                       return at;\r
+               }\r
+\r
+               @Override\r
+               public void setTransform(IElement e, AffineTransform at) {\r
+                       Path2D path = e.getHint(KEY_PATH);\r
+                       if (path==null) return;\r
+                       ArrayList<BendImpl> list = e.getHint(KEY_BENDS);\r
+                       for (BendImpl bi : list)\r
+                               at.transform(bi.pos, bi.pos);\r
+                       buildPath(e);\r
+               }\r
+\r
+               @Override\r
+               public Point2D getPosition(IElement e) {\r
+                       return new Point2D.Double(0, 0);\r
+               }\r
+\r
+               @Override\r
+               public void moveTo(IElement e, double x, double y) {\r
+                       AffineTransform at = new AffineTransform();\r
+                       at.setToTranslation(x, y);\r
+                       setTransform(e, at);\r
+               }\r
+\r
+               @Override\r
+               public double getAngle(IElement e, ICanvasContext ctx) {\r
+                       return 0;\r
+               }\r
+\r
+               @Override\r
+               public void rotate(IElement e, ICanvasContext ctx, double theta, Point2D origo) {\r
+                       AffineTransform at = new AffineTransform();\r
+                       at.setToRotation(theta, origo.getX(), origo.getY());\r
+                       setTransform(e, at);\r
+               }\r
+\r
+               @Override\r
+               public Double getFixedAspectRatio(IElement e) {\r
+                       return null;\r
+               }\r
+\r
+               @Override\r
+               public Point2D getMaximumScale(IElement e) {\r
+                       return null;\r
+               }\r
+\r
+               @Override\r
+               public Point2D getMinimumScale(IElement e) {\r
+                       return null;\r
+               }\r
+\r
+               @Override\r
+               public Point2D getScale(IElement e) {\r
+                       return new Point2D.Double(1, 1);\r
+               }\r
+\r
+               @Override\r
+               public void setScale(IElement e, Point2D newScale) {\r
+                       AffineTransform at = new AffineTransform();\r
+                       at.setToScale(newScale.getX(), newScale.getY());\r
+                       setTransform(e, at);\r
+               }\r
+ */\r
+        @Override\r
+        public void onElementActivated(IDiagram d, IElement e) {\r
+            update(e);\r
+        }\r
+\r
+        @Override\r
+        public void onElementCreated(IElement e) {\r
+            e.setHint(KEY_PATH, new Path2D.Double(Path2D.WIND_NON_ZERO, 2));\r
+            e.setHint(KEY_ANGLETYPE, AngleType.RightAngled);\r
+            e.setHint(KEY_BOUNDS, new Rectangle2D.Double());\r
+            e.setHint(KEY_BENDS, new ArrayList<BendImpl>(2));\r
+        }\r
+        @Override\r
+        public void onElementDestroyed(IElement e) {\r
+//                     EdgeSGNode sg = e.getElementClass().getAtMostOneItemOfClass(EdgeSGNode.class);\r
+//                     if(sg != null)\r
+//                             sg.cleanup(e);\r
+        }\r
+\r
+        private void update(IElement e) {\r
+            EdgeSceneGraph sg = e.getElementClass().getAtMostOneItemOfClass(EdgeSceneGraph.class);\r
+            if(sg != null)\r
+                sg.update(e);\r
+        }\r
+\r
+        @Override\r
+        public void onElementDeactivated(IDiagram d, IElement e) {\r
+        }\r
+\r
+        @Override\r
+        public Rectangle2D getBounds(IElement e, Rectangle2D size) {\r
+            Rectangle2D rect = e.getHint(KEY_BOUNDS);\r
+            if (size==null) size = new Rectangle2D.Double();\r
+            if (rect != null)\r
+                size.setFrame(rect);\r
+            return rect;\r
+        }\r
+\r
+        @Override\r
+        public Bend addBend(IElement e, int index, Point2D pos) {\r
+            ArrayList<BendImpl> list = e.getHint(KEY_BENDS);\r
+            BendImpl b = new BendImpl();\r
+            b.pos = new Point2D.Double(pos.getX(), pos.getY());\r
+            list.add(index, b);\r
+//                     buildPath(e);\r
+            update(e);\r
+            return b;\r
+        }\r
+\r
+        @Override\r
+        public void getBendPosition(IElement e, Bend b, Point2D pos) {\r
+            pos.setLocation( ((BendImpl)b).pos );\r
+        }\r
+\r
+        @Override\r
+        public int getBendsCount(IElement e) {\r
+            ArrayList<BendImpl> list = e.getHint(KEY_BENDS);\r
+            return list.size();\r
+        }\r
+\r
+        @Override\r
+        public void getBends(IElement e, List<Bend> bends) {\r
+            ArrayList<BendImpl> list = e.getHint(KEY_BENDS);\r
+            bends.addAll(list);\r
+        }\r
+\r
+        @Override\r
+        public boolean removeBend(IElement e, Bend b) {\r
+            ArrayList<BendImpl> list = e.getHint(KEY_BENDS);\r
+            if (!list.remove(b)) return false;\r
+//                     buildPath(e);\r
+            return true;\r
+        }\r
+\r
+        @Override\r
+        public Path2D getPath(IElement e) {\r
+            return e.getHint(KEY_PATH);\r
+        }\r
+\r
+        @Override\r
+        public void setPath(IElement e, Path2D path) {\r
+            e.setHint(KEY_PATH, path);\r
+            e.setHint(KEY_BOUNDS, path.getBounds2D());\r
+            /*\r
+                       ArrayList<BendImpl> list = e.getHint(KEY_BENDS);\r
+                       ArrayList<Point2D> positions = new ArrayList<Point2D>();\r
+                       GeometryUtils.getPoints(path, positions);\r
+                       list.clear();\r
+                       for (Point2D p : positions) {\r
+                               BendImpl bi = new BendImpl();\r
+                               bi.pos = p;\r
+                               list.add(bi);\r
+                       }*/\r
+            update(e);\r
+        }\r
+\r
+        @Override\r
+        public void moveBend(IElement e, Bend b, Point2D pos) {\r
+            BendImpl bi = ((BendImpl)b);\r
+            if (bi.pos.equals(pos)) return;\r
+            bi.pos.setLocation(pos);\r
+//                     buildPath(e);\r
+            update(e);\r
+        }\r
+    }\r
+\r
+    public static class ControlPointKey extends Key {\r
+        public final int index;\r
+        final int hash;\r
+        public ControlPointKey(int index)\r
+        {\r
+            super();\r
+            this.index = index;\r
+            hash = getClass().hashCode() ^ index ^ 54392439;\r
+        }\r
+        @Override\r
+        public boolean isValueAccepted(Object value) {\r
+            return IElement.class.isInstance(value);\r
+        }\r
+        @Override\r
+        public int hashCode() {\r
+            return hash;\r
+        }\r
+        @Override\r
+        public boolean equals(Object obj) {\r
+            if (obj == null)\r
+                return false;\r
+            if (getClass() != obj.getClass())\r
+                return false;\r
+            ControlPointKey other = (ControlPointKey) obj;\r
+            return other.index == index;\r
+        }\r
+    }\r
+\r
+}\r