Package org.eclipse.sapphire.ui.swt.gef

Source Code of org.eclipse.sapphire.ui.swt.gef.SapphireConnectionRouter

/******************************************************************************
* Copyright (c) 2014 Oracle
* 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:
*    Ling Hao - initial implementation and ongoing maintenance
******************************************************************************/

package org.eclipse.sapphire.ui.swt.gef;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Set;

import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.draw2d.geometry.PrecisionPoint;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.draw2d.geometry.Vector;
import org.eclipse.sapphire.ui.Bounds;
import org.eclipse.sapphire.ui.swt.gef.model.DiagramConnectionModel;
import org.eclipse.sapphire.ui.swt.gef.model.DiagramNodeModel;
import org.eclipse.sapphire.ui.swt.gef.utils.MultiValueMap;

/**
* @author <a href="mailto:ling.hao@oracle.com">Ling Hao</a>
*/

public class SapphireConnectionRouter
{
  private MultiValueMap<HashKey,DiagramConnectionModel> connections = new MultiValueMap<HashKey,DiagramConnectionModel>();
  private MultiValueMap<HashKey,Integer> connectionIndices = new MultiValueMap<HashKey,Integer>();
  private HashMap<DiagramConnectionModel, Integer> connectionIndexMap =
          new HashMap<DiagramConnectionModel, Integer>();
  private int separation = 30;
 
  private static final class HashKey
  {
    private DiagramNodeModel sourceNode, targetNode;

    HashKey(DiagramConnectionModel conn)
    {
      sourceNode = conn.getSourceNode();
      targetNode = conn.getTargetNode();
    }

    public boolean equals(Object object)
    {
      boolean isEqual = false;
      HashKey hashKey;

      if (object instanceof HashKey)
      {
        hashKey = (HashKey) object;
        DiagramNodeModel hkA1 = hashKey.getFirstNode();
        DiagramNodeModel hkA2 = hashKey.getSecondNode();

        isEqual = (hkA1.equals(sourceNode) && hkA2.equals(targetNode))
            || (hkA1.equals(targetNode) && hkA2.equals(sourceNode));
      }
      return isEqual;
    }

    public DiagramNodeModel getFirstNode()
    {
      return sourceNode;
    }

    public DiagramNodeModel getSecondNode()
    {
      return targetNode;
    }

    public int hashCode()
    {
      return sourceNode.hashCode() ^ targetNode.hashCode();
    }
  }
 

  public SapphireConnectionRouter() {}
   
  public int getSeparation()
  {
    return separation;
  }
 
  public void setSeparation(int value)
  {
    separation = value;
  }
 
  public void removeConnectionFromCache(DiagramConnectionModel conn)
  {
    HashKey connectionKey = new HashKey(conn);
    connections.remove(connectionKey, conn);
    if (connectionIndexMap.containsKey(conn))
    {
      int index = connectionIndexMap.get(conn);
      connectionIndices.remove(connectionKey, index);
    }
  }
 
  public void clear()
  {
    this.connectionIndexMap.clear();
    this.connections.clear();
    this.connectionIndices.clear();
  }
 
  private Point getNodeLocation(DiagramNodeModel node)
  {
    Bounds bounds = node.getNodeBounds();
    if (node.getShapePresentation().getFigure() != null)
    {
      Rectangle rect = node.getShapePresentation().getFigure().getBounds();
      int x = rect.x != -1 ? rect.x : bounds.getX();
      int y = rect.y != -1 ? rect.y : bounds.getY();
      return new Point(x + rect.width / 2, y + rect.height / 2);
    }
    else
    {         
      return new Point(bounds.getX() + bounds.getWidth() /2, bounds.getY() + bounds.getWidth() / 2);
    }
  }
 
  public Point route(DiagramConnectionModel conn)
  {   
    final HashKey connectionKey = new HashKey(conn);

    if( this.connections.containsKey( connectionKey ) )
    {
      PointList points = new PointList();
      points.addPoint(getNodeLocation(conn.getSourceNode()));
      points.addPoint(getNodeLocation(conn.getTargetNode()));

      int index  = getNextConnectionIndex(connectionKey);
      addConnectionKey(conn, connectionKey, index);

      Point bendpoint = handleCollision(points, index);
      return bendpoint;
    }
    else
    {
      addConnectionKey(conn, connectionKey, -1);
    }
   
    return null;
  }
 
  public void addConnection(DiagramConnectionModel conn)
  {
    HashKey connectionKey = new HashKey(conn);
    addConnectionKey(conn, connectionKey, -1);
  }
 
  private void addConnectionKey(DiagramConnectionModel conn, HashKey connectionKey, int index)
  {
    connections.put(connectionKey, conn);
    connectionIndices.put(connectionKey, index);
    connectionIndexMap.put(conn, index);   
  }
 
  private Point handleCollision(PointList points, int index)
  {
    PrecisionPoint start = new PrecisionPoint( points.getFirstPoint() );
    PrecisionPoint end = new PrecisionPoint( points.getLastPoint() );

    if (start.equals(end))
      return null;

    Point midPoint = new Point((end.x + start.x) / 2, (end.y + start.y) / 2);
    int position = end.getPosition(start);
    Vector vector;
    if (position == PositionConstants.SOUTH
        || position == PositionConstants.EAST)
      vector = new Vector(start, end);
    else
      vector = new Vector(end, start);
    double length = vector.getLength();

    double xSeparation = getSeparation() * vector.x / length;
    double ySeparation = getSeparation() * vector.y / length;

    Point bendPoint;

    if (index % 2 == 0)
    {
      bendPoint = new Point
      (
        (int) ( midPoint.x + ( (double) index / 2 ) * ( -1 * ySeparation ) ),
        (int) ( midPoint.y + ( (double) index / 2 ) * xSeparation )
      );
    }
    else
    {
      bendPoint = new Point
      (
          (int) ( midPoint.x + ( (double) index / 2 ) * ySeparation ),
          (int) ( midPoint.y + ( (double) index / 2 ) * ( -1 * xSeparation ) )
      );
    }
    if (!bendPoint.equals(midPoint)) {
      return bendPoint;
    }
   
    return null;
  }
 
  private int getNextConnectionIndex(HashKey connectionKey)
  {
    final Set<Integer> indices = connectionIndices.get(connectionKey);
    int[] intArr = new int[indices.size()];
    int i = 0;
    for (Object obj : indices)
    {
      Integer intObj = (Integer)obj;
      intArr[i++] = intObj;
    }
    Arrays.sort(intArr, 0, indices.size());
   
    int nextInt = -1;
    for (int j = 0; j < intArr.length; j++)
    {
      int temp = intArr[j];
      if (temp > 1 && temp != j + 1)
      {
        nextInt = j + 1;
        break;
      }
    }
    if (nextInt == -1)
    {
      nextInt = indices.size() + 1;
    }
    return nextInt;
  }

}
TOP

Related Classes of org.eclipse.sapphire.ui.swt.gef.SapphireConnectionRouter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.