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.diagramEditor;
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.geom.AffineTransform;
19 import java.io.IOException;
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.HashMap;
23 import java.util.List;
25 import org.eclipse.jface.viewers.IStructuredSelection;
26 import org.simantics.db.ReadGraph;
27 import org.simantics.db.RequestProcessor;
28 import org.simantics.db.Resource;
29 import org.simantics.db.Session;
30 import org.simantics.db.common.request.UnaryRead;
31 import org.simantics.db.common.request.UniqueRead;
32 import org.simantics.db.common.utils.NameUtils;
33 import org.simantics.db.common.utils.OrderedSetUtils;
34 import org.simantics.db.exception.DatabaseException;
35 import org.simantics.db.layer0.SelectionHints;
36 import org.simantics.db.layer0.variable.Variable;
37 import org.simantics.db.layer0.variable.Variables;
38 import org.simantics.db.layer0.variable.Variables.Role;
39 import org.simantics.diagram.adapter.GraphToDiagramSynchronizer;
40 import org.simantics.diagram.content.ConnectionUtil;
41 import org.simantics.diagram.stubs.DiagramResource;
42 import org.simantics.diagram.ui.DiagramModelHints;
43 import org.simantics.g2d.diagram.handler.DataElementMap;
44 import org.simantics.g2d.dnd.DnDHints;
45 import org.simantics.g2d.dnd.ElementClassDragItem;
46 import org.simantics.g2d.dnd.IDnDContext;
47 import org.simantics.g2d.dnd.IDropTargetParticipant;
48 import org.simantics.g2d.element.ElementHints;
49 import org.simantics.g2d.element.IElement;
50 import org.simantics.g2d.utils.Alignment;
51 import org.simantics.layer0.Layer0;
52 import org.simantics.modeling.ModelingResources;
53 import org.simantics.modeling.PropertyVariables;
54 import org.simantics.modeling.PropertyVariablesImpl;
55 import org.simantics.modeling.ui.diagram.monitor.MonitorClassFactory2;
56 import org.simantics.structural.stubs.StructuralResource2;
57 import org.simantics.ui.dnd.LocalObjectTransfer;
58 import org.simantics.ui.dnd.LocalObjectTransferable;
59 import org.simantics.ui.selection.WorkbenchSelectionElement;
60 import org.simantics.ui.selection.WorkbenchSelectionUtils;
61 import org.simantics.utils.datastructures.Triple;
62 import org.simantics.utils.datastructures.hints.IHintContext;
63 import org.simantics.utils.ui.ISelectionUtils;
64 import org.slf4j.Logger;
65 import org.slf4j.LoggerFactory;
67 import gnu.trove.set.hash.THashSet;
69 public class PopulateElementMonitorDropParticipant extends PopulateElementDropParticipant implements IDropTargetParticipant {
70 private static final Logger LOGGER = LoggerFactory.getLogger(PopulateElementMonitorDropParticipant.class);
72 private static final boolean DEBUG = false;
74 // Scale for the monitors
75 double scaleX, scaleY;
79 public PopulateElementMonitorDropParticipant(GraphToDiagramSynchronizer synchronizer, double scaleX, double scaleY) {
83 this.typeURI = DiagramResource.URIs.Monitor;
86 public PopulateElementMonitorDropParticipant(GraphToDiagramSynchronizer synchronizer, String typeURI, double scaleX, double scaleY) {
90 this.typeURI = typeURI;
94 public void dragEnter(DropTargetDragEvent dtde, final IDnDContext dp) {
96 Transferable tr = dtde.getTransferable();
98 if (tr.isDataFlavorSupported(LocalObjectTransferable.FLAVOR)) {
100 // This must be done to have SWT transfer set the source data
102 Object obj = tr.getTransferData(LocalObjectTransferable.FLAVOR);
104 System.out.println("GOT FROM AWT: " + obj);
107 if (!(obj instanceof IStructuredSelection)) {
108 obj = LocalObjectTransfer.getTransfer().getObject();
110 System.out.println("GOT FROM SWT: " + obj);
113 if (obj instanceof IStructuredSelection) {
115 IStructuredSelection sel = (IStructuredSelection) obj;
117 for(WorkbenchSelectionElement wse : WorkbenchSelectionUtils.getWorkbenchSelectionElements(sel)) {
118 dp.add(new WSEDragItem(wse));
121 Session session = synchronizer.getSession();
123 List<Variable> properties = resolveVariables(session, (IStructuredSelection) obj);
124 if (properties.isEmpty())
127 List<ElementClassDragItem> items = session.syncRequest(new ResolveItems(properties));
128 for (ElementClassDragItem item : items)
131 dp.getHints().setHint(DnDHints.KEY_DND_GRID_COLUMNS, Integer.valueOf(1));
134 } catch (UnsupportedFlavorException|IOException|DatabaseException e) {
135 LOGGER.error("dragEnter failed", e);
139 dtde.acceptDrag(DnDConstants.ACTION_COPY);
143 public void setHints(IHintContext context) {
146 protected List<Variable> resolveVariables(RequestProcessor processor, IStructuredSelection sel) throws DatabaseException {
148 return Collections.emptyList();
150 Variable property = WorkbenchSelectionUtils.getPossibleVariableFromSelection(processor, sel);
152 return Collections.singletonList(property);
154 property = ISelectionUtils.getSinglePossibleKey(sel, SelectionHints.KEY_SELECTION_PROPERTY, Variable.class);
155 if (property != null)
156 return Collections.singletonList(property);
158 final List<PropertyVariables> vars = ISelectionUtils.getPossibleKeys(sel, SelectionHints.KEY_MAIN, PropertyVariables.class);
159 if (!vars.isEmpty()) {
160 return processor.syncRequest(new UniqueRead<List<Variable>>() {
162 public List<Variable> perform(ReadGraph graph) throws DatabaseException {
163 // FIXME: this is a hack for indexed value support
164 List<PropertyVariables> vs = PropertyVariablesImpl.resolve(graph, vars);
165 List<Variable> result = new ArrayList<Variable>(vs.size());
166 for (PropertyVariables v : vs)
167 result.add(v.getVisualVariable());
173 return Collections.emptyList();
176 protected class ResolveItems extends UnaryRead<List<Variable>, List<ElementClassDragItem>> {
178 public ResolveItems(List<Variable> parameter) {
183 public List<ElementClassDragItem> perform(ReadGraph graph) throws DatabaseException {
184 List<ElementClassDragItem> result = new ArrayList<ElementClassDragItem>(parameter.size());
185 for (Variable property : parameter)
186 result.addAll( resolve(graph, property) );
190 public List<ElementClassDragItem> resolve(ReadGraph graph, Variable parameter) throws DatabaseException {
193 System.out.println("PARAM: " + parameter.getURI(graph));
194 Variable parent = parameter.browsePossible(graph, "..");
195 System.out.println("PARENT: " + parent.getURI(graph));
196 Resource parentComposite = parent.getPossibleRepresents(graph);
197 System.out.println("PARENT REPRESENTS: " + NameUtils.getSafeLabel(graph, parentComposite));
198 String prvi = Variables.getRVI(graph, parent);
199 System.out.println("PARENT RVI: " + prvi);
200 String parvi = Variables.getRVI(graph, parameter);
201 System.out.println("PARAM RVI: " + parvi);
204 Triple<Variable, Resource, IElement> match = findElementInDiagram(graph, parameter, false);
206 return Collections.emptyList();
208 if(match.third == null) {
209 // We are in a different diagram, prevent creation of monitors
210 // from UCs to different UCs or model configuration
211 Resource diagram = synchronizer.getDiagram().getHint(DiagramModelHints.KEY_DIAGRAM_RESOURCE);
212 Resource commonParent = findCommonParent(graph, diagram, match.second);
213 StructuralResource2 STR = StructuralResource2.getInstance(graph);
214 if(!graph.isInstanceOf(commonParent, STR.Composite))
215 return Collections.emptyList();
219 System.out.println("p=" + parameter.getURI(graph));
220 System.out.println("c=" + match.first.getURI(graph));
223 String rvi = Variables.getRVI(graph, match.first, parameter);
225 System.out.println("r=" + rvi);
227 Resource type = graph.getResource(typeURI);
229 ElementClassDragItem item = new ElementClassDragItem(MonitorClassFactory2.createMonitorClass(type, match.third, new HashMap<String, String>(), match.second, rvi, scaleX, scaleY));
230 item.getHintContext().setHint(ElementHints.KEY_HORIZONTAL_ALIGN, Alignment.LEADING);
232 if (match.third != null)
233 item.getHintContext().setHint(ElementHints.KEY_PARENT_ELEMENT, match.third);
235 AffineTransform initialTr = AffineTransform.getScaleInstance(scaleX, scaleY);
236 item.getHintContext().setHint(ElementHints.KEY_TRANSFORM, initialTr);
238 setHints(item.getHintContext());
240 return Collections.singletonList(item);
244 private Triple<Variable, Resource, IElement> findElementInDiagram(ReadGraph graph, Variable property, boolean propertyRoleFound) throws DatabaseException {
245 if (property == null)
249 System.out.println("findElementInDiagram " + property.getURI(graph) + " " + property);
251 DiagramResource DIA = DiagramResource.getInstance(graph);
252 ModelingResources MOD = ModelingResources.getInstance(graph);
253 final Resource diagram = synchronizer.getDiagram().getHint(DiagramModelHints.KEY_DIAGRAM_RESOURCE);
255 if (!propertyRoleFound) {
256 Role role = property.getPossibleRole(graph);
257 propertyRoleFound = role == Role.PROPERTY;
260 Resource represents = property.getPossibleRepresents(graph);
261 if (represents != null) {
263 System.out.println("represents " + NameUtils.getSafeName(graph, represents, true));
264 Resource elementResource = graph.getPossibleObject(represents, MOD.ComponentToElement);
265 // There must have be at least one
266 // PROPERTY role variable in the
267 // browsed path before finding this
269 if(elementResource != null && propertyRoleFound) {
270 Resource elementDiagram = OrderedSetUtils.getSingleOwnerList(graph, elementResource, DIA.Diagram);
271 if(diagram.equals(elementDiagram)) {
272 final DataElementMap map = synchronizer.getDiagram().getDiagramClass().getSingleItem(DataElementMap.class);
273 IElement parentElement = map.getElement(synchronizer.getDiagram(), elementResource);
275 if (graph.isInstanceOf(elementResource, DIA.Connection)) {
276 Resource tailNode = ConnectionUtil.getConnectionTailNode(graph, elementResource);
277 if (tailNode != null) {
278 IElement tailNodeElement = map.getElement(synchronizer.getDiagram(), tailNode);
279 if (tailNodeElement != null)
280 parentElement = tailNodeElement;
284 return Triple.make(property, represents, parentElement);
286 // The monitored target module is on another diagram/composite.
287 // No parent for the monitor then.
288 return Triple.make(property, represents, null);
293 return findElementInDiagram(graph, property.browsePossible(graph, "."), propertyRoleFound);
298 private static Resource findCommonParent(ReadGraph graph, Resource a, Resource b) throws DatabaseException {
299 Layer0 L0 = Layer0.getInstance(graph);
300 THashSet<Resource> set = new THashSet<>();
305 a = graph.getPossibleObject(a, L0.PartOf);
308 return graph.getRootLibrary();
312 b = graph.getPossibleObject(a, L0.PartOf);
318 public double getPriority() {