/******************************************************************************* * 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.g2d.diagram.handler.impl; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import org.simantics.g2d.connection.EndKeyOf; import org.simantics.g2d.connection.TerminalKeyOf; import org.simantics.g2d.diagram.IDiagram; import org.simantics.g2d.diagram.handler.ElementListener; import org.simantics.g2d.diagram.handler.SubstituteElement; import org.simantics.g2d.diagram.handler.Topology; import org.simantics.g2d.element.ElementHints; import org.simantics.g2d.element.ElementUtils; import org.simantics.g2d.element.IElement; import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd; import org.simantics.utils.datastructures.hints.IHintContext.Key; /** * * @author Toni Kalajainen */ public class TopologyImpl implements Topology, ElementListener { @Override public Connection getConnection(IElement edge, EdgeEnd end) { Key key = EndKeyOf.get(end); Connection c = edge.getHint(key); if (c == null) return null; IDiagram d = ElementUtils.getDiagram(edge); c = _updateReferences(d, c); return c; } @Override public void getConnections(IElement node, Terminal terminal, Collection connections) { // FIXME: only allows single connection / terminal Key key = new TerminalKeyOf(terminal, null, Connection.class); Connection c = node.getHint(key); if (c != null) { connections.add(c); } IDiagram d = ElementUtils.getDiagram(node); _updateReferences(d, c); } private Connection _updateReferences(IDiagram d, Connection c) { List list = d.getDiagramClass().getItemsByClass(SubstituteElement.class); if (list.size()==0) return c; IElement e = c.edge; IElement n = c.node; for (SubstituteElement se : list) { IElement ne = se.substitute(d, e); IElement nn = se.substitute(d, n); if (ne != null) e = ne; if (nn != null) n = nn; } return new Connection(e, c.end, n, c.terminal); } @Override public void connect(IElement edge, EdgeEnd end, IElement node, Terminal terminal) { if (edge == null) throw new NullPointerException("null edge"); if (end == null) throw new NullPointerException("null end"); if (node == null) throw new NullPointerException("null node"); if (terminal == null) throw new NullPointerException("null terminal"); IDiagram d = ElementUtils.getDiagram(edge); assert( d == ElementUtils.getDiagram(node) ); Connection c = new Connection(edge, end, node, terminal); // It is not the job of this code to check or resolve modelling issues // caused by this connection. // This makes it possible to have more than one connection to the same // terminal. Object edgeData = edge.getHint(ElementHints.KEY_OBJECT); TerminalKeyOf key = new TerminalKeyOf(terminal, edgeData, Connection.class); node.setHint(key, c); EndKeyOf key2 = EndKeyOf.get(end); edge.setHint(key2, c); } @Override public void disconnect(IElement edge, EdgeEnd end, IElement node, Terminal terminal) { if (edge == null) throw new NullPointerException("null edge"); if (end == null) throw new NullPointerException("null end"); if (node == null) throw new NullPointerException("null node"); if (terminal == null) throw new NullPointerException("null terminal"); IDiagram d = ElementUtils.getDiagram(edge); assert( d == ElementUtils.getDiagram(node) ); EndKeyOf edgeKey = EndKeyOf.get(end); Connection c = edge.getHint(edgeKey); if (c == null) throw new UnsupportedOperationException("cannot disconnect, no Connection in edge " + edge); for (Map.Entry entry : node.getHintsOfClass(TerminalKeyOf.class).entrySet()) { Connection cc = (Connection) entry.getValue(); if (c == cc) { node.removeHint(entry.getKey()); edge.removeHint(edgeKey); return; } } throw new UnsupportedOperationException("cannot disconnect, no connection between found between edge " + edge + " and node " + node); } @Override public void onElementAdded(IDiagram d, IElement e) { } @Override public void onElementRemoved(IDiagram d, IElement e) { Set keys1 = e.getHintsOfClass(TerminalKeyOf.class).keySet(); for (TerminalKeyOf key : keys1) e.removeHint(key); for (EndKeyOf key : EndKeyOf.KEYS) e.removeHint(key); } }