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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.modeling.ui.symbolEditor;
\r
14 import java.awt.datatransfer.Transferable;
\r
15 import java.awt.datatransfer.UnsupportedFlavorException;
\r
16 import java.awt.dnd.DnDConstants;
\r
17 import java.awt.dnd.DropTargetDragEvent;
\r
18 import java.awt.dnd.DropTargetDropEvent;
\r
19 import java.awt.dnd.DropTargetEvent;
\r
20 import java.awt.geom.Point2D;
\r
21 import java.io.IOException;
\r
22 import java.util.HashSet;
\r
23 import java.util.Set;
\r
25 import org.simantics.db.ReadGraph;
\r
26 import org.simantics.db.Resource;
\r
27 import org.simantics.db.Session;
\r
28 import org.simantics.db.WriteGraph;
\r
29 import org.simantics.db.common.request.ObjectsWithType;
\r
30 import org.simantics.db.exception.DatabaseException;
\r
31 import org.simantics.db.request.Read;
\r
32 import org.simantics.diagram.adapter.GraphToDiagramSynchronizer;
\r
33 import org.simantics.diagram.stubs.DiagramResource;
\r
34 import org.simantics.diagram.synchronization.graph.DiagramGraphUtil;
\r
35 import org.simantics.diagram.synchronization.graph.ElementWriter;
\r
36 import org.simantics.diagram.ui.DiagramModelHints;
\r
37 import org.simantics.g2d.diagram.DiagramHints;
\r
38 import org.simantics.g2d.diagram.DiagramMutator;
\r
39 import org.simantics.g2d.diagram.DiagramUtils;
\r
40 import org.simantics.g2d.diagram.IDiagram;
\r
41 import org.simantics.g2d.diagram.participant.AbstractDiagramParticipant;
\r
42 import org.simantics.g2d.dnd.DnDHints;
\r
43 import org.simantics.g2d.dnd.ElementClassDragItem;
\r
44 import org.simantics.g2d.dnd.IDnDContext;
\r
45 import org.simantics.g2d.dnd.IDragItem;
\r
46 import org.simantics.g2d.dnd.IDropTargetParticipant;
\r
47 import org.simantics.g2d.element.ElementClass;
\r
48 import org.simantics.g2d.element.ElementUtils;
\r
49 import org.simantics.g2d.element.IElement;
\r
50 import org.simantics.layer0.Layer0;
\r
51 import org.simantics.modeling.ModelingResources;
\r
52 import org.simantics.modeling.symbolEditor.PopulateTerminal;
\r
53 import org.simantics.structural.stubs.StructuralResource2;
\r
54 import org.simantics.ui.dnd.LocalObjectTransfer;
\r
55 import org.simantics.ui.dnd.LocalObjectTransferable;
\r
56 import org.simantics.ui.utils.ResourceAdaptionUtils;
\r
57 import org.simantics.utils.datastructures.Callback;
\r
58 import org.simantics.utils.datastructures.hints.IHintContext.Key;
\r
59 import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;
\r
60 import org.simantics.utils.logging.TimeLogger;
\r
61 import org.simantics.utils.ui.ErrorLogger;
\r
64 * @author Tuukka Lehtonen
\r
66 public class PopulateTerminalDropParticipant extends AbstractDiagramParticipant implements IDropTargetParticipant {
\r
68 private static final Key KEY_TERMINAL_RELATION = new KeyOf(Resource.class, "TERMINAL_RELATION");
\r
70 protected GraphToDiagramSynchronizer synchronizer;
\r
71 protected Resource symbolDiagram;
\r
73 public PopulateTerminalDropParticipant(Resource symbolDiagram, GraphToDiagramSynchronizer synchronizer) {
\r
74 this.symbolDiagram = symbolDiagram;
\r
75 this.synchronizer = synchronizer;
\r
79 public void dragEnter(final DropTargetDragEvent dtde, final IDnDContext dp) {
\r
80 Transferable tr = dtde.getTransferable();
\r
81 if (tr.isDataFlavorSupported(LocalObjectTransferable.FLAVOR)) {
\r
83 Session session = synchronizer.getSession();
\r
86 tr.getTransferData(LocalObjectTransferable.FLAVOR);
\r
87 final Resource[] resources = ResourceAdaptionUtils.toResources(LocalObjectTransfer.getTransfer()
\r
90 int itemsAdded = session.syncRequest(new Read<Integer>() {
\r
92 public Integer perform(ReadGraph g) throws DatabaseException {
\r
95 Layer0 L0 = Layer0.getInstance(g);
\r
96 DiagramResource DIA = DiagramResource.getInstance(g);
\r
97 StructuralResource2 STR = StructuralResource2.getInstance(g);
\r
98 ModelingResources MOD = ModelingResources.getInstance(g);
\r
100 Resource symbol = g.getPossibleObject(symbolDiagram, STR.Defines);
\r
101 if (symbol == null)
\r
103 Resource componentType = g.getPossibleObject(symbol, MOD.SymbolToComponentType);
\r
104 if (componentType == null)
\r
106 Set<Resource> connectionRelationsOfSymbol = new HashSet<Resource>( g.syncRequest(new ObjectsWithType(componentType, L0.ConsistsOf, STR.ConnectionRelation)) );
\r
108 // System.out.println("Symbol: " + NameUtils.getURIOrSafeNameInternal(g, symbolDiagram));
\r
109 // System.out.println("Component type: " + NameUtils.getURIOrSafeNameInternal(g, componentType));
\r
110 // System.out.println("Connection relations: " + connectionRelationsOfSymbol);
\r
112 Set<Resource> usedConnectionRelations = new HashSet<Resource>();
\r
113 for (Resource terminal : g.syncRequest(new ObjectsWithType(symbolDiagram, L0.ConsistsOf, DIA.Terminal))) {
\r
114 Resource binds = DiagramGraphUtil.getPossibleConnectionPointOfTerminal(g, terminal);
\r
116 for (Resource connRel : g.getObjects(binds, MOD.DiagramConnectionRelationToConnectionRelation))
\r
117 usedConnectionRelations.add(connRel);
\r
120 for (Resource resource : resources) {
\r
121 //System.out.println("Name: " + NameUtils.getSafeName(g, resource));
\r
122 IDragItem di = null;
\r
123 Resource connectionRelation = null;
\r
125 if (g.isInstanceOf(resource, STR.ConnectionRelation)) {
\r
126 if (!connectionRelationsOfSymbol.contains(resource))
\r
128 Resource terminal = g.getPossibleObject(resource, MOD.ConnectionRelationToTerminal);
\r
129 if (terminal == null)
\r
130 terminal = MOD.TestTerminal;
\r
131 di = new ElementClassDragItem(synchronizer.getNodeClass(g, terminal));
\r
132 connectionRelation = resource;
\r
134 /* TODO should we replace this with something?
\r
135 else if (g.isInstanceOf(resource, STR.ConnectionPointDefinition)) {
\r
136 Resource connectionType = g.getPossibleObject(resource, STR.HasConnectionType);
\r
137 Resource connectionDirection = g.getPossibleObject(resource, STR.HasConnectionDirection);
\r
138 Collection<Resource> terminals = connectionType == null || connectionDirection == null
\r
139 ? Collections.<Resource> emptyList() : g.getObjects(connectionType,
\r
140 g.getInverse(STR.SupportsConnectionType));
\r
141 if (terminals.isEmpty())
\r
142 di = new ElementClassDragItem(synchronizer.getNodeClass(g, MOD.TestTerminal));
\r
144 for (Resource t : terminals)
\r
145 if (connectionDirection.equals(g.getPossibleObject(t, STR.SupportsDirection))) {
\r
146 di = new ElementClassDragItem(synchronizer.getNodeClass(t));
\r
150 connectionRelation = g.getSingleObject(resource, L0.ConcernsRelation);
\r
153 if (di != null && connectionRelation != null && !usedConnectionRelations.contains(connectionRelation)) {
\r
154 di.getHintContext().setHint(KEY_TERMINAL_RELATION, connectionRelation);
\r
163 if (itemsAdded > 0 ) {
\r
164 dp.getHints().setHint(DnDHints.KEY_DND_GRID_COLUMNS, Integer.valueOf(1));
\r
165 dtde.acceptDrag(DnDConstants.ACTION_COPY);
\r
168 } catch (DatabaseException e) {
\r
169 ErrorLogger.defaultLogError(e);
\r
170 } catch (UnsupportedFlavorException e) {
\r
171 ErrorLogger.defaultLogError(e);
\r
172 } catch (IOException e) {
\r
173 ErrorLogger.defaultLogError(e);
\r
174 } catch (IllegalArgumentException e) {
\r
175 ErrorLogger.defaultLogError(e);
\r
182 public void dragExit(DropTargetEvent dte, IDnDContext dp) {
\r
183 // System.out.println("exit");
\r
187 public void dragOver(DropTargetDragEvent dtde, IDnDContext dp) {
\r
188 // System.out.println("over");
\r
192 public void drop(DropTargetDropEvent dtde, final IDnDContext dp) {
\r
193 TimeLogger.resetTimeAndLog(getClass(), "drop");
\r
195 final IDiagram d = getHint(DiagramHints.KEY_DIAGRAM);
\r
199 DiagramUtils.mutateDiagram(d, mutator -> {
\r
200 IDragItem items[] = dp.toArray();
\r
202 for (IDragItem i : items) {
\r
203 if (!(i instanceof ElementClassDragItem))
\r
205 final Resource relation = i.getHintContext().getHint(KEY_TERMINAL_RELATION);
\r
206 if (relation == null)
\r
209 ElementClassDragItem res = (ElementClassDragItem) i;
\r
210 ElementClass ec = res.getElementClass();
\r
212 Point2D pos = dp.getItemPosition(i);
\r
213 // System.out.println(pos);
\r
214 assert (pos != null);
\r
216 IElement element = mutator.newElement(ec);
\r
217 ElementUtils.setPos(element, new Point2D.Double(pos.getX(), pos.getY()));
\r
218 element.setHint(DiagramModelHints.KEY_ELEMENT_WRITER, new ElementWriter() {
\r
221 public void addToGraph(WriteGraph g, IElement element, Resource terminal) throws DatabaseException {
\r
222 PopulateTerminal.addToGraph(g, symbolDiagram, relation, terminal);
\r
226 public void removeFromGraph(WriteGraph graph, Resource elementResource) {
\r
234 getContext().getContentContext().setDirty();
\r
238 public void dropActionChanged(DropTargetDragEvent dtde, IDnDContext dp) {
\r
239 dtde.acceptDrag(DnDConstants.ACTION_COPY);
\r
243 public int getAllowedOps() {
\r
244 return DnDConstants.ACTION_COPY | DnDConstants.ACTION_MOVE | DnDConstants.ACTION_LINK;
\r
248 public double getPriority() {
\r