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.diagramEditor;
\r
14 import gnu.trove.set.hash.THashSet;
\r
16 import java.awt.datatransfer.Transferable;
\r
17 import java.awt.datatransfer.UnsupportedFlavorException;
\r
18 import java.awt.dnd.DnDConstants;
\r
19 import java.awt.dnd.DropTargetDragEvent;
\r
20 import java.awt.geom.AffineTransform;
\r
21 import java.io.IOException;
\r
22 import java.util.ArrayList;
\r
23 import java.util.Collections;
\r
24 import java.util.HashMap;
\r
25 import java.util.List;
\r
27 import org.eclipse.jface.viewers.IStructuredSelection;
\r
28 import org.simantics.Logger;
\r
29 import org.simantics.db.ReadGraph;
\r
30 import org.simantics.db.RequestProcessor;
\r
31 import org.simantics.db.Resource;
\r
32 import org.simantics.db.Session;
\r
33 import org.simantics.db.common.request.UnaryRead;
\r
34 import org.simantics.db.common.request.UniqueRead;
\r
35 import org.simantics.db.common.utils.NameUtils;
\r
36 import org.simantics.db.common.utils.OrderedSetUtils;
\r
37 import org.simantics.db.exception.DatabaseException;
\r
38 import org.simantics.db.layer0.SelectionHints;
\r
39 import org.simantics.db.layer0.variable.Variable;
\r
40 import org.simantics.db.layer0.variable.Variables;
\r
41 import org.simantics.db.layer0.variable.Variables.Role;
\r
42 import org.simantics.diagram.adapter.GraphToDiagramSynchronizer;
\r
43 import org.simantics.diagram.content.ConnectionUtil;
\r
44 import org.simantics.diagram.stubs.DiagramResource;
\r
45 import org.simantics.diagram.ui.DiagramModelHints;
\r
46 import org.simantics.g2d.diagram.handler.DataElementMap;
\r
47 import org.simantics.g2d.dnd.DnDHints;
\r
48 import org.simantics.g2d.dnd.ElementClassDragItem;
\r
49 import org.simantics.g2d.dnd.IDnDContext;
\r
50 import org.simantics.g2d.dnd.IDropTargetParticipant;
\r
51 import org.simantics.g2d.element.ElementHints;
\r
52 import org.simantics.g2d.element.IElement;
\r
53 import org.simantics.g2d.utils.Alignment;
\r
54 import org.simantics.layer0.Layer0;
\r
55 import org.simantics.modeling.ModelingResources;
\r
56 import org.simantics.modeling.PropertyVariables;
\r
57 import org.simantics.modeling.PropertyVariablesImpl;
\r
58 import org.simantics.modeling.ui.diagram.monitor.MonitorClassFactory2;
\r
59 import org.simantics.structural.stubs.StructuralResource2;
\r
60 import org.simantics.ui.dnd.LocalObjectTransfer;
\r
61 import org.simantics.ui.dnd.LocalObjectTransferable;
\r
62 import org.simantics.ui.selection.WorkbenchSelectionElement;
\r
63 import org.simantics.ui.selection.WorkbenchSelectionUtils;
\r
64 import org.simantics.utils.datastructures.Triple;
\r
65 import org.simantics.utils.datastructures.hints.IHintContext;
\r
66 import org.simantics.utils.ui.ISelectionUtils;
\r
68 public class PopulateElementMonitorDropParticipant extends PopulateElementDropParticipant implements IDropTargetParticipant {
\r
70 private static final boolean DEBUG = false;
\r
72 // Scale for the monitors
\r
73 double scaleX, scaleY;
\r
77 public PopulateElementMonitorDropParticipant(GraphToDiagramSynchronizer synchronizer, double scaleX, double scaleY) {
\r
78 super(synchronizer);
\r
79 this.scaleX = scaleX;
\r
80 this.scaleY = scaleY;
\r
81 this.typeURI = DiagramResource.URIs.Monitor;
\r
84 public PopulateElementMonitorDropParticipant(GraphToDiagramSynchronizer synchronizer, String typeURI, double scaleX, double scaleY) {
\r
85 super(synchronizer);
\r
86 this.scaleX = scaleX;
\r
87 this.scaleY = scaleY;
\r
88 this.typeURI = typeURI;
\r
92 public void dragEnter(DropTargetDragEvent dtde, final IDnDContext dp) {
\r
94 Transferable tr = dtde.getTransferable();
\r
96 if (tr.isDataFlavorSupported(LocalObjectTransferable.FLAVOR)) {
\r
98 // This must be done to have SWT transfer set the source data
\r
100 Object obj = tr.getTransferData(LocalObjectTransferable.FLAVOR);
\r
102 System.out.println("GOT FROM AWT: " + obj);
\r
105 if (!(obj instanceof IStructuredSelection)) {
\r
106 obj = LocalObjectTransfer.getTransfer().getObject();
\r
108 System.out.println("GOT FROM SWT: " + obj);
\r
111 if (obj instanceof IStructuredSelection) {
\r
113 IStructuredSelection sel = (IStructuredSelection) obj;
\r
115 for(WorkbenchSelectionElement wse : WorkbenchSelectionUtils.getWorkbenchSelectionElements(sel)) {
\r
116 dp.add(new WSEDragItem(wse));
\r
119 Session session = synchronizer.getSession();
\r
121 List<Variable> properties = resolveVariables(session, (IStructuredSelection) obj);
\r
122 if (properties.isEmpty())
\r
125 List<ElementClassDragItem> items = session.syncRequest(new ResolveItems(properties));
\r
126 for (ElementClassDragItem item : items)
\r
129 dp.getHints().setHint(DnDHints.KEY_DND_GRID_COLUMNS, Integer.valueOf(1));
\r
132 } catch (UnsupportedFlavorException e) {
\r
133 Logger.defaultLogError(e);
\r
134 } catch (IOException e) {
\r
135 Logger.defaultLogError(e);
\r
136 } catch (DatabaseException e) {
\r
137 Logger.defaultLogError(e);
\r
142 dtde.acceptDrag(DnDConstants.ACTION_COPY);
\r
146 public void setHints(IHintContext context) {
\r
149 protected List<Variable> resolveVariables(RequestProcessor processor, IStructuredSelection sel) throws DatabaseException {
\r
151 return Collections.emptyList();
\r
153 Variable property = WorkbenchSelectionUtils.getPossibleVariable(sel);
\r
154 if(property != null)
\r
155 return Collections.singletonList(property);
\r
157 property = ISelectionUtils.getSinglePossibleKey(sel, SelectionHints.KEY_SELECTION_PROPERTY, Variable.class);
\r
158 if (property != null)
\r
159 return Collections.singletonList(property);
\r
161 final List<PropertyVariables> vars = ISelectionUtils.getPossibleKeys(sel, SelectionHints.KEY_MAIN, PropertyVariables.class);
\r
162 if (!vars.isEmpty()) {
\r
163 return processor.syncRequest(new UniqueRead<List<Variable>>() {
\r
165 public List<Variable> perform(ReadGraph graph) throws DatabaseException {
\r
166 // FIXME: this is a hack for indexed value support
\r
167 List<PropertyVariables> vs = PropertyVariablesImpl.resolve(graph, vars);
\r
168 List<Variable> result = new ArrayList<Variable>(vs.size());
\r
169 for (PropertyVariables v : vs)
\r
170 result.add(v.getVisualVariable());
\r
176 return Collections.emptyList();
\r
179 protected class ResolveItems extends UnaryRead<List<Variable>, List<ElementClassDragItem>> {
\r
181 public ResolveItems(List<Variable> parameter) {
\r
186 public List<ElementClassDragItem> perform(ReadGraph graph) throws DatabaseException {
\r
187 List<ElementClassDragItem> result = new ArrayList<ElementClassDragItem>(parameter.size());
\r
188 for (Variable property : parameter)
\r
189 result.addAll( resolve(graph, property) );
\r
193 public List<ElementClassDragItem> resolve(ReadGraph graph, Variable parameter) throws DatabaseException {
\r
196 System.out.println("PARAM: " + parameter.getURI(graph));
\r
197 Variable parent = parameter.browsePossible(graph, "..");
\r
198 System.out.println("PARENT: " + parent.getURI(graph));
\r
199 Resource parentComposite = parent.getPossibleRepresents(graph);
\r
200 System.out.println("PARENT REPRESENTS: " + NameUtils.getSafeLabel(graph, parentComposite));
\r
201 String prvi = Variables.getRVI(graph, parent);
\r
202 System.out.println("PARENT RVI: " + prvi);
\r
203 String parvi = Variables.getRVI(graph, parameter);
\r
204 System.out.println("PARAM RVI: " + parvi);
\r
207 Triple<Variable, Resource, IElement> match = findElementInDiagram(graph, parameter, false);
\r
209 return Collections.emptyList();
\r
211 if(match.third == null) {
\r
212 // We are in a different diagram, prevent creation of monitors
\r
213 // from UCs to different UCs or model configuration
\r
214 Resource diagram = synchronizer.getDiagram().getHint(DiagramModelHints.KEY_DIAGRAM_RESOURCE);
\r
215 Resource commonParent = findCommonParent(graph, diagram, match.second);
\r
216 StructuralResource2 STR = StructuralResource2.getInstance(graph);
\r
217 if(!graph.isInstanceOf(commonParent, STR.Composite))
\r
218 return Collections.emptyList();
\r
222 System.out.println("p=" + parameter.getURI(graph));
\r
223 System.out.println("c=" + match.first.getURI(graph));
\r
226 String rvi = Variables.getRVI(graph, match.first, parameter);
\r
228 System.out.println("r=" + rvi);
\r
230 Resource type = graph.getResource(typeURI);
\r
232 ElementClassDragItem item = new ElementClassDragItem(MonitorClassFactory2.createMonitorClass(type, match.third, new HashMap<String, String>(), match.second, rvi, scaleX, scaleY));
\r
233 item.getHintContext().setHint(ElementHints.KEY_HORIZONTAL_ALIGN, Alignment.LEADING);
\r
235 if (match.third != null)
\r
236 item.getHintContext().setHint(ElementHints.KEY_PARENT_ELEMENT, match.third);
\r
238 AffineTransform initialTr = AffineTransform.getScaleInstance(scaleX, scaleY);
\r
239 item.getHintContext().setHint(ElementHints.KEY_TRANSFORM, initialTr);
\r
241 setHints(item.getHintContext());
\r
243 return Collections.singletonList(item);
\r
247 private Triple<Variable, Resource, IElement> findElementInDiagram(ReadGraph graph, Variable property, boolean propertyRoleFound) throws DatabaseException {
\r
248 if (property == null)
\r
252 System.out.println("findElementInDiagram " + property.getURI(graph) + " " + property);
\r
254 DiagramResource DIA = DiagramResource.getInstance(graph);
\r
255 ModelingResources MOD = ModelingResources.getInstance(graph);
\r
256 final Resource diagram = synchronizer.getDiagram().getHint(DiagramModelHints.KEY_DIAGRAM_RESOURCE);
\r
258 if (!propertyRoleFound) {
\r
259 Role role = property.getPossibleRole(graph);
\r
260 propertyRoleFound = role == Role.PROPERTY;
\r
263 Resource represents = property.getPossibleRepresents(graph);
\r
264 if (represents != null) {
\r
266 System.out.println("represents " + NameUtils.getSafeName(graph, represents, true));
\r
267 Resource elementResource = graph.getPossibleObject(represents, MOD.ComponentToElement);
\r
268 // There must have be at least one
\r
269 // PROPERTY role variable in the
\r
270 // browsed path before finding this
\r
272 if(elementResource != null && propertyRoleFound) {
\r
273 Resource elementDiagram = OrderedSetUtils.getSingleOwnerList(graph, elementResource, DIA.Diagram);
\r
274 if(diagram.equals(elementDiagram)) {
\r
275 final DataElementMap map = synchronizer.getDiagram().getDiagramClass().getSingleItem(DataElementMap.class);
\r
276 IElement parentElement = map.getElement(synchronizer.getDiagram(), elementResource);
\r
278 if (graph.isInstanceOf(elementResource, DIA.Connection)) {
\r
279 Resource tailNode = ConnectionUtil.getConnectionTailNode(graph, elementResource);
\r
280 if (tailNode != null) {
\r
281 IElement tailNodeElement = map.getElement(synchronizer.getDiagram(), tailNode);
\r
282 if (tailNodeElement != null)
\r
283 parentElement = tailNodeElement;
\r
287 return Triple.make(property, represents, parentElement);
\r
289 // The monitored target module is on another diagram/composite.
\r
290 // No parent for the monitor then.
\r
291 return Triple.make(property, represents, null);
\r
296 return findElementInDiagram(graph, property.browsePossible(graph, "."), propertyRoleFound);
\r
301 private static Resource findCommonParent(ReadGraph graph, Resource a, Resource b) throws DatabaseException {
\r
302 Layer0 L0 = Layer0.getInstance(graph);
\r
303 THashSet<Resource> set = new THashSet<>();
\r
308 a = graph.getPossibleObject(a, L0.PartOf);
\r
311 return graph.getRootLibrary();
\r
315 b = graph.getPossibleObject(a, L0.PartOf);
\r
321 public double getPriority() {
\r