]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/handler/impl/PickContextImpl.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / diagram / handler / impl / PickContextImpl.java
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
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.g2d.diagram.handler.impl;\r
13 \r
14 import java.awt.Shape;\r
15 import java.awt.geom.AffineTransform;\r
16 import java.awt.geom.NoninvertibleTransformException;\r
17 import java.awt.geom.Rectangle2D;\r
18 import java.util.ArrayList;\r
19 import java.util.Collection;\r
20 import java.util.List;\r
21 \r
22 import org.simantics.g2d.diagram.DiagramHints;\r
23 import org.simantics.g2d.diagram.IDiagram;\r
24 import org.simantics.g2d.diagram.handler.PickContext;\r
25 import org.simantics.g2d.diagram.handler.PickRequest;\r
26 import org.simantics.g2d.diagram.handler.PickRequest.PickPolicy;\r
27 import org.simantics.g2d.element.ElementClass;\r
28 import org.simantics.g2d.element.ElementUtils;\r
29 import org.simantics.g2d.element.IElement;\r
30 import org.simantics.g2d.element.handler.ElementLayers;\r
31 import org.simantics.g2d.element.handler.InternalSize;\r
32 import org.simantics.g2d.element.handler.Outline;\r
33 import org.simantics.g2d.element.handler.Pick;\r
34 import org.simantics.g2d.element.handler.Pick2;\r
35 import org.simantics.g2d.element.handler.Transform;\r
36 import org.simantics.g2d.layers.ILayers;\r
37 import org.simantics.g2d.utils.GeometryUtils;\r
38 \r
39 /**\r
40  * @author Toni Kalajainen\r
41  */\r
42 public class PickContextImpl implements PickContext {\r
43 \r
44         public static final PickContextImpl INSTANCE = new PickContextImpl(); \r
45 \r
46         @Override\r
47         public void pick(\r
48                         IDiagram diagram, \r
49                         PickRequest request, \r
50                         Collection<IElement> finalResult) \r
51         {\r
52                 assert(diagram!=null);\r
53                 assert(request!=null);\r
54                 assert(finalResult!=null);\r
55 \r
56                 ILayers layers = diagram.getHint(DiagramHints.KEY_LAYERS);\r
57 \r
58                 Collection<IElement> result = finalResult;\r
59                 if (request.pickSorter != null) {\r
60                         // Need a temporary List<IElement> for PickSorter\r
61                         result = new ArrayList<IElement>();\r
62                 }\r
63                 Rectangle2D elementBounds = new Rectangle2D.Double();\r
64                 nextElement:\r
65                 for (IElement e : diagram.getSnapshot())\r
66                 {\r
67                         // Ignore hidden elements.\r
68                         if (ElementUtils.isHidden(e))\r
69                                 continue;\r
70 \r
71                         ElementClass ec = e.getElementClass();\r
72                         \r
73                         if(layers != null && !layers.getIgnoreFocusSettings()) {\r
74                                 ElementLayers el = ec.getAtMostOneItemOfClass(ElementLayers.class);\r
75                                 if(el != null) {\r
76                                         if(!el.isFocusable(e, layers)) continue;\r
77                                 }\r
78                         }\r
79                         \r
80                         if (request.pickFilter!=null && !request.pickFilter.accept(e)) continue;\r
81                         \r
82                         Transform t = e.getElementClass().getSingleItem(Transform.class);\r
83                         AffineTransform canvasToElement = t.getTransform(e);\r
84                         if (canvasToElement==null) continue;\r
85                         double det = canvasToElement.getDeterminant();\r
86                         if (det == 0) {\r
87                                 // Singular transform, just reset the rotation/scaling part to\r
88                                 // allow picking to proceed.\r
89                                 // TODO: this may modify the internal transform value of an element which is not intended\r
90                                 canvasToElement.setToTranslation(\r
91                                                 canvasToElement.getTranslateX(),\r
92                                                 canvasToElement.getTranslateY());\r
93                         }\r
94 \r
95                         // Get bounds, ignore elements that have no bounds\r
96                         InternalSize b = e.getElementClass().getAtMostOneItemOfClass(InternalSize.class);\r
97                         if (b==null) continue;\r
98                         elementBounds.setFrame(Double.NaN, Double.NaN, Double.NaN, Double.NaN);\r
99                         b.getBounds(e, elementBounds);\r
100                         if (Double.isNaN(elementBounds.getWidth()) || Double.isNaN(elementBounds.getHeight()))\r
101                                 continue;\r
102 \r
103                         Shape elementBoundsOnCanvas = GeometryUtils.transformShape(elementBounds, canvasToElement);\r
104                         if (elementBoundsOnCanvas instanceof Rectangle2D)\r
105                                 elementBoundsOnCanvas = elementBoundsOnCanvas.getBounds2D();\r
106                         elementBoundsOnCanvas = elementBoundsOnCanvas.getBounds2D();\r
107                         org.simantics.scenegraph.utils.GeometryUtils.expandRectangle((Rectangle2D)elementBoundsOnCanvas, 1e-3, 1e-3, 1e-3, 1e-3);\r
108                         \r
109                         // Pick with pick handler(s)\r
110                         List<Pick> pickHandlers = e.getElementClass().getItemsByClass(Pick.class);\r
111                         if (!pickHandlers.isEmpty())\r
112                         {\r
113                             // Rough filtering with bounds\r
114                                 if (!GeometryUtils.intersects(request.pickArea, elementBoundsOnCanvas)) {\r
115 //                                      System.out.println("Element bounds discards " + e.getElementClass());\r
116                                         continue;\r
117                                 }\r
118                                 \r
119                                 // Convert pick shape to element coordinates\r
120 //                              AffineTransform elementToCanvas;\r
121 //                              try {\r
122 //                                      elementToCanvas = canvasToElement.createInverse();\r
123 //                              } catch (NoninvertibleTransformException e1) {\r
124 //                                      throw new RuntimeException(e1);\r
125 //                              }\r
126 //                              Shape pickShapeInElementCoords = GeometryUtils.transformShape(request.pickArea, elementToCanvas);\r
127                                 for (Pick p : pickHandlers)\r
128                                 {\r
129                                         if (p instanceof Pick2) {\r
130                                                 Pick2 p2 = (Pick2) p;\r
131                                                 //if (p2.pick(e, pickShapeInElementCoords, request.pickPolicy, result) > 0)\r
132                                                 if (p2.pick(e, request.pickArea, request.pickPolicy, result) > 0)\r
133                                                         continue nextElement;\r
134                                         } else {\r
135                                                 //if (p.pickTest(e, pickShapeInElementCoords, request.pickPolicy)) {\r
136                                                 if (p.pickTest(e, request.pickArea, request.pickPolicy)) {\r
137                                                         result.add(e);\r
138                                                         continue nextElement;\r
139                                                 }\r
140                                         }\r
141                                 }\r
142                                 continue nextElement;\r
143                         }\r
144                         \r
145                         // Pick with shape handler(s) \r
146                         List<Outline> shapeHandlers = e.getElementClass().getItemsByClass(Outline.class);\r
147                         if (!shapeHandlers.isEmpty())\r
148                         {\r
149                                 // Rough filtering with bounds\r
150                                 if (!GeometryUtils.intersects(request.pickArea, elementBoundsOnCanvas)) continue;\r
151                                 \r
152                                 // Convert pick shape to element coordinates\r
153                                 AffineTransform elementToCanvas;\r
154                                 try {\r
155                                         elementToCanvas = canvasToElement.createInverse();\r
156                                 } catch (NoninvertibleTransformException e1) {\r
157                                         throw new RuntimeException(e1);\r
158                                 }\r
159                                 Shape pickShapeInElementCoords = GeometryUtils.transformShape(request.pickArea, elementToCanvas);\r
160                                 \r
161                                 // Intersection with one shape is enough\r
162                                 if (request.pickPolicy == PickPolicy.PICK_INTERSECTING_OBJECTS)\r
163                                 {\r
164                                         for (Outline es : shapeHandlers)\r
165                                         {\r
166                                                 Shape elementShape = es.getElementShape(e);             \r
167                                                 if (elementShape==null) continue nextElement;\r
168                                                 if (GeometryUtils.intersects(pickShapeInElementCoords, elementShape))\r
169                                                 {\r
170                                                         result.add(e);\r
171                                                         continue nextElement;\r
172                                                 }\r
173                                         }\r
174                                         continue nextElement;\r
175                                 }\r
176                                 \r
177                                 // Contains of all shapes is required \r
178                                 if (request.pickPolicy == PickPolicy.PICK_CONTAINED_OBJECTS)\r
179                                 {\r
180                                         for (Outline es : shapeHandlers)\r
181                                         {\r
182                                                 Shape elementShape = es.getElementShape(e);\r
183                                                 if (!GeometryUtils.contains(pickShapeInElementCoords, elementShape))\r
184                                                         continue nextElement;\r
185                                         }\r
186                                         result.add(e);          \r
187                                         continue nextElement;\r
188                                 }\r
189                                 continue nextElement;\r
190                         } \r
191                         \r
192                         // Pick by rectangle\r
193                         if (request.pickPolicy == PickPolicy.PICK_INTERSECTING_OBJECTS)\r
194                         {\r
195                                 if (GeometryUtils.intersects(request.pickArea, elementBoundsOnCanvas)) \r
196                                         result.add(e);\r
197                         }\r
198                         \r
199                         else\r
200                                 \r
201                         if (request.pickPolicy == PickPolicy.PICK_CONTAINED_OBJECTS)\r
202                         {\r
203                                 if (GeometryUtils.contains(request.pickArea, elementBoundsOnCanvas)) \r
204                                         result.add(e);\r
205                         }\r
206                         \r
207                 }\r
208 \r
209                 if (request.pickSorter != null) {\r
210                         request.pickSorter.sort((List<IElement>) result);\r
211                         finalResult.addAll(result);\r
212                 }\r
213         }\r
214 \r
215 }\r