/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.modeling.ui.symbolEditor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.dnd.DnDConstants; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.geom.Point2D; import java.io.IOException; import java.util.HashSet; import java.util.Set; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.Session; import org.simantics.db.WriteGraph; import org.simantics.db.common.request.ObjectsWithType; import org.simantics.db.exception.DatabaseException; import org.simantics.db.request.Read; import org.simantics.diagram.adapter.GraphToDiagramSynchronizer; import org.simantics.diagram.stubs.DiagramResource; import org.simantics.diagram.synchronization.graph.DiagramGraphUtil; import org.simantics.diagram.synchronization.graph.ElementWriter; import org.simantics.diagram.ui.DiagramModelHints; import org.simantics.g2d.diagram.DiagramHints; import org.simantics.g2d.diagram.DiagramMutator; import org.simantics.g2d.diagram.DiagramUtils; import org.simantics.g2d.diagram.IDiagram; import org.simantics.g2d.diagram.participant.AbstractDiagramParticipant; import org.simantics.g2d.dnd.DnDHints; import org.simantics.g2d.dnd.ElementClassDragItem; import org.simantics.g2d.dnd.IDnDContext; import org.simantics.g2d.dnd.IDragItem; import org.simantics.g2d.dnd.IDropTargetParticipant; import org.simantics.g2d.element.ElementClass; import org.simantics.g2d.element.ElementUtils; import org.simantics.g2d.element.IElement; import org.simantics.layer0.Layer0; import org.simantics.modeling.ModelingResources; import org.simantics.modeling.symbolEditor.PopulateTerminal; import org.simantics.structural.stubs.StructuralResource2; import org.simantics.ui.dnd.LocalObjectTransfer; import org.simantics.ui.dnd.LocalObjectTransferable; import org.simantics.ui.utils.ResourceAdaptionUtils; import org.simantics.utils.datastructures.Callback; import org.simantics.utils.datastructures.hints.IHintContext.Key; import org.simantics.utils.datastructures.hints.IHintContext.KeyOf; import org.simantics.utils.logging.TimeLogger; import org.simantics.utils.ui.ErrorLogger; /** * @author Tuukka Lehtonen */ public class PopulateTerminalDropParticipant extends AbstractDiagramParticipant implements IDropTargetParticipant { private static final Key KEY_TERMINAL_RELATION = new KeyOf(Resource.class, "TERMINAL_RELATION"); protected GraphToDiagramSynchronizer synchronizer; protected Resource symbolDiagram; public PopulateTerminalDropParticipant(Resource symbolDiagram, GraphToDiagramSynchronizer synchronizer) { this.symbolDiagram = symbolDiagram; this.synchronizer = synchronizer; } @Override public void dragEnter(final DropTargetDragEvent dtde, final IDnDContext dp) { Transferable tr = dtde.getTransferable(); if (tr.isDataFlavorSupported(LocalObjectTransferable.FLAVOR)) { Session session = synchronizer.getSession(); try { tr.getTransferData(LocalObjectTransferable.FLAVOR); final Resource[] resources = ResourceAdaptionUtils.toResources(LocalObjectTransfer.getTransfer() .getObject()); int itemsAdded = session.syncRequest(new Read() { @Override public Integer perform(ReadGraph g) throws DatabaseException { int items = 0; Layer0 L0 = Layer0.getInstance(g); DiagramResource DIA = DiagramResource.getInstance(g); StructuralResource2 STR = StructuralResource2.getInstance(g); ModelingResources MOD = ModelingResources.getInstance(g); Resource symbol = g.getPossibleObject(symbolDiagram, STR.Defines); if (symbol == null) return 0; Resource componentType = g.getPossibleObject(symbol, MOD.SymbolToComponentType); if (componentType == null) return 0; Set connectionRelationsOfSymbol = new HashSet( g.syncRequest(new ObjectsWithType(componentType, L0.ConsistsOf, STR.ConnectionRelation)) ); // System.out.println("Symbol: " + NameUtils.getURIOrSafeNameInternal(g, symbolDiagram)); // System.out.println("Component type: " + NameUtils.getURIOrSafeNameInternal(g, componentType)); // System.out.println("Connection relations: " + connectionRelationsOfSymbol); Set usedConnectionRelations = new HashSet(); for (Resource terminal : g.syncRequest(new ObjectsWithType(symbolDiagram, L0.ConsistsOf, DIA.Terminal))) { Resource binds = DiagramGraphUtil.getPossibleConnectionPointOfTerminal(g, terminal); if(binds != null) for (Resource connRel : g.getObjects(binds, MOD.DiagramConnectionRelationToConnectionRelation)) usedConnectionRelations.add(connRel); } for (Resource resource : resources) { //System.out.println("Name: " + NameUtils.getSafeName(g, resource)); IDragItem di = null; Resource connectionRelation = null; if (g.isInstanceOf(resource, STR.ConnectionRelation)) { if (!connectionRelationsOfSymbol.contains(resource)) continue; Resource terminal = g.getPossibleObject(resource, MOD.ConnectionRelationToTerminal); if (terminal == null) terminal = MOD.TestTerminal; di = new ElementClassDragItem(synchronizer.getNodeClass(g, terminal)); connectionRelation = resource; } /* TODO should we replace this with something? else if (g.isInstanceOf(resource, STR.ConnectionPointDefinition)) { Resource connectionType = g.getPossibleObject(resource, STR.HasConnectionType); Resource connectionDirection = g.getPossibleObject(resource, STR.HasConnectionDirection); Collection terminals = connectionType == null || connectionDirection == null ? Collections. emptyList() : g.getObjects(connectionType, g.getInverse(STR.SupportsConnectionType)); if (terminals.isEmpty()) di = new ElementClassDragItem(synchronizer.getNodeClass(g, MOD.TestTerminal)); else for (Resource t : terminals) if (connectionDirection.equals(g.getPossibleObject(t, STR.SupportsDirection))) { di = new ElementClassDragItem(synchronizer.getNodeClass(t)); break; } connectionRelation = g.getSingleObject(resource, L0.ConcernsRelation); }*/ if (di != null && connectionRelation != null && !usedConnectionRelations.contains(connectionRelation)) { di.getHintContext().setHint(KEY_TERMINAL_RELATION, connectionRelation); dp.add( di ); ++items; } } return items; } }); if (itemsAdded > 0 ) { dp.getHints().setHint(DnDHints.KEY_DND_GRID_COLUMNS, Integer.valueOf(1)); dtde.acceptDrag(DnDConstants.ACTION_COPY); } } catch (DatabaseException e) { ErrorLogger.defaultLogError(e); } catch (UnsupportedFlavorException e) { ErrorLogger.defaultLogError(e); } catch (IOException e) { ErrorLogger.defaultLogError(e); } catch (IllegalArgumentException e) { ErrorLogger.defaultLogError(e); } } } @Override public void dragExit(DropTargetEvent dte, IDnDContext dp) { // System.out.println("exit"); } @Override public void dragOver(DropTargetDragEvent dtde, IDnDContext dp) { // System.out.println("over"); } @Override public void drop(DropTargetDropEvent dtde, final IDnDContext dp) { TimeLogger.resetTimeAndLog(getClass(), "drop"); final IDiagram d = getHint(DiagramHints.KEY_DIAGRAM); if (d == null) return; DiagramUtils.mutateDiagram(d, mutator -> { IDragItem items[] = dp.toArray(); for (IDragItem i : items) { if (!(i instanceof ElementClassDragItem)) continue; final Resource relation = i.getHintContext().getHint(KEY_TERMINAL_RELATION); if (relation == null) continue; ElementClassDragItem res = (ElementClassDragItem) i; ElementClass ec = res.getElementClass(); Point2D pos = dp.getItemPosition(i); // System.out.println(pos); assert (pos != null); IElement element = mutator.newElement(ec); ElementUtils.setPos(element, new Point2D.Double(pos.getX(), pos.getY())); element.setHint(DiagramModelHints.KEY_ELEMENT_WRITER, new ElementWriter() { @Override public void addToGraph(WriteGraph g, IElement element, Resource terminal) throws DatabaseException { PopulateTerminal.addToGraph(g, symbolDiagram, relation, terminal); } @Override public void removeFromGraph(WriteGraph graph, Resource elementResource) { } }); dp.remove(i); } }); getContext().getContentContext().setDirty(); } @Override public void dropActionChanged(DropTargetDragEvent dtde, IDnDContext dp) { dtde.acceptDrag(DnDConstants.ACTION_COPY); } @Override public int getAllowedOps() { return DnDConstants.ACTION_COPY | DnDConstants.ACTION_MOVE | DnDConstants.ACTION_LINK; } @Override public double getPriority() { return 9.0; } }