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