]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - 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
diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/handler/impl/PickContextImpl.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/handler/impl/PickContextImpl.java
new file mode 100644 (file)
index 0000000..0fca5dc
--- /dev/null
@@ -0,0 +1,215 @@
+/*******************************************************************************\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.diagram.handler.impl;\r
+\r
+import java.awt.Shape;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.NoninvertibleTransformException;\r
+import java.awt.geom.Rectangle2D;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.List;\r
+\r
+import org.simantics.g2d.diagram.DiagramHints;\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.diagram.handler.PickContext;\r
+import org.simantics.g2d.diagram.handler.PickRequest;\r
+import org.simantics.g2d.diagram.handler.PickRequest.PickPolicy;\r
+import org.simantics.g2d.element.ElementClass;\r
+import org.simantics.g2d.element.ElementUtils;\r
+import org.simantics.g2d.element.IElement;\r
+import org.simantics.g2d.element.handler.ElementLayers;\r
+import org.simantics.g2d.element.handler.InternalSize;\r
+import org.simantics.g2d.element.handler.Outline;\r
+import org.simantics.g2d.element.handler.Pick;\r
+import org.simantics.g2d.element.handler.Pick2;\r
+import org.simantics.g2d.element.handler.Transform;\r
+import org.simantics.g2d.layers.ILayers;\r
+import org.simantics.g2d.utils.GeometryUtils;\r
+\r
+/**\r
+ * @author Toni Kalajainen\r
+ */\r
+public class PickContextImpl implements PickContext {\r
+\r
+       public static final PickContextImpl INSTANCE = new PickContextImpl(); \r
+\r
+       @Override\r
+       public void pick(\r
+                       IDiagram diagram, \r
+                       PickRequest request, \r
+                       Collection<IElement> finalResult) \r
+       {\r
+               assert(diagram!=null);\r
+               assert(request!=null);\r
+               assert(finalResult!=null);\r
+\r
+               ILayers layers = diagram.getHint(DiagramHints.KEY_LAYERS);\r
+\r
+               Collection<IElement> result = finalResult;\r
+               if (request.pickSorter != null) {\r
+                       // Need a temporary List<IElement> for PickSorter\r
+                       result = new ArrayList<IElement>();\r
+               }\r
+               Rectangle2D elementBounds = new Rectangle2D.Double();\r
+               nextElement:\r
+               for (IElement e : diagram.getSnapshot())\r
+               {\r
+                       // Ignore hidden elements.\r
+                       if (ElementUtils.isHidden(e))\r
+                               continue;\r
+\r
+                       ElementClass ec = e.getElementClass();\r
+                       \r
+                       if(layers != null && !layers.getIgnoreFocusSettings()) {\r
+                               ElementLayers el = ec.getAtMostOneItemOfClass(ElementLayers.class);\r
+                               if(el != null) {\r
+                                       if(!el.isFocusable(e, layers)) continue;\r
+                               }\r
+                       }\r
+                       \r
+                       if (request.pickFilter!=null && !request.pickFilter.accept(e)) continue;\r
+                       \r
+                       Transform t = e.getElementClass().getSingleItem(Transform.class);\r
+                       AffineTransform canvasToElement = t.getTransform(e);\r
+                       if (canvasToElement==null) continue;\r
+                       double det = canvasToElement.getDeterminant();\r
+                       if (det == 0) {\r
+                               // Singular transform, just reset the rotation/scaling part to\r
+                               // allow picking to proceed.\r
+                               // TODO: this may modify the internal transform value of an element which is not intended\r
+                               canvasToElement.setToTranslation(\r
+                                               canvasToElement.getTranslateX(),\r
+                                               canvasToElement.getTranslateY());\r
+                       }\r
+\r
+                       // Get bounds, ignore elements that have no bounds\r
+                       InternalSize b = e.getElementClass().getAtMostOneItemOfClass(InternalSize.class);\r
+                       if (b==null) continue;\r
+                       elementBounds.setFrame(Double.NaN, Double.NaN, Double.NaN, Double.NaN);\r
+                       b.getBounds(e, elementBounds);\r
+                       if (Double.isNaN(elementBounds.getWidth()) || Double.isNaN(elementBounds.getHeight()))\r
+                               continue;\r
+\r
+                       Shape elementBoundsOnCanvas = GeometryUtils.transformShape(elementBounds, canvasToElement);\r
+                       if (elementBoundsOnCanvas instanceof Rectangle2D)\r
+                               elementBoundsOnCanvas = elementBoundsOnCanvas.getBounds2D();\r
+                       elementBoundsOnCanvas = elementBoundsOnCanvas.getBounds2D();\r
+                       org.simantics.scenegraph.utils.GeometryUtils.expandRectangle((Rectangle2D)elementBoundsOnCanvas, 1e-3, 1e-3, 1e-3, 1e-3);\r
+                       \r
+                       // Pick with pick handler(s)\r
+                       List<Pick> pickHandlers = e.getElementClass().getItemsByClass(Pick.class);\r
+                       if (!pickHandlers.isEmpty())\r
+                       {\r
+                           // Rough filtering with bounds\r
+                               if (!GeometryUtils.intersects(request.pickArea, elementBoundsOnCanvas)) {\r
+//                                     System.out.println("Element bounds discards " + e.getElementClass());\r
+                                       continue;\r
+                               }\r
+                               \r
+                               // Convert pick shape to element coordinates\r
+//                             AffineTransform elementToCanvas;\r
+//                             try {\r
+//                                     elementToCanvas = canvasToElement.createInverse();\r
+//                             } catch (NoninvertibleTransformException e1) {\r
+//                                     throw new RuntimeException(e1);\r
+//                             }\r
+//                             Shape pickShapeInElementCoords = GeometryUtils.transformShape(request.pickArea, elementToCanvas);\r
+                               for (Pick p : pickHandlers)\r
+                               {\r
+                                       if (p instanceof Pick2) {\r
+                                               Pick2 p2 = (Pick2) p;\r
+                                               //if (p2.pick(e, pickShapeInElementCoords, request.pickPolicy, result) > 0)\r
+                                               if (p2.pick(e, request.pickArea, request.pickPolicy, result) > 0)\r
+                                                       continue nextElement;\r
+                                       } else {\r
+                                               //if (p.pickTest(e, pickShapeInElementCoords, request.pickPolicy)) {\r
+                                               if (p.pickTest(e, request.pickArea, request.pickPolicy)) {\r
+                                                       result.add(e);\r
+                                                       continue nextElement;\r
+                                               }\r
+                                       }\r
+                               }\r
+                               continue nextElement;\r
+                       }\r
+                       \r
+                       // Pick with shape handler(s) \r
+                       List<Outline> shapeHandlers = e.getElementClass().getItemsByClass(Outline.class);\r
+                       if (!shapeHandlers.isEmpty())\r
+                       {\r
+                               // Rough filtering with bounds\r
+                               if (!GeometryUtils.intersects(request.pickArea, elementBoundsOnCanvas)) continue;\r
+                               \r
+                               // Convert pick shape to element coordinates\r
+                               AffineTransform elementToCanvas;\r
+                               try {\r
+                                       elementToCanvas = canvasToElement.createInverse();\r
+                               } catch (NoninvertibleTransformException e1) {\r
+                                       throw new RuntimeException(e1);\r
+                               }\r
+                               Shape pickShapeInElementCoords = GeometryUtils.transformShape(request.pickArea, elementToCanvas);\r
+                               \r
+                               // Intersection with one shape is enough\r
+                               if (request.pickPolicy == PickPolicy.PICK_INTERSECTING_OBJECTS)\r
+                               {\r
+                                       for (Outline es : shapeHandlers)\r
+                                       {\r
+                                               Shape elementShape = es.getElementShape(e);             \r
+                                               if (elementShape==null) continue nextElement;\r
+                                               if (GeometryUtils.intersects(pickShapeInElementCoords, elementShape))\r
+                                               {\r
+                                                       result.add(e);\r
+                                                       continue nextElement;\r
+                                               }\r
+                                       }\r
+                                       continue nextElement;\r
+                               }\r
+                               \r
+                               // Contains of all shapes is required \r
+                               if (request.pickPolicy == PickPolicy.PICK_CONTAINED_OBJECTS)\r
+                               {\r
+                                       for (Outline es : shapeHandlers)\r
+                                       {\r
+                                               Shape elementShape = es.getElementShape(e);\r
+                                               if (!GeometryUtils.contains(pickShapeInElementCoords, elementShape))\r
+                                                       continue nextElement;\r
+                                       }\r
+                                       result.add(e);          \r
+                                       continue nextElement;\r
+                               }\r
+                               continue nextElement;\r
+                       } \r
+                       \r
+                       // Pick by rectangle\r
+                       if (request.pickPolicy == PickPolicy.PICK_INTERSECTING_OBJECTS)\r
+                       {\r
+                               if (GeometryUtils.intersects(request.pickArea, elementBoundsOnCanvas)) \r
+                                       result.add(e);\r
+                       }\r
+                       \r
+                       else\r
+                               \r
+                       if (request.pickPolicy == PickPolicy.PICK_CONTAINED_OBJECTS)\r
+                       {\r
+                               if (GeometryUtils.contains(request.pickArea, elementBoundsOnCanvas)) \r
+                                       result.add(e);\r
+                       }\r
+                       \r
+               }\r
+\r
+               if (request.pickSorter != null) {\r
+                       request.pickSorter.sort((List<IElement>) result);\r
+                       finalResult.addAll(result);\r
+               }\r
+       }\r
+\r
+}\r