--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.modeling.ui.diagramEditor;\r
+\r
+import gnu.trove.set.hash.THashSet;\r
+\r
+import java.awt.datatransfer.Transferable;\r
+import java.awt.datatransfer.UnsupportedFlavorException;\r
+import java.awt.dnd.DnDConstants;\r
+import java.awt.dnd.DropTargetDragEvent;\r
+import java.awt.geom.AffineTransform;\r
+import java.io.IOException;\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.simantics.Logger;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.RequestProcessor;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.common.request.UnaryRead;\r
+import org.simantics.db.common.request.UniqueRead;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.common.utils.OrderedSetUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.SelectionHints;\r
+import org.simantics.db.layer0.variable.Variable;\r
+import org.simantics.db.layer0.variable.Variables;\r
+import org.simantics.db.layer0.variable.Variables.Role;\r
+import org.simantics.diagram.adapter.GraphToDiagramSynchronizer;\r
+import org.simantics.diagram.content.ConnectionUtil;\r
+import org.simantics.diagram.stubs.DiagramResource;\r
+import org.simantics.diagram.ui.DiagramModelHints;\r
+import org.simantics.g2d.diagram.handler.DataElementMap;\r
+import org.simantics.g2d.dnd.DnDHints;\r
+import org.simantics.g2d.dnd.ElementClassDragItem;\r
+import org.simantics.g2d.dnd.IDnDContext;\r
+import org.simantics.g2d.dnd.IDropTargetParticipant;\r
+import org.simantics.g2d.element.ElementHints;\r
+import org.simantics.g2d.element.IElement;\r
+import org.simantics.g2d.utils.Alignment;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.modeling.ModelingResources;\r
+import org.simantics.modeling.PropertyVariables;\r
+import org.simantics.modeling.PropertyVariablesImpl;\r
+import org.simantics.modeling.ui.diagram.monitor.MonitorClassFactory2;\r
+import org.simantics.structural.stubs.StructuralResource2;\r
+import org.simantics.ui.dnd.LocalObjectTransfer;\r
+import org.simantics.ui.dnd.LocalObjectTransferable;\r
+import org.simantics.ui.selection.WorkbenchSelectionElement;\r
+import org.simantics.ui.selection.WorkbenchSelectionUtils;\r
+import org.simantics.utils.datastructures.Triple;\r
+import org.simantics.utils.datastructures.hints.IHintContext;\r
+import org.simantics.utils.ui.ISelectionUtils;\r
+\r
+public class PopulateElementMonitorDropParticipant extends PopulateElementDropParticipant implements IDropTargetParticipant {\r
+\r
+ private static final boolean DEBUG = false;\r
+\r
+ // Scale for the monitors\r
+ double scaleX, scaleY;\r
+ // Monitor type\r
+ String typeURI;\r
+\r
+ public PopulateElementMonitorDropParticipant(GraphToDiagramSynchronizer synchronizer, double scaleX, double scaleY) {\r
+ super(synchronizer);\r
+ this.scaleX = scaleX;\r
+ this.scaleY = scaleY;\r
+ this.typeURI = DiagramResource.URIs.Monitor;\r
+ }\r
+\r
+ public PopulateElementMonitorDropParticipant(GraphToDiagramSynchronizer synchronizer, String typeURI, double scaleX, double scaleY) {\r
+ super(synchronizer);\r
+ this.scaleX = scaleX;\r
+ this.scaleY = scaleY;\r
+ this.typeURI = typeURI;\r
+ }\r
+\r
+ @Override\r
+ public void dragEnter(DropTargetDragEvent dtde, final IDnDContext dp) {\r
+\r
+ Transferable tr = dtde.getTransferable();\r
+\r
+ if (tr.isDataFlavorSupported(LocalObjectTransferable.FLAVOR)) {\r
+\r
+ // This must be done to have SWT transfer set the source data\r
+ try {\r
+ Object obj = tr.getTransferData(LocalObjectTransferable.FLAVOR);\r
+ if (DEBUG)\r
+ System.out.println("GOT FROM AWT: " + obj);\r
+\r
+ // Check SWT\r
+ if (!(obj instanceof IStructuredSelection)) {\r
+ obj = LocalObjectTransfer.getTransfer().getObject();\r
+ if (DEBUG)\r
+ System.out.println("GOT FROM SWT: " + obj);\r
+ }\r
+\r
+ if (obj instanceof IStructuredSelection) {\r
+ \r
+ IStructuredSelection sel = (IStructuredSelection) obj;\r
+ \r
+ for(WorkbenchSelectionElement wse : WorkbenchSelectionUtils.getWorkbenchSelectionElements(sel)) {\r
+ dp.add(new WSEDragItem(wse));\r
+ }\r
+\r
+ Session session = synchronizer.getSession();\r
+\r
+ List<Variable> properties = resolveVariables(session, (IStructuredSelection) obj);\r
+ if (properties.isEmpty())\r
+ return;\r
+\r
+ List<ElementClassDragItem> items = session.syncRequest(new ResolveItems(properties));\r
+ for (ElementClassDragItem item : items)\r
+ dp.add(item);\r
+\r
+ dp.getHints().setHint(DnDHints.KEY_DND_GRID_COLUMNS, Integer.valueOf(1));\r
+ }\r
+\r
+ } catch (UnsupportedFlavorException e) {\r
+ Logger.defaultLogError(e);\r
+ } catch (IOException e) {\r
+ Logger.defaultLogError(e);\r
+ } catch (DatabaseException e) {\r
+ Logger.defaultLogError(e);\r
+ }\r
+\r
+ }\r
+\r
+ dtde.acceptDrag(DnDConstants.ACTION_COPY);\r
+\r
+ }\r
+\r
+ public void setHints(IHintContext context) {\r
+ }\r
+\r
+ protected List<Variable> resolveVariables(RequestProcessor processor, IStructuredSelection sel) throws DatabaseException {\r
+ if (sel.isEmpty())\r
+ return Collections.emptyList();\r
+\r
+ Variable property = WorkbenchSelectionUtils.getPossibleVariable(sel);\r
+ if(property != null)\r
+ return Collections.singletonList(property);\r
+\r
+ property = ISelectionUtils.getSinglePossibleKey(sel, SelectionHints.KEY_SELECTION_PROPERTY, Variable.class);\r
+ if (property != null)\r
+ return Collections.singletonList(property);\r
+\r
+ final List<PropertyVariables> vars = ISelectionUtils.getPossibleKeys(sel, SelectionHints.KEY_MAIN, PropertyVariables.class);\r
+ if (!vars.isEmpty()) {\r
+ return processor.syncRequest(new UniqueRead<List<Variable>>() {\r
+ @Override\r
+ public List<Variable> perform(ReadGraph graph) throws DatabaseException {\r
+ // FIXME: this is a hack for indexed value support\r
+ List<PropertyVariables> vs = PropertyVariablesImpl.resolve(graph, vars);\r
+ List<Variable> result = new ArrayList<Variable>(vs.size());\r
+ for (PropertyVariables v : vs)\r
+ result.add(v.getVisualVariable());\r
+ return result;\r
+ }\r
+ });\r
+ }\r
+\r
+ return Collections.emptyList();\r
+ }\r
+\r
+ protected class ResolveItems extends UnaryRead<List<Variable>, List<ElementClassDragItem>> {\r
+\r
+ public ResolveItems(List<Variable> parameter) {\r
+ super(parameter);\r
+ }\r
+\r
+ @Override\r
+ public List<ElementClassDragItem> perform(ReadGraph graph) throws DatabaseException {\r
+ List<ElementClassDragItem> result = new ArrayList<ElementClassDragItem>(parameter.size());\r
+ for (Variable property : parameter)\r
+ result.addAll( resolve(graph, property) );\r
+ return result;\r
+ }\r
+\r
+ public List<ElementClassDragItem> resolve(ReadGraph graph, Variable parameter) throws DatabaseException {\r
+\r
+ if (DEBUG) {\r
+ System.out.println("PARAM: " + parameter.getURI(graph));\r
+ Variable parent = parameter.browsePossible(graph, "..");\r
+ System.out.println("PARENT: " + parent.getURI(graph));\r
+ Resource parentComposite = parent.getPossibleRepresents(graph);\r
+ System.out.println("PARENT REPRESENTS: " + NameUtils.getSafeLabel(graph, parentComposite));\r
+ String prvi = Variables.getRVI(graph, parent);\r
+ System.out.println("PARENT RVI: " + prvi);\r
+ String parvi = Variables.getRVI(graph, parameter);\r
+ System.out.println("PARAM RVI: " + parvi);\r
+ }\r
+\r
+ Triple<Variable, Resource, IElement> match = findElementInDiagram(graph, parameter, false);\r
+ if (match == null)\r
+ return Collections.emptyList();\r
+ \r
+ if(match.third == null) {\r
+ // We are in a different diagram, prevent creation of monitors\r
+ // from UCs to different UCs or model configuration\r
+ Resource diagram = synchronizer.getDiagram().getHint(DiagramModelHints.KEY_DIAGRAM_RESOURCE);\r
+ Resource commonParent = findCommonParent(graph, diagram, match.second);\r
+ StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
+ if(!graph.isInstanceOf(commonParent, STR.Composite))\r
+ return Collections.emptyList();\r
+ }\r
+\r
+ if (DEBUG) {\r
+ System.out.println("p=" + parameter.getURI(graph));\r
+ System.out.println("c=" + match.first.getURI(graph));\r
+ }\r
+\r
+ String rvi = Variables.getRVI(graph, match.first, parameter);\r
+ if (DEBUG)\r
+ System.out.println("r=" + rvi);\r
+\r
+ Resource type = graph.getResource(typeURI);\r
+\r
+ ElementClassDragItem item = new ElementClassDragItem(MonitorClassFactory2.createMonitorClass(type, match.third, new HashMap<String, String>(), match.second, rvi, scaleX, scaleY));\r
+ item.getHintContext().setHint(ElementHints.KEY_HORIZONTAL_ALIGN, Alignment.LEADING);\r
+\r
+ if (match.third != null)\r
+ item.getHintContext().setHint(ElementHints.KEY_PARENT_ELEMENT, match.third);\r
+\r
+ AffineTransform initialTr = AffineTransform.getScaleInstance(scaleX, scaleY);\r
+ item.getHintContext().setHint(ElementHints.KEY_TRANSFORM, initialTr);\r
+\r
+ setHints(item.getHintContext());\r
+\r
+ return Collections.singletonList(item);\r
+\r
+ }\r
+\r
+ private Triple<Variable, Resource, IElement> findElementInDiagram(ReadGraph graph, Variable property, boolean propertyRoleFound) throws DatabaseException {\r
+ if (property == null)\r
+ return null;\r
+\r
+ if (DEBUG)\r
+ System.out.println("findElementInDiagram " + property.getURI(graph) + " " + property);\r
+\r
+ DiagramResource DIA = DiagramResource.getInstance(graph);\r
+ ModelingResources MOD = ModelingResources.getInstance(graph);\r
+ final Resource diagram = synchronizer.getDiagram().getHint(DiagramModelHints.KEY_DIAGRAM_RESOURCE);\r
+\r
+ if (!propertyRoleFound) {\r
+ Role role = property.getPossibleRole(graph);\r
+ propertyRoleFound = role == Role.PROPERTY;\r
+ }\r
+\r
+ Resource represents = property.getPossibleRepresents(graph);\r
+ if (represents != null) {\r
+ if (DEBUG)\r
+ System.out.println("represents " + NameUtils.getSafeName(graph, represents, true));\r
+ Resource elementResource = graph.getPossibleObject(represents, MOD.ComponentToElement);\r
+ // There must have be at least one\r
+ // PROPERTY role variable in the\r
+ // browsed path before finding this\r
+ // element.\r
+ if(elementResource != null && propertyRoleFound) {\r
+ Resource elementDiagram = OrderedSetUtils.getSingleOwnerList(graph, elementResource, DIA.Diagram);\r
+ if(diagram.equals(elementDiagram)) {\r
+ final DataElementMap map = synchronizer.getDiagram().getDiagramClass().getSingleItem(DataElementMap.class);\r
+ IElement parentElement = map.getElement(synchronizer.getDiagram(), elementResource);\r
+\r
+ if (graph.isInstanceOf(elementResource, DIA.Connection)) {\r
+ Resource tailNode = ConnectionUtil.getConnectionTailNode(graph, elementResource);\r
+ if (tailNode != null) {\r
+ IElement tailNodeElement = map.getElement(synchronizer.getDiagram(), tailNode);\r
+ if (tailNodeElement != null)\r
+ parentElement = tailNodeElement;\r
+ }\r
+ }\r
+\r
+ return Triple.make(property, represents, parentElement);\r
+ } else {\r
+ // The monitored target module is on another diagram/composite.\r
+ // No parent for the monitor then.\r
+ return Triple.make(property, represents, null);\r
+ }\r
+ }\r
+ }\r
+\r
+ return findElementInDiagram(graph, property.browsePossible(graph, "."), propertyRoleFound);\r
+ }\r
+\r
+ }\r
+\r
+ private static Resource findCommonParent(ReadGraph graph, Resource a, Resource b) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ THashSet<Resource> set = new THashSet<>();\r
+ while(true) {\r
+ if(a != null) {\r
+ if(!set.add(a))\r
+ return a;\r
+ a = graph.getPossibleObject(a, L0.PartOf);\r
+ }\r
+ else if(b == null)\r
+ return graph.getRootLibrary();\r
+ if(b != null) {\r
+ if(!set.add(b))\r
+ return b;\r
+ b = graph.getPossibleObject(a, L0.PartOf);\r
+ }\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public double getPriority() {\r
+ return 9.0;\r
+ }\r
+ \r
+}
\ No newline at end of file