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