/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.transformation.ui.connection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.geometry.Dimension;
import org.teiid.designer.diagram.ui.connection.AnchorManager;
import org.teiid.designer.diagram.ui.connection.NodeConnectionAnchor;
import org.teiid.designer.diagram.ui.connection.NodeConnectionEditPart;
import org.teiid.designer.diagram.ui.model.DiagramModelNode;
import org.teiid.designer.diagram.ui.part.DiagramEditPart;
/**
* AnchorManager
*
* @since 8.0
*/
public class TransformationAnchorManager implements AnchorManager {
private List northAnchors;
private List southAnchors;
private List eastAnchors;
private List westAnchors;
private DiagramEditPart diagramEditPart;
/**
* Construct an instance of AnchorManager.
*
*/
public TransformationAnchorManager(DiagramEditPart diagramEditPart) {
this.diagramEditPart = diagramEditPart;
init();
}
private void init() {
}
/**
* @return
*/
private List getEastAnchors() {
return eastAnchors;
}
/**
* @return
*/
private List getNorthAnchors() {
return northAnchors;
}
/**
* @return
*/
private List getSouthAnchors() {
return southAnchors;
}
/**
* @return
*/
private List getWestAnchors() {
return westAnchors;
}
/**
* @param newAnchor
*/
private boolean addEastAnchor(NodeConnectionAnchor newAnchor) {
if( eastAnchors == null )
eastAnchors = new ArrayList(1);
if( !eastAnchors.contains(newAnchor)) {
eastAnchors.add(newAnchor);
return true;
}
return false;
}
/**
* @param newAnchor
*/
private boolean addNorthAnchor(NodeConnectionAnchor newAnchor) {
if( northAnchors == null )
northAnchors = new ArrayList(1);
if( !northAnchors.contains(newAnchor)) {
northAnchors.add(newAnchor);
return true;
}
return false;
}
/**
* @param newAnchor
*/
private boolean addSouthAnchor(NodeConnectionAnchor newAnchor) {
if( southAnchors == null )
southAnchors = new ArrayList(1);
if( !southAnchors.contains(newAnchor)) {
southAnchors.add(newAnchor);
return true;
}
return false;
}
/**
* @param newAnchor
*/
private boolean addWestAnchor(NodeConnectionAnchor newAnchor) {
if( westAnchors == null )
westAnchors = new ArrayList(1);
if( !westAnchors.contains(newAnchor)) {
westAnchors.add(newAnchor);
return true;
}
return false;
}
@Override
public boolean add(NodeConnectionAnchor targetAnchor) {
boolean added = false;
if( targetAnchor.getDirection() == NORTH ) {
added = addNorthAnchor(targetAnchor);
} else if( targetAnchor.getDirection() == SOUTH ) {
added = addSouthAnchor(targetAnchor);
} else if( targetAnchor.getDirection() == EAST ) {
added = addEastAnchor(targetAnchor);
} else if( targetAnchor.getDirection() == WEST ) {
added = addWestAnchor(targetAnchor);
}
return added;
}
@Override
public boolean move(NodeConnectionAnchor targetAnchor) {
// Need to move the target anchor from one anchor list to another.
// remove from any list.
boolean removed = remove(targetAnchor);
// Now add to direction's list
boolean added = add( targetAnchor);
if( removed && added )
return true;
return false;
}
@Override
public boolean remove(NodeConnectionAnchor targetAnchor) {
boolean removed = false;
if( targetAnchor.getDirection() != NORTH &&
getNorthAnchors() != null && getNorthAnchors().contains(targetAnchor) ) {
getNorthAnchors().remove(targetAnchor);
removed = true;
}
if( targetAnchor.getDirection() != SOUTH &&
getSouthAnchors() != null && getSouthAnchors().contains(targetAnchor) ) {
getSouthAnchors().remove(targetAnchor);
removed = true;
}
if( targetAnchor.getDirection() != EAST &&
getEastAnchors() != null && getEastAnchors().contains(targetAnchor) ) {
getEastAnchors().remove(targetAnchor);
removed = true;
}
if( targetAnchor.getDirection() != WEST &&
getWestAnchors() != null && getWestAnchors().contains(targetAnchor) ) {
getWestAnchors().remove(targetAnchor);
removed = true;
}
return removed;
}
@Override
public void resetSourceAnchors(boolean updateTargetEnd) {
List sConnections = getSourceConnections();
if( sConnections.isEmpty())
return;
NodeConnectionEditPart nextConnection = null;
Iterator iter = sConnections.iterator();
DiagramEditPart targetEditPart = null;
NodeConnectionAnchor sourceAnchor = null;
while( iter.hasNext() ) {
nextConnection = (NodeConnectionEditPart)iter.next();
sourceAnchor = (NodeConnectionAnchor)nextConnection.getSourceAnchor();
targetEditPart = (DiagramEditPart )nextConnection.getTarget();
if( targetEditPart != null && sourceAnchor != null ) {
setAnchorPosition( sourceAnchor, WEST);
// Update Target side anchors
if( updateTargetEnd )
targetEditPart.createOrUpdateAnchorsLocations(false);
}
}
}
@Override
public void resetTargetAnchors(boolean updateSourceEnd) {
List tConnections = getTargetConnections();
if( tConnections.isEmpty())
return;
NodeConnectionEditPart nextConnection = null;
Iterator iter = tConnections.iterator();
DiagramEditPart sourceEditPart = null;
NodeConnectionAnchor targetAnchor = null;
while( iter.hasNext() ) {
nextConnection = (NodeConnectionEditPart)iter.next();
targetAnchor = (NodeConnectionAnchor)nextConnection.getTargetAnchor();
sourceEditPart = (DiagramEditPart )nextConnection.getSource();
if( sourceEditPart != null && targetAnchor != null ) {
setAnchorPosition( targetAnchor, EAST);
// Update Source side anchors
if( updateSourceEnd )
sourceEditPart.createOrUpdateAnchorsLocations(false);
}
}
}
/**
* @return
*/
@Override
public List getSourceConnections() {
return diagramEditPart.getSourceConnections();
}
/**
* @return
*/
@Override
public List getTargetConnections() {
return diagramEditPart.getTargetConnections();
}
/**
* @return
*/
@Override
public ConnectionAnchor getSourceAnchor(NodeConnectionEditPart connection) {
// This anchor manager belongs to the edit part.
// This edit part knows about all it's target connections
// An anchor is either target or source
//
if( connection.getSourceAnchor() == null ) {
// Create a anchor for it.
NodeConnectionAnchor newAnchor = createSourceAnchor();
connection.setSourceAnchor(newAnchor);
return newAnchor;
}
return connection.getSourceAnchor();
}
/**
* @return
*/
@Override
public ConnectionAnchor getTargetAnchor(NodeConnectionEditPart connection) {
// This anchor manager belongs to the edit part.
// This edit part knows about all it's target connections
// An anchor is either target or source
//
if( connection.getTargetAnchor() == null ) {
// Create a anchor for it.
NodeConnectionAnchor newAnchor = createTargetAnchor();
connection.setTargetAnchor(newAnchor);
return newAnchor;
}
return connection.getTargetAnchor();
}
private NodeConnectionAnchor createTargetAnchor() {
NodeConnectionAnchor newAnchor = new NodeConnectionAnchor(diagramEditPart.getFigure(), NodeConnectionAnchor.IS_TARGET);
// Set some default direction
newAnchor.setDirection(EAST);
add(newAnchor);
setAnchorPosition(newAnchor, EAST);
return newAnchor;
}
private NodeConnectionAnchor createSourceAnchor() {
NodeConnectionAnchor newAnchor = new NodeConnectionAnchor(diagramEditPart.getFigure(), NodeConnectionAnchor.IS_SOURCE);
// Set some default direction
newAnchor.setDirection(WEST);
add(newAnchor);
setAnchorPosition(newAnchor, WEST);
return newAnchor;
}
@Override
public boolean hasSourceAnchors() {
NodeConnectionAnchor nextAnchor = null;
Iterator iter = null;
if( northAnchors != null && !northAnchors.isEmpty() ) {
iter = northAnchors.iterator();
while(iter.hasNext()) {
nextAnchor = (NodeConnectionAnchor)iter.next();
if( nextAnchor != null && nextAnchor.isSource() )
return true;
}
}
if( southAnchors != null && !southAnchors.isEmpty() ) {
iter = southAnchors.iterator();
while(iter.hasNext()) {
nextAnchor = (NodeConnectionAnchor)iter.next();
if( nextAnchor != null && nextAnchor.isSource() )
return true;
}
}
if( eastAnchors != null && !eastAnchors.isEmpty() ) {
iter = eastAnchors.iterator();
while(iter.hasNext()) {
nextAnchor = (NodeConnectionAnchor)iter.next();
if( nextAnchor != null && nextAnchor.isSource() )
return true;
}
}
if( westAnchors != null && !westAnchors.isEmpty() ) {
iter = westAnchors.iterator();
while(iter.hasNext()) {
nextAnchor = (NodeConnectionAnchor)iter.next();
if( nextAnchor != null && nextAnchor.isSource() )
return true;
}
}
return false;
}
@Override
public boolean hasTargetAnchors() {
NodeConnectionAnchor nextAnchor = null;
Iterator iter = null;
if( northAnchors != null && !northAnchors.isEmpty() ) {
iter = northAnchors.iterator();
while(iter.hasNext()) {
nextAnchor = (NodeConnectionAnchor)iter.next();
if( nextAnchor != null && !nextAnchor.isSource() )
return true;
}
}
if( southAnchors != null && !southAnchors.isEmpty() ) {
iter = southAnchors.iterator();
while(iter.hasNext()) {
nextAnchor = (NodeConnectionAnchor)iter.next();
if( nextAnchor != null && !nextAnchor.isSource() )
return true;
}
}
if( eastAnchors != null && !eastAnchors.isEmpty() ) {
iter = eastAnchors.iterator();
while(iter.hasNext()) {
nextAnchor = (NodeConnectionAnchor)iter.next();
if( nextAnchor != null && !nextAnchor.isSource() )
return true;
}
}
if( westAnchors != null && !westAnchors.isEmpty() ) {
iter = westAnchors.iterator();
while(iter.hasNext()) {
nextAnchor = (NodeConnectionAnchor)iter.next();
if( nextAnchor != null && !nextAnchor.isSource() )
return true;
}
}
return false;
}
@Override
public void setAnchorPosition(NodeConnectionAnchor theAnchor, int direction ) {
Dimension partSize = ((DiagramModelNode)diagramEditPart.getModel()).getSize();
int oldDirection = theAnchor.getDirection();
theAnchor.setDirection(direction);
boolean moved = move(theAnchor);
if( moved ) {
setAnchorPositions(oldDirection, direction);
} else if( direction == NORTH ) {
theAnchor.setOffsetH(partSize.width/2);
theAnchor.setOffsetV(0);
} else if( direction == SOUTH) {
theAnchor.setOffsetH(partSize.width/2);
theAnchor.setOffsetV(partSize.height);
} else if( direction == WEST) {
theAnchor.setOffsetH(0);
theAnchor.setOffsetV(partSize.height/2);
} else {
theAnchor.setOffsetH(partSize.width);
theAnchor.setOffsetV(partSize.height/2);
}
}
/**
* This method for setting anchor positions assumes that we want to walk through all anchor positions
* to insure proper spacing..... should be called whenever an anchor is "moved" and there are more than
* to or from.
* @param theAnchor
* @param direction
*/
private void setAnchorPositions(int oldDirection, int newDirection ) {
setAnchorPositions(oldDirection);
setAnchorPositions(newDirection);
}
private void setAnchorPositions( int direction ) {
Dimension partSize = ((DiagramModelNode)diagramEditPart.getModel()).getSize();
Iterator iter = null;
if( direction == NORTH && getNorthAnchors() != null && !getNorthAnchors().isEmpty() ) {
// Walk through the anchors
iter = getNorthAnchors().iterator();
NodeConnectionAnchor theAnchor = null;
while( iter.hasNext()) {
theAnchor = (NodeConnectionAnchor)iter.next();
theAnchor.setOffsetH(partSize.width/2);
theAnchor.setOffsetV(0);
}
} else if( direction == SOUTH&& getSouthAnchors() != null && !getSouthAnchors().isEmpty() ) {
// Walk through the anchors
iter = getSouthAnchors().iterator();
NodeConnectionAnchor theAnchor = null;
while( iter.hasNext()) {
theAnchor = (NodeConnectionAnchor)iter.next();
theAnchor.setOffsetH(partSize.width/2);
theAnchor.setOffsetV(partSize.height);
}
} else if( direction == WEST&& getWestAnchors() != null && !getWestAnchors().isEmpty() ) {
// Walk through the anchors
iter = getWestAnchors().iterator();
NodeConnectionAnchor theAnchor = null;
while( iter.hasNext()) {
theAnchor = (NodeConnectionAnchor)iter.next();
theAnchor.setOffsetH(0);
theAnchor.setOffsetV(partSize.height/2);
}
} else if( getEastAnchors() != null && !getEastAnchors().isEmpty() ) {
// Walk through the anchors
iter = getEastAnchors().iterator();
NodeConnectionAnchor theAnchor = null;
while( iter.hasNext()) {
theAnchor = (NodeConnectionAnchor)iter.next();
theAnchor.setOffsetH(partSize.width);
theAnchor.setOffsetV(partSize.height/2);
}
}
}
/**
*
* @see org.teiid.designer.diagram.ui.connection.AnchorManager#reorderAllAnchors()
* @since 4.2
*/
@Override
public void reorderAllAnchors(boolean updateBothEnds) {
resetSourceAnchors(updateBothEnds);
resetTargetAnchors(updateBothEnds);
}
}