]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.g2d.elementclass.connection;
13
14 import java.awt.Shape;
15 import java.awt.geom.AffineTransform;
16 import java.awt.geom.Path2D;
17 import java.awt.geom.Point2D;
18 import java.awt.geom.Rectangle2D;
19 import java.util.ArrayList;
20 import java.util.List;
21
22 import org.simantics.g2d.diagram.IDiagram;
23 import org.simantics.g2d.element.ElementClass;
24 import org.simantics.g2d.element.ElementHints;
25 import org.simantics.g2d.element.IElement;
26 import org.simantics.g2d.element.handler.BendsHandler;
27 import org.simantics.g2d.element.handler.InternalSize;
28 import org.simantics.g2d.element.handler.LifeCycle;
29 import org.simantics.g2d.element.handler.Move;
30 import org.simantics.g2d.element.handler.Outline;
31 import org.simantics.g2d.element.handler.Parent;
32 import org.simantics.g2d.element.handler.Transform;
33 import org.simantics.g2d.element.handler.impl.ConfigurableEdgeVisuals;
34 import org.simantics.g2d.element.handler.impl.ConnectionSelectionOutline;
35 import org.simantics.g2d.element.handler.impl.FillColorImpl;
36 import org.simantics.g2d.element.handler.impl.ParentImpl;
37 import org.simantics.g2d.element.handler.impl.ShapePick;
38 import org.simantics.g2d.element.handler.impl.SimpleElementLayers;
39 import org.simantics.g2d.elementclass.PlainElementPropertySetter;
40 import org.simantics.utils.datastructures.hints.IHintContext.Key;
41 import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;
42
43 /**
44  * @author Toni Kalajainen
45  */
46 public class EdgeClass {
47
48     /**
49      * A {@link Transform} and {@link Move} implementation suitable for edges
50      * which are connected to nodes and cannot be moved by themselves.
51      * 
52      * <p>
53      * The {@link Transform} implementation is a simple one with support for a
54      * parent element through {@link ElementHints#KEY_PARENT_ELEMENT}. The
55      * {@link Move} implementation in turn is a stub which does nothing to make
56      * edges immovable.
57      * 
58      * <p>
59      * FIXME: The more correct solution would be not to have a {@link Move}
60      * handler at all but much the current participant code is very highly
61      * dependent on having a single {@link Move} handler available that this
62      * workaround seems better at this point.
63      * 
64      * @author Tuukka Lehtonen
65      */
66     public static class FixedTransform implements Transform, Move {
67
68         private static final long serialVersionUID = 2287402413442694915L;
69
70         public static final FixedTransform INSTANCE = new FixedTransform();
71         public static final AffineTransform IDENTITY = new AffineTransform();
72
73         @Override
74         public AffineTransform getTransform(IElement e) {
75             AffineTransform local = e.getHint(ElementHints.KEY_TRANSFORM);
76             if (local == null)
77                 local = IDENTITY;
78
79             Parent p = e.getElementClass().getAtMostOneItemOfClass(Parent.class);
80             if (p == null)
81                 return local;
82
83             IElement parentElement = p.getParent(e);
84             if (parentElement == null)
85                 return local;
86
87             AffineTransform parentTransform = parentElement.getElementClass().getSingleItem(Transform.class).getTransform(parentElement);
88             if (parentTransform.isIdentity())
89                 return local;
90
91             AffineTransform result = new AffineTransform(local);
92             result.preConcatenate(parentTransform);
93             return result;
94         }
95
96         @Override
97         public void setTransform(IElement e, AffineTransform at) {
98             assert at != null;
99             e.setHint(ElementHints.KEY_TRANSFORM, at);
100         }
101
102         @Override
103         public Point2D getPosition(IElement e) {
104             AffineTransform at = e.getHint(ElementHints.KEY_TRANSFORM);
105             if (at == null)
106                 return new Point2D.Double();
107             return new Point2D.Double(at.getTranslateX(), at.getTranslateY());
108         }
109
110         @Override
111         public void moveTo(IElement e, double x, double y) {
112             // Don't allow moving.
113         }
114     }
115
116     // TODO scale, rotate, move, transform
117     public static final ElementClass STRAIGHT =
118         ElementClass.compile(
119                 EdgeSceneGraph.INSTANCE,
120                 EdgeHandler.INSTANCE,
121                 ConfigurableEdgeVisuals.DEFAULT,
122                 FillColorImpl.RED,
123                 FixedTransform.INSTANCE,
124                 ShapePick.INSTANCE,
125                 ConnectionSelectionOutline.INSTANCE,
126                 SimpleElementLayers.INSTANCE,
127                 ParentImpl.INSTANCE,
128                 new PlainElementPropertySetter(EdgeSceneGraph.KEY_SG_NODE)
129         ).setId("EdgeClass.STRAIGHT");
130
131
132     public static class EdgeHandler implements BendsHandler, Outline, LifeCycle, InternalSize {
133
134         private static final long serialVersionUID = -5949432471958957382L;
135
136         public static final EdgeHandler INSTANCE = new EdgeHandler();
137
138         public static final Key KEY_PATH = new KeyOf(Path2D.class, "PATH");
139         public static final Key KEY_BOUNDS = new KeyOf(Rectangle2D.class, "BOUNDS");
140         public static final Key KEY_ANGLETYPE = new KeyOf(AngleType.class);
141         public static final Key KEY_BENDS = new KeyOf(ArrayList.class, "BENDS");
142
143         public static class BendImpl implements Bend {
144             Point2D pos;
145         }
146
147         /**
148          * Reads bends, builds path, and writes it to KEY_PATH
149          * @param e
150          */
151         /*
152                 private void buildPath(IElement e)
153                 {
154                         ArrayList<Point2D> points = new ArrayList<Point2D>();
155                         ElementUtils.getBends(e, points);
156                         Path2D path = GeometryUtils.buildPath(points);
157                         e.setHint(KEY_PATH, path);
158                         e.setHint(KEY_BOUNDS, path.getBounds2D());
159                 }*/
160
161         @Override
162         public void setAngleType(IElement e, AngleType angleType) {
163             e.setHint(KEY_ANGLETYPE, angleType);
164         }
165
166         @Override
167         public AngleType getAngleType(IElement e) {
168             return e.getHint(KEY_ANGLETYPE);
169         }
170
171         @Override
172         public Shape getElementShape(IElement e) {
173             // Path2DOutlineShape no longer needed with ConnectionSelectionOutline
174             // that uses Stroke.createStrokedShape.
175             //return new Path2DOutlineShape((Path2D)e.getHint(KEY_PATH));
176             return e.getHint(KEY_PATH);
177         }
178 /*
179                 @Override
180                 public AffineTransform getTransform(IElement e) {
181                         AffineTransform at = GeometryUtils.IDENTITY;
182                         assert(at.isIdentity());
183                         return at;
184                 }
185
186                 @Override
187                 public void setTransform(IElement e, AffineTransform at) {
188                         Path2D path = e.getHint(KEY_PATH);
189                         if (path==null) return;
190                         ArrayList<BendImpl> list = e.getHint(KEY_BENDS);
191                         for (BendImpl bi : list)
192                                 at.transform(bi.pos, bi.pos);
193                         buildPath(e);
194                 }
195
196                 @Override
197                 public Point2D getPosition(IElement e) {
198                         return new Point2D.Double(0, 0);
199                 }
200
201                 @Override
202                 public void moveTo(IElement e, double x, double y) {
203                         AffineTransform at = new AffineTransform();
204                         at.setToTranslation(x, y);
205                         setTransform(e, at);
206                 }
207
208                 @Override
209                 public double getAngle(IElement e, ICanvasContext ctx) {
210                         return 0;
211                 }
212
213                 @Override
214                 public void rotate(IElement e, ICanvasContext ctx, double theta, Point2D origo) {
215                         AffineTransform at = new AffineTransform();
216                         at.setToRotation(theta, origo.getX(), origo.getY());
217                         setTransform(e, at);
218                 }
219
220                 @Override
221                 public Double getFixedAspectRatio(IElement e) {
222                         return null;
223                 }
224
225                 @Override
226                 public Point2D getMaximumScale(IElement e) {
227                         return null;
228                 }
229
230                 @Override
231                 public Point2D getMinimumScale(IElement e) {
232                         return null;
233                 }
234
235                 @Override
236                 public Point2D getScale(IElement e) {
237                         return new Point2D.Double(1, 1);
238                 }
239
240                 @Override
241                 public void setScale(IElement e, Point2D newScale) {
242                         AffineTransform at = new AffineTransform();
243                         at.setToScale(newScale.getX(), newScale.getY());
244                         setTransform(e, at);
245                 }
246  */
247         @Override
248         public void onElementActivated(IDiagram d, IElement e) {
249             update(e);
250         }
251
252         @Override
253         public void onElementCreated(IElement e) {
254             e.setHint(KEY_PATH, new Path2D.Double(Path2D.WIND_NON_ZERO, 2));
255             e.setHint(KEY_ANGLETYPE, AngleType.RightAngled);
256             e.setHint(KEY_BOUNDS, new Rectangle2D.Double());
257             e.setHint(KEY_BENDS, new ArrayList<BendImpl>(2));
258         }
259         @Override
260         public void onElementDestroyed(IElement e) {
261 //                      EdgeSGNode sg = e.getElementClass().getAtMostOneItemOfClass(EdgeSGNode.class);
262 //                      if(sg != null)
263 //                              sg.cleanup(e);
264         }
265
266         private void update(IElement e) {
267             EdgeSceneGraph sg = e.getElementClass().getAtMostOneItemOfClass(EdgeSceneGraph.class);
268             if(sg != null)
269                 sg.update(e);
270         }
271
272         @Override
273         public void onElementDeactivated(IDiagram d, IElement e) {
274         }
275
276         @Override
277         public Rectangle2D getBounds(IElement e, Rectangle2D size) {
278             Rectangle2D rect = e.getHint(KEY_BOUNDS);
279             if (size==null) size = new Rectangle2D.Double();
280             if (rect != null)
281                 size.setFrame(rect);
282             return rect;
283         }
284
285         @Override
286         public Bend addBend(IElement e, int index, Point2D pos) {
287             ArrayList<BendImpl> list = e.getHint(KEY_BENDS);
288             BendImpl b = new BendImpl();
289             b.pos = new Point2D.Double(pos.getX(), pos.getY());
290             list.add(index, b);
291 //                      buildPath(e);
292             update(e);
293             return b;
294         }
295
296         @Override
297         public void getBendPosition(IElement e, Bend b, Point2D pos) {
298             pos.setLocation( ((BendImpl)b).pos );
299         }
300
301         @Override
302         public int getBendsCount(IElement e) {
303             ArrayList<BendImpl> list = e.getHint(KEY_BENDS);
304             return list.size();
305         }
306
307         @Override
308         public void getBends(IElement e, List<Bend> bends) {
309             ArrayList<BendImpl> list = e.getHint(KEY_BENDS);
310             bends.addAll(list);
311         }
312
313         @Override
314         public boolean removeBend(IElement e, Bend b) {
315             ArrayList<BendImpl> list = e.getHint(KEY_BENDS);
316             if (!list.remove(b)) return false;
317 //                      buildPath(e);
318             return true;
319         }
320
321         @Override
322         public Path2D getPath(IElement e) {
323             return e.getHint(KEY_PATH);
324         }
325
326         @Override
327         public void setPath(IElement e, Path2D path) {
328             e.setHint(KEY_PATH, path);
329             e.setHint(KEY_BOUNDS, path.getBounds2D());
330             /*
331                         ArrayList<BendImpl> list = e.getHint(KEY_BENDS);
332                         ArrayList<Point2D> positions = new ArrayList<Point2D>();
333                         GeometryUtils.getPoints(path, positions);
334                         list.clear();
335                         for (Point2D p : positions) {
336                                 BendImpl bi = new BendImpl();
337                                 bi.pos = p;
338                                 list.add(bi);
339                         }*/
340             update(e);
341         }
342
343         @Override
344         public void moveBend(IElement e, Bend b, Point2D pos) {
345             BendImpl bi = ((BendImpl)b);
346             if (bi.pos.equals(pos)) return;
347             bi.pos.setLocation(pos);
348 //                      buildPath(e);
349             update(e);
350         }
351     }
352
353     public static class ControlPointKey extends Key {
354         public final int index;
355         final int hash;
356         public ControlPointKey(int index)
357         {
358             super();
359             this.index = index;
360             hash = getClass().hashCode() ^ index ^ 54392439;
361         }
362         @Override
363         public boolean isValueAccepted(Object value) {
364             return IElement.class.isInstance(value);
365         }
366         @Override
367         public int hashCode() {
368             return hash;
369         }
370         @Override
371         public boolean equals(Object obj) {
372             if (obj == null)
373                 return false;
374             if (getClass() != obj.getClass())
375                 return false;
376             ControlPointKey other = (ControlPointKey) obj;
377             return other.index == index;
378         }
379     }
380
381 }