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