]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/symbolEditor/PopulateTerminalDropParticipant.java
Red background color & tooltip for invalid derived property expression
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / symbolEditor / PopulateTerminalDropParticipant.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
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
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.modeling.ui.symbolEditor;
13
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;
23 import java.util.Set;
24
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;
62
63 /**
64  * @author Tuukka Lehtonen
65  */
66 public class PopulateTerminalDropParticipant extends AbstractDiagramParticipant implements IDropTargetParticipant {
67
68     private static final Key KEY_TERMINAL_RELATION = new KeyOf(Resource.class, "TERMINAL_RELATION");
69
70     protected GraphToDiagramSynchronizer synchronizer;
71     protected Resource                   symbolDiagram;
72
73     public PopulateTerminalDropParticipant(Resource symbolDiagram, GraphToDiagramSynchronizer synchronizer) {
74         this.symbolDiagram = symbolDiagram;
75         this.synchronizer = synchronizer;
76     }
77
78     @Override
79     public void dragEnter(final DropTargetDragEvent dtde, final IDnDContext dp) {
80         Transferable tr = dtde.getTransferable();
81         if (tr.isDataFlavorSupported(LocalObjectTransferable.FLAVOR)) {
82
83             Session session = synchronizer.getSession();
84
85             try {
86                 tr.getTransferData(LocalObjectTransferable.FLAVOR);
87                 final Resource[] resources = ResourceAdaptionUtils.toResources(LocalObjectTransfer.getTransfer()
88                         .getObject());
89
90                 int itemsAdded = session.syncRequest(new Read<Integer>() {
91                     @Override
92                     public Integer perform(ReadGraph g) throws DatabaseException {
93                         int items = 0;
94
95                         Layer0 L0 = Layer0.getInstance(g);
96                         DiagramResource DIA = DiagramResource.getInstance(g);
97                         StructuralResource2 STR = StructuralResource2.getInstance(g);
98                         ModelingResources MOD = ModelingResources.getInstance(g);
99
100                         Resource symbol = g.getPossibleObject(symbolDiagram, STR.Defines);
101                         if (symbol == null)
102                             return 0;
103                         Resource componentType = g.getPossibleObject(symbol, MOD.SymbolToComponentType);
104                         if (componentType == null)
105                             return 0;
106                         Set<Resource> connectionRelationsOfSymbol = new HashSet<Resource>( g.syncRequest(new ObjectsWithType(componentType, L0.ConsistsOf, STR.ConnectionRelation)) );
107
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);
111
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);
115                             if(binds != null)
116                                 for (Resource connRel : g.getObjects(binds, MOD.DiagramConnectionRelationToConnectionRelation))
117                                     usedConnectionRelations.add(connRel);
118                         }
119
120                         for (Resource resource : resources) {
121                             //System.out.println("Name: " + NameUtils.getSafeName(g, resource));
122                             IDragItem di = null;
123                             Resource connectionRelation = null;
124
125                             if (g.isInstanceOf(resource, STR.ConnectionRelation)) {
126                                 if (!connectionRelationsOfSymbol.contains(resource))
127                                     continue;
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;
133                             }
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));
143                                 else
144                                     for (Resource t : terminals)
145                                         if (connectionDirection.equals(g.getPossibleObject(t, STR.SupportsDirection))) {
146                                             di = new ElementClassDragItem(synchronizer.getNodeClass(t));
147                                             break;
148                                         }
149
150                                 connectionRelation = g.getSingleObject(resource, L0.ConcernsRelation);
151                             }*/
152
153                             if (di != null && connectionRelation != null && !usedConnectionRelations.contains(connectionRelation)) {
154                                 di.getHintContext().setHint(KEY_TERMINAL_RELATION, connectionRelation);
155                                 dp.add( di );
156                                 ++items;
157                             }
158                         }
159                         return items;
160                     }
161                 });
162
163                 if (itemsAdded > 0 ) {
164                     dp.getHints().setHint(DnDHints.KEY_DND_GRID_COLUMNS, Integer.valueOf(1));
165                     dtde.acceptDrag(DnDConstants.ACTION_COPY);
166                 }
167
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);
176             }
177         }
178
179     }
180
181     @Override
182     public void dragExit(DropTargetEvent dte, IDnDContext dp) {
183         // System.out.println("exit");
184     }
185
186     @Override
187     public void dragOver(DropTargetDragEvent dtde, IDnDContext dp) {
188         // System.out.println("over");
189     }
190
191     @Override
192     public void drop(DropTargetDropEvent dtde, final IDnDContext dp) {
193         TimeLogger.resetTimeAndLog(getClass(), "drop");
194     
195         final IDiagram d = getHint(DiagramHints.KEY_DIAGRAM);
196         if (d == null)
197             return;
198
199         DiagramUtils.mutateDiagram(d, mutator -> {
200             IDragItem items[] = dp.toArray();
201
202             for (IDragItem i : items) {
203                 if (!(i instanceof ElementClassDragItem))
204                     continue;
205                 final Resource relation = i.getHintContext().getHint(KEY_TERMINAL_RELATION);
206                 if (relation == null)
207                     continue;
208
209                 ElementClassDragItem res = (ElementClassDragItem) i;
210                 ElementClass ec = res.getElementClass();
211
212                 Point2D pos = dp.getItemPosition(i);
213                 // System.out.println(pos);
214                 assert (pos != null);
215
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() {
219
220                     @Override
221                     public void addToGraph(WriteGraph g, IElement element, Resource terminal) throws DatabaseException {
222                         PopulateTerminal.addToGraph(g, symbolDiagram, relation, terminal);
223                     }
224
225                     @Override
226                     public void removeFromGraph(WriteGraph graph, Resource elementResource) {
227                     }
228                 });
229
230                 dp.remove(i);
231             }
232         });
233
234         getContext().getContentContext().setDirty();
235     }
236
237     @Override
238     public void dropActionChanged(DropTargetDragEvent dtde, IDnDContext dp) {
239         dtde.acceptDrag(DnDConstants.ACTION_COPY);
240     }
241
242     @Override
243     public int getAllowedOps() {
244         return DnDConstants.ACTION_COPY | DnDConstants.ACTION_MOVE | DnDConstants.ACTION_LINK;
245     }
246
247     @Override
248     public double getPriority() {
249         return 9.0;
250     }
251     
252 }