+/*******************************************************************************\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.modeling.ui.symbolEditor;\r
+\r
+import java.awt.datatransfer.Transferable;\r
+import java.awt.datatransfer.UnsupportedFlavorException;\r
+import java.awt.dnd.DnDConstants;\r
+import java.awt.dnd.DropTargetDragEvent;\r
+import java.awt.dnd.DropTargetDropEvent;\r
+import java.awt.dnd.DropTargetEvent;\r
+import java.awt.geom.Point2D;\r
+import java.io.IOException;\r
+import java.util.HashSet;\r
+import java.util.Set;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.request.ObjectsWithType;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.diagram.adapter.GraphToDiagramSynchronizer;\r
+import org.simantics.diagram.stubs.DiagramResource;\r
+import org.simantics.diagram.synchronization.graph.DiagramGraphUtil;\r
+import org.simantics.diagram.synchronization.graph.ElementWriter;\r
+import org.simantics.diagram.ui.DiagramModelHints;\r
+import org.simantics.g2d.diagram.DiagramHints;\r
+import org.simantics.g2d.diagram.DiagramMutator;\r
+import org.simantics.g2d.diagram.DiagramUtils;\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.diagram.participant.AbstractDiagramParticipant;\r
+import org.simantics.g2d.dnd.DnDHints;\r
+import org.simantics.g2d.dnd.ElementClassDragItem;\r
+import org.simantics.g2d.dnd.IDnDContext;\r
+import org.simantics.g2d.dnd.IDragItem;\r
+import org.simantics.g2d.dnd.IDropTargetParticipant;\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.layer0.Layer0;\r
+import org.simantics.modeling.ModelingResources;\r
+import org.simantics.modeling.symbolEditor.PopulateTerminal;\r
+import org.simantics.structural.stubs.StructuralResource2;\r
+import org.simantics.ui.dnd.LocalObjectTransfer;\r
+import org.simantics.ui.dnd.LocalObjectTransferable;\r
+import org.simantics.ui.utils.ResourceAdaptionUtils;\r
+import org.simantics.utils.datastructures.Callback;\r
+import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
+import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;\r
+import org.simantics.utils.logging.TimeLogger;\r
+import org.simantics.utils.ui.ErrorLogger;\r
+\r
+/**\r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class PopulateTerminalDropParticipant extends AbstractDiagramParticipant implements IDropTargetParticipant {\r
+\r
+ private static final Key KEY_TERMINAL_RELATION = new KeyOf(Resource.class, "TERMINAL_RELATION");\r
+\r
+ protected GraphToDiagramSynchronizer synchronizer;\r
+ protected Resource symbolDiagram;\r
+\r
+ public PopulateTerminalDropParticipant(Resource symbolDiagram, GraphToDiagramSynchronizer synchronizer) {\r
+ this.symbolDiagram = symbolDiagram;\r
+ this.synchronizer = synchronizer;\r
+ }\r
+\r
+ @Override\r
+ public void dragEnter(final DropTargetDragEvent dtde, final IDnDContext dp) {\r
+ Transferable tr = dtde.getTransferable();\r
+ if (tr.isDataFlavorSupported(LocalObjectTransferable.FLAVOR)) {\r
+\r
+ Session session = synchronizer.getSession();\r
+\r
+ try {\r
+ tr.getTransferData(LocalObjectTransferable.FLAVOR);\r
+ final Resource[] resources = ResourceAdaptionUtils.toResources(LocalObjectTransfer.getTransfer()\r
+ .getObject());\r
+\r
+ int itemsAdded = session.syncRequest(new Read<Integer>() {\r
+ @Override\r
+ public Integer perform(ReadGraph g) throws DatabaseException {\r
+ int items = 0;\r
+\r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ DiagramResource DIA = DiagramResource.getInstance(g);\r
+ StructuralResource2 STR = StructuralResource2.getInstance(g);\r
+ ModelingResources MOD = ModelingResources.getInstance(g);\r
+\r
+ Resource symbol = g.getPossibleObject(symbolDiagram, STR.Defines);\r
+ if (symbol == null)\r
+ return 0;\r
+ Resource componentType = g.getPossibleObject(symbol, MOD.SymbolToComponentType);\r
+ if (componentType == null)\r
+ return 0;\r
+ Set<Resource> connectionRelationsOfSymbol = new HashSet<Resource>( g.syncRequest(new ObjectsWithType(componentType, L0.ConsistsOf, STR.ConnectionRelation)) );\r
+\r
+// System.out.println("Symbol: " + NameUtils.getURIOrSafeNameInternal(g, symbolDiagram));\r
+// System.out.println("Component type: " + NameUtils.getURIOrSafeNameInternal(g, componentType));\r
+// System.out.println("Connection relations: " + connectionRelationsOfSymbol);\r
+\r
+ Set<Resource> usedConnectionRelations = new HashSet<Resource>();\r
+ for (Resource terminal : g.syncRequest(new ObjectsWithType(symbolDiagram, L0.ConsistsOf, DIA.Terminal))) {\r
+ Resource binds = DiagramGraphUtil.getPossibleConnectionPointOfTerminal(g, terminal);\r
+ if(binds != null)\r
+ for (Resource connRel : g.getObjects(binds, MOD.DiagramConnectionRelationToConnectionRelation))\r
+ usedConnectionRelations.add(connRel);\r
+ }\r
+\r
+ for (Resource resource : resources) {\r
+ //System.out.println("Name: " + NameUtils.getSafeName(g, resource));\r
+ IDragItem di = null;\r
+ Resource connectionRelation = null;\r
+\r
+ if (g.isInstanceOf(resource, STR.ConnectionRelation)) {\r
+ if (!connectionRelationsOfSymbol.contains(resource))\r
+ continue;\r
+ Resource terminal = g.getPossibleObject(resource, MOD.ConnectionRelationToTerminal);\r
+ if (terminal == null)\r
+ terminal = MOD.TestTerminal;\r
+ di = new ElementClassDragItem(synchronizer.getNodeClass(g, terminal));\r
+ connectionRelation = resource;\r
+ }\r
+ /* TODO should we replace this with something?\r
+ else if (g.isInstanceOf(resource, STR.ConnectionPointDefinition)) {\r
+ Resource connectionType = g.getPossibleObject(resource, STR.HasConnectionType);\r
+ Resource connectionDirection = g.getPossibleObject(resource, STR.HasConnectionDirection);\r
+ Collection<Resource> terminals = connectionType == null || connectionDirection == null\r
+ ? Collections.<Resource> emptyList() : g.getObjects(connectionType,\r
+ g.getInverse(STR.SupportsConnectionType));\r
+ if (terminals.isEmpty())\r
+ di = new ElementClassDragItem(synchronizer.getNodeClass(g, MOD.TestTerminal));\r
+ else\r
+ for (Resource t : terminals)\r
+ if (connectionDirection.equals(g.getPossibleObject(t, STR.SupportsDirection))) {\r
+ di = new ElementClassDragItem(synchronizer.getNodeClass(t));\r
+ break;\r
+ }\r
+\r
+ connectionRelation = g.getSingleObject(resource, L0.ConcernsRelation);\r
+ }*/\r
+\r
+ if (di != null && connectionRelation != null && !usedConnectionRelations.contains(connectionRelation)) {\r
+ di.getHintContext().setHint(KEY_TERMINAL_RELATION, connectionRelation);\r
+ dp.add( di );\r
+ ++items;\r
+ }\r
+ }\r
+ return items;\r
+ }\r
+ });\r
+\r
+ if (itemsAdded > 0 ) {\r
+ dp.getHints().setHint(DnDHints.KEY_DND_GRID_COLUMNS, Integer.valueOf(1));\r
+ dtde.acceptDrag(DnDConstants.ACTION_COPY);\r
+ }\r
+\r
+ } catch (DatabaseException e) {\r
+ ErrorLogger.defaultLogError(e);\r
+ } catch (UnsupportedFlavorException e) {\r
+ ErrorLogger.defaultLogError(e);\r
+ } catch (IOException e) {\r
+ ErrorLogger.defaultLogError(e);\r
+ } catch (IllegalArgumentException e) {\r
+ ErrorLogger.defaultLogError(e);\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ @Override\r
+ public void dragExit(DropTargetEvent dte, IDnDContext dp) {\r
+ // System.out.println("exit");\r
+ }\r
+\r
+ @Override\r
+ public void dragOver(DropTargetDragEvent dtde, IDnDContext dp) {\r
+ // System.out.println("over");\r
+ }\r
+\r
+ @Override\r
+ public void drop(DropTargetDropEvent dtde, final IDnDContext dp) {\r
+ TimeLogger.resetTimeAndLog(getClass(), "drop");\r
+ \r
+ final IDiagram d = getHint(DiagramHints.KEY_DIAGRAM);\r
+ if (d == null)\r
+ return;\r
+\r
+ DiagramUtils.mutateDiagram(d, mutator -> {\r
+ IDragItem items[] = dp.toArray();\r
+\r
+ for (IDragItem i : items) {\r
+ if (!(i instanceof ElementClassDragItem))\r
+ continue;\r
+ final Resource relation = i.getHintContext().getHint(KEY_TERMINAL_RELATION);\r
+ if (relation == null)\r
+ continue;\r
+\r
+ ElementClassDragItem res = (ElementClassDragItem) i;\r
+ ElementClass ec = res.getElementClass();\r
+\r
+ Point2D pos = dp.getItemPosition(i);\r
+ // System.out.println(pos);\r
+ assert (pos != null);\r
+\r
+ IElement element = mutator.newElement(ec);\r
+ ElementUtils.setPos(element, new Point2D.Double(pos.getX(), pos.getY()));\r
+ element.setHint(DiagramModelHints.KEY_ELEMENT_WRITER, new ElementWriter() {\r
+\r
+ @Override\r
+ public void addToGraph(WriteGraph g, IElement element, Resource terminal) throws DatabaseException {\r
+ PopulateTerminal.addToGraph(g, symbolDiagram, relation, terminal);\r
+ }\r
+\r
+ @Override\r
+ public void removeFromGraph(WriteGraph graph, Resource elementResource) {\r
+ }\r
+ });\r
+\r
+ dp.remove(i);\r
+ }\r
+ });\r
+\r
+ getContext().getContentContext().setDirty();\r
+ }\r
+\r
+ @Override\r
+ public void dropActionChanged(DropTargetDragEvent dtde, IDnDContext dp) {\r
+ dtde.acceptDrag(DnDConstants.ACTION_COPY);\r
+ }\r
+\r
+ @Override\r
+ public int getAllowedOps() {\r
+ return DnDConstants.ACTION_COPY | DnDConstants.ACTION_MOVE | DnDConstants.ACTION_LINK;\r
+ }\r
+\r
+ @Override\r
+ public double getPriority() {\r
+ return 9.0;\r
+ }\r
+ \r
+}
\ No newline at end of file