/******************************************************************************
* Copyright (c) 2016 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.policies;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.draw2d.Bendpoint;
import org.eclipse.draw2d.Connection;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.Shape;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.handles.BendpointHandle;
import org.eclipse.gef.requests.BendpointRequest;
import org.eclipse.sapphire.ui.swt.gef.commands.BendPointCommand;
import org.eclipse.sapphire.ui.swt.gef.commands.CreateBendPointCommand;
import org.eclipse.sapphire.ui.swt.gef.commands.DeleteBendPointCommand;
import org.eclipse.sapphire.ui.swt.gef.commands.MoveBendPointCommand;
import org.eclipse.sapphire.ui.swt.gef.model.DiagramConnectionModel;
/**
* @author <a href="mailto:ling.hao@oracle.com">Ling Hao</a>
*/
public class DiagramConnectionBendpointEditPolicy extends org.eclipse.gef.editpolicies.BendpointEditPolicy {
@SuppressWarnings("rawtypes")
private static final List NULL_CONSTRAINT = new ArrayList();
private Map<Shape, Integer> shapeToLineStyle = new HashMap<Shape, Integer>();
protected Command getCreateBendpointCommand(BendpointRequest request) {
ConnectionEditPart connectionEditPart = (ConnectionEditPart)getHost();
if (connectionEditPart.getSource() == connectionEditPart.getTarget())
{
return null;
}
CreateBendPointCommand com = new CreateBendPointCommand();
Point p = request.getLocation();
Connection conn = getConnection();
conn.translateToRelative(p);
com.setLocation(p);
Point ref1 = getConnection().getSourceAnchor().getReferencePoint();
Point ref2 = getConnection().getTargetAnchor().getReferencePoint();
conn.translateToRelative(ref1);
conn.translateToRelative(ref2);
com.setRelativeDimensions(p.getDifference(ref1), p.getDifference(ref2));
com.setDiagramConnectionModel((DiagramConnectionModel) request.getSource().getModel());
com.setIndex(request.getIndex());
return com;
}
protected Command getMoveBendpointCommand(BendpointRequest request) {
ConnectionEditPart connectionEditPart = (ConnectionEditPart)getHost();
if (connectionEditPart.getSource() == connectionEditPart.getTarget())
{
return null;
}
MoveBendPointCommand com = new MoveBendPointCommand();
Point p = request.getLocation();
Connection conn = getConnection();
conn.translateToRelative(p);
com.setLocation(p);
Point ref1 = getConnection().getSourceAnchor().getReferencePoint();
Point ref2 = getConnection().getTargetAnchor().getReferencePoint();
conn.translateToRelative(ref1);
conn.translateToRelative(ref2);
com.setRelativeDimensions(p.getDifference(ref1), p.getDifference(ref2));
com.setDiagramConnectionModel((DiagramConnectionModel) request.getSource().getModel());
com.setIndex(request.getIndex());
return com;
}
protected Command getDeleteBendpointCommand(BendpointRequest request) {
ConnectionEditPart connectionEditPart = (ConnectionEditPart)getHost();
if (connectionEditPart.getSource() == connectionEditPart.getTarget())
{
return null;
}
BendPointCommand com = new DeleteBendPointCommand();
Point p = request.getLocation();
com.setLocation(p);
com.setDiagramConnectionModel((DiagramConnectionModel) request.getSource().getModel());
com.setIndex(request.getIndex());
return com;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
protected List createSelectionHandles() {
ConnectionEditPart connectionEditPart = (ConnectionEditPart)getHost();
if (connectionEditPart.getSource() == connectionEditPart.getTarget())
{
return Collections.EMPTY_LIST;
}
List<BendpointHandle> list;
boolean automaticallyBending = isAutomaticallyBending();
if (automaticallyBending) {
list = createHandlesForAutomaticBendpoints();
} else {
list = createHandlesForUserBendpoints();
}
return list;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private List createHandlesForAutomaticBendpoints() {
List list = new ArrayList();
ConnectionEditPart connEP = (ConnectionEditPart) getHost();
PointList points = getConnection().getPoints();
for (int i = 0; i < points.size() - 1; i++)
list.add(new DiagramBendpointCreationHandle(connEP, 0, i));
return list;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private List createHandlesForUserBendpoints() {
List list = new ArrayList();
ConnectionEditPart connEP = (ConnectionEditPart) getHost();
PointList points = getConnection().getPoints();
List bendPoints = (List) getConnection().getRoutingConstraint();
int bendPointIndex = 0;
Point currBendPoint = null;
if (bendPoints == null)
bendPoints = NULL_CONSTRAINT;
else if (!bendPoints.isEmpty())
currBendPoint = ((Bendpoint) bendPoints.get(0)).getLocation();
for (int i = 0; i < points.size() - 1; i++) {
// Put a create handle on the middle of every segment
list.add(new DiagramBendpointCreationHandle(connEP, bendPointIndex, i));
// If the current user bendpoint matches a bend location, show a
// move handle
if (i < points.size() - 1 && bendPointIndex < bendPoints.size()
&& currBendPoint.equals(points.getPoint(i + 1))) {
list.add(new DiagramBendpointMoveHandle(connEP, bendPointIndex, i + 1));
// Go to the next user bendpoint
bendPointIndex++;
if (bendPointIndex < bendPoints.size())
currBendPoint = ((Bendpoint) bendPoints.get(bendPointIndex)).getLocation();
}
}
return list;
}
@SuppressWarnings("rawtypes")
private boolean isAutomaticallyBending() {
List constraint = (List) getConnection().getRoutingConstraint();
PointList points = getConnection().getPoints();
return ((points.size() > 2) && (constraint == null || constraint.isEmpty()));
}
@Override
protected void addSelectionHandles() {
super.addSelectionHandles();
showHighlight();
}
@Override
protected void removeSelectionHandles() {
super.removeSelectionHandles();
removeHighlight();
}
protected void showHighlight() {
// remove previous highlight
removeHighlight();
// determine new highlight-values
int newLineStyle = Graphics.LINE_DASH;
// store old highlight-values and set new highlight-values
shapeToLineStyle.put(getConnectionFigure(), getConnectionFigure().getLineStyle());
getConnectionFigure().setLineStyle(newLineStyle);
}
protected void removeHighlight() {
Set<Shape> lineStyleShapes = shapeToLineStyle.keySet();
for (Shape lineStyleShape : lineStyleShapes) {
int lineStyle = shapeToLineStyle.get(lineStyleShape);
lineStyleShape.setLineStyle(lineStyle);
}
shapeToLineStyle.clear();
}
private Shape getConnectionFigure() {
return (Shape) ((GraphicalEditPart) getHost()).getFigure();
}
}