/*
* @(#)EdgeView.java 1.0 03-JUL-04
*
* Copyright (c) 2001-2004 Gaudenz Alder
*
*/
package org.jgraph.graph;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Map;
import javax.swing.SwingUtilities;
import org.jgraph.JGraph;
import org.jgraph.plaf.GraphUI;
import org.jgraph.plaf.basic.BasicGraphUI;
/**
* The default implementation of an edge view. The getEdgeRenderer method
* assumes a renderer of type EdgeRenderer. If you provide a custom renderer to
* a subclass, you must also override the methods that call this method, namely:
* getShape, getLabelBounds, getExtraLabelBounds, intersects and getBounds.
*
* @version 1.0 1/1/02
* @author Gaudenz Alder
*/
public class EdgeView extends AbstractCellView {
/** Renderer for the class. */
public static transient EdgeRenderer renderer = new EdgeRenderer();
/** List of points of the edge. May contain ports. */
protected transient java.util.List points;
/** Cached source and target portview of the edge. */
protected transient CellView source, target;
/** Cached label position of the edge. */
protected transient Point labelPosition;
protected transient Point[] extraLabelPositions;
/** Drawing attributes that are created on the fly */
public Shape beginShape, endShape, lineShape;
/** Shared-path tune-up. */
public transient GeneralPath sharedPath = null;
protected transient Rectangle2D cachedLabelBounds = null;
protected transient Rectangle2D[] cachedExtraLabelBounds = null;
protected transient Rectangle2D cachedBounds = null;
protected transient Point2D labelVector = null;
/**
* Constructs an empty edge view.
*/
public EdgeView() {
super();
}
/**
* Constructs an edge view for the specified model object.
*
* @param cell
* reference to the model object
*/
public EdgeView(Object cell) {
super(cell);
}
//
// Data Source
//
/**
* Overrides the parent method to udpate the cached points, source and
* target port. If the source or target is removed, a point is inserted into
* the array of points.
*/
public void refresh(GraphModel model, CellMapper mapper,
boolean createDependentViews) {
super.refresh(model, mapper, createDependentViews);
// Re-sync source- and targetportviews
Object modelSource = model.getSource(cell);
Object modelTarget = model.getTarget(cell);
setSource(mapper.getMapping(modelSource, createDependentViews));
setTarget(mapper.getMapping(modelTarget, createDependentViews));
}
/**
* Update attributes and recurse children.
*/
public void update() {
super.update();
// Save the reference to the points so they can be changed
// in-place by use of setPoint, setSource, setTarget methods.
points = GraphConstants.getPoints(allAttributes);
if (points == null) {
points = new ArrayList(4);
points.add(getAllAttributes().createPoint(10, 10));
points.add(getAllAttributes().createPoint(20, 20));
GraphConstants.setPoints(allAttributes, points);
}
checkDefaultLabelPosition();
Point[] positions = GraphConstants
.getExtraLabelPositions(allAttributes);
if (positions != null) {
extraLabelPositions = new Point[positions.length];
for (int i = 0; i < positions.length; i++)
extraLabelPositions[i] = positions[i];
} else
extraLabelPositions = null;
Edge.Routing routing = GraphConstants.getRouting(allAttributes);
if (routing != null)
routing.route(this, points);
// Clear cached shapes
beginShape = null;
endShape = null;
lineShape = null;
invalidate();
}
/**
* Hook for subclassers to avoid default label positions.
*/
protected void checkDefaultLabelPosition() {
labelPosition = GraphConstants.getLabelPosition(allAttributes);
String label = String.valueOf(getCell());
if (labelPosition == null && label != null && label.length() > 0) {
int center = GraphConstants.PERMILLE / 2;
labelPosition = new Point(center, 0);
GraphConstants.setLabelPosition(allAttributes, labelPosition);
}
}
void invalidate() {
labelVector = null;
sharedPath = null;
cachedBounds = null;
cachedLabelBounds = null;
cachedExtraLabelBounds = null;
}
/**
* Returns the shape of the view according to the last rendering state
*/
public Shape getShape() {
if (sharedPath != null)
return sharedPath;
else
return sharedPath = (GeneralPath) getEdgeRenderer().createShape();
}
/**
* Returns the bounds of label according to the last rendering state
*/
public Rectangle2D getLabelBounds() {
if (cachedLabelBounds != null) {
return cachedLabelBounds;
} else {
return cachedLabelBounds = getEdgeRenderer().getLabelBounds(null,
this);
}
}
/**
* Returns the bounds of label according to the last rendering state
*/
public Rectangle2D getExtraLabelBounds(int index) {
if (cachedLabelBounds != null && index < cachedExtraLabelBounds.length
&& cachedExtraLabelBounds[index] != null) {
return cachedExtraLabelBounds[index];
} else {
return cachedExtraLabelBounds[index] = getEdgeRenderer()
.getExtraLabelBounds(null, this, index);
}
}
//
// View Methods
//
/**
* Returns true if this view intersects the given rectangle.
*/
public boolean intersects(JGraph graph, Rectangle2D rect) {
boolean intersects = super.intersects(graph, rect);
if (!isLeaf()) {
return intersects;
} else if (intersects) {
Rectangle r = new Rectangle((int) rect.getX(), (int) rect.getY(),
(int) rect.getWidth(), (int) rect.getHeight());
return getEdgeRenderer().intersects(graph, this, r);
}
return false;
}
/**
* Returns the location for this portview.
*/
public Rectangle2D getBounds() {
Rectangle2D rect = super.getBounds();
if (rect == null) {
if (cachedBounds == null) {
cachedBounds = getEdgeRenderer().getBounds(this);
}
rect = cachedBounds;
}
return rect;
}
/**
* Returns the local renderer. Do not access the renderer field directly.
* Use this method instead. Note: This method is package private.
*/
EdgeRenderer getEdgeRenderer() {
return (EdgeRenderer) getRenderer();
}
/**
* Returns a renderer for the class.
*/
public CellViewRenderer getRenderer() {
return renderer;
}
/**
* Returns a cell handle for the view.
*/
public CellHandle getHandle(GraphContext context) {
return new EdgeHandle(this, context);
}
//
// Cached Values
//
/**
* Returns the CellView that represents the source of the edge.
*/
public CellView getSource() {
return source;
}
/**
* Sets the <code>sourceView</code> of the edge.
*/
public void setSource(CellView sourceView) {
source = sourceView;
if (source != null)
points.set(0, source);
else
points.set(0, getPoint(0));
invalidate();
}
/**
* Returns the CellView that represents the target of the edge.
*/
public CellView getTarget() {
return target;
}
/**
* Sets the <code>targetView</code> of the edge.
*/
public void setTarget(CellView targetView) {
target = targetView;
int n = points.size() - 1;
if (target != null)
points.set(n, target);
else
points.set(n, getPoint(n));
invalidate();
}
/**
* Returns a point that describes the position of the label.
*/
public Point2D getExtraLabelPosition(int index) {
return extraLabelPositions[index];
}
/**
* Returns a point that describes the position of the label.
*/
public Point2D getLabelPosition() {
return labelPosition;
}
/**
* Sets the description of the label position.
*/
public void setLabelPosition(Point2D pos) {
labelPosition.setLocation(pos);
invalidate();
}
/**
* Sets the description of the label position.
*/
public void setExtraLabelPosition(int index, Point2D pos) {
extraLabelPositions[index].setLocation(pos);
invalidate();
}
//
// Points
//
/**
* Returns the points.
*
* @return java.util.List
*/
public java.util.List getPoints() {
return points;
}
/**
* Returns the number of point for this edge.
*/
public int getPointCount() {
return points.size();
}
/**
* Returns the cached points for this edge.
*/
public Point2D getPoint(int index) {
Object obj = points.get(index);
if (obj instanceof PortView)
// Port Location Seen From This Edge
return ((PortView) obj).getLocation(this,
getPointLocation((index == 0) ? 1 : points.size() - 2));
else if (obj instanceof CellView) {
// Should not happen
Rectangle2D r = ((CellView) obj).getBounds();
return new Point2D.Double(r.getX(), r.getY());
} else if (obj instanceof Point2D)
// Regular Point
return (Point2D) obj;
return null;
}
/**
* Returns the point of <code>edge</code> at <code>index</code>. Avoids
* calling <code>getLocation</code> on any ports of <code>edge</code>.
* <br>
* This is used from within getPoint to pass the nearest point to the
* portview to find it's location. This uses the center point of the parent
* view to determine the port view's location to avoid infinite recursion.
*/
protected Point2D getPointLocation(int index) {
Object obj = points.get(index);
if (obj instanceof Point2D)
return (Point2D) obj;
else if (obj instanceof PortView) {
VertexView vertex = (VertexView) ((CellView) obj).getParentView();
if (vertex != null)
return vertex.getCenterPoint();
}
return null;
}
/**
* Sets the point at <code>index</code> to <code>p</code>.
*/
public void setPoint(int index, Point2D p) {
points.set(index, p);
invalidate();
}
/**
* Adds <code>p</code> at position <code>index</code>.
*/
public void addPoint(int index, Point2D p) {
points.add(index, p);
invalidate();
}
/**
* Removes the point at position <code>index</code>.
*/
public void removePoint(int index) {
points.remove(index);
invalidate();
}
/**
* Hook to return the vector that is taken as the base vector to compute
* relative label positions. Normally, the vector goes from the first to the
* last point on the edge, unless these points are equal, in which case the
* average distance of all points to the source point is used.
*/
public Point2D getLabelVector() {
if (labelVector == null) {
Point2D p0 = getPoint(0);
Point2D pe = getPoint(getPointCount() - 1);
double dx = 0;
double dy = 0;
// Finds an average distance
dx = 0;
dy = 0;
int n = getPointCount();
for (int i = 1; i < n; i++) {
Point2D point = getPoint(i);
dx += point.getX() - p0.getX();
dy += point.getY() - p0.getY();
}
n--;
dx /= (double) n;
dy /= (double) n;
labelVector = new Point2D.Double(dx, dy);
}
return labelVector;
}
//
// Routing
//
public static double getLength(CellView view) {
double cost = 1;
if (view instanceof EdgeView) {
EdgeView edge = (EdgeView) view;
Point2D last = null, current = null;
for (int i = 0; i < edge.getPointCount(); i++) {
current = edge.getPoint(i);
if (last != null)
cost += last.distance(current);
last = current;
}
}
return cost;
}
//
// Handle
//
// This implementation uses the point instance to make the change. No index
// is used for the current point because routing could change the index
// during
// the move operation.
public static class EdgeHandle implements CellHandle, Serializable {
protected JGraph graph;
/* Pointer to the edge and its clone. */
protected EdgeView edge, orig;
/*
* Boolean indicating whether the source, target or label is being
* edited.
*/
protected boolean label = false, source = false, target = false;
/**
* Holds the index of the current (editing) label or point.
*/
protected int currentLabel = -1, currentIndex = -1;
/* Pointer to the currently selected point. */
protected Point2D currentPoint;
/* Array of control points represented as rectangles. */
protected transient Rectangle2D[] r;
/* A control point for the label position. */
protected transient Rectangle2D loc;
protected transient Rectangle2D[] extraLabelLocations;
protected boolean firstOverlayCall = true;
protected boolean isEdgeConnectable = true;
protected EdgeView relevantEdge = null;
/**
* Indicates whether the edge has been modified during the last mouse
* pressed and dragged operations.
*/
protected boolean edgeModified = false;
public EdgeHandle(EdgeView edge, GraphContext ctx) {
this.graph = ctx.getGraph();
this.edge = edge;
loc = new Rectangle();
Object[] labels = GraphConstants.getExtraLabels(edge
.getAllAttributes());
if (labels != null) {
extraLabelLocations = new Rectangle[labels.length];
for (int i = 0; i < extraLabelLocations.length; i++)
extraLabelLocations[i] = new Rectangle();
}
orig = (EdgeView) graph.getGraphLayoutCache().getMapping(
edge.getCell(), false);
reloadPoints(orig);
isEdgeConnectable = GraphConstants.isConnectable(edge
.getAllAttributes());
}
protected void reloadPoints(EdgeView edge) {
relevantEdge = edge;
r = new Rectangle[edge.getPointCount()];
for (int i = 0; i < r.length; i++)
r[i] = new Rectangle();
invalidate();
}
// Update and paint control points
public void paint(Graphics g) {
invalidate();
if (!edge.isLeaf())
return;
for (int i = 0; i < r.length; i++) {
if (isEdgeConnectable)
g.setColor(graph.getHandleColor());
else
g.setColor(graph.getLockedHandleColor());
g.fill3DRect((int) r[i].getX(), (int) r[i].getY(), (int) r[i]
.getWidth(), (int) r[i].getHeight(), true);
CellView port = null;
if (i == 0 && edge.getSource() != null)
port = edge.getSource();
else if (i == r.length - 1 && edge.getTarget() != null)
port = edge.getTarget();
if (port != null) {
g.setColor(graph.getLockedHandleColor());
Point2D tmp = GraphConstants.getOffset(port
.getAllAttributes());
if (tmp != null) {
g.drawLine((int) r[i].getX() + 1,
(int) r[i].getY() + 1,
(int) (r[i].getX() + r[i].getWidth()) - 3,
(int) (r[i].getY() + r[i].getHeight()) - 3);
g.drawLine((int) r[i].getX() + 1,
(int) (r[i].getY() + r[i].getHeight()) - 3,
(int) (r[i].getX() + r[i].getWidth()) - 3,
(int) r[i].getY() + 1);
} else
g.drawRect((int) r[i].getX() + 2,
(int) r[i].getY() + 2,
(int) r[i].getWidth() - 5, (int) r[i]
.getHeight() - 5);
}
}
}
public void overlay(Graphics g) {
if (edge != null && !firstOverlayCall && edge.isLeaf()) {
// g.setColor(graph.getBackground()); // JDK 1.3
g.setColor(graph.getForeground());
g.setXORMode(graph.getBackground().darker());
Graphics2D g2 = (Graphics2D) g;
AffineTransform oldTransform = g2.getTransform();
g2.scale(graph.getScale(), graph.getScale());
graph.getUI().paintCell(g, edge, edge.getBounds(), true);
g2.setTransform(oldTransform);
if (isSourceEditing() && edge.getSource() != null)
paintPort(g, edge.getSource());
else if (isTargetEditing() && edge.getTarget() != null)
paintPort(g, edge.getTarget());
}
firstOverlayCall = false;
}
protected void paintPort(Graphics g, CellView p) {
boolean offset = (GraphConstants.getOffset(p.getAllAttributes()) != null);
Rectangle2D r = (offset) ? p.getBounds() : p.getParentView()
.getBounds();
r = graph.toScreen((Rectangle2D) r.clone());
int s = 3;
r.setFrame(r.getX() - s, r.getY() - s, r.getWidth() + 2 * s, r
.getHeight()
+ 2 * s);
graph.getUI().paintCell(g, p, r, true);
}
protected boolean snap(boolean source, Point2D point) {
boolean connect = graph.isConnectable() && isEdgeConnectable;
Object port = graph.getPortForLocation(point.getX(), point.getY());
if (port != null && connect) {
CellView portView = graph.getGraphLayoutCache().getMapping(
port, false);
if (GraphConstants.isConnectable(portView.getParentView()
.getAllAttributes())) {
Object cell = edge.getCell();
if (source && graph.getModel().acceptsSource(cell, port)) {
if (edge.getSource() != portView) {
overlay(graph.getGraphics());
edge.setSource(portView);
edge.update();
overlay(graph.getGraphics());
}
return true;
} else if (!source
&& graph.getModel().acceptsTarget(cell, port)) {
if (edge.getTarget() != portView) {
overlay(graph.getGraphics());
edge.setTarget(portView);
edge.update();
overlay(graph.getGraphics());
}
return true;
}
}
}
return false;
}
public boolean isConstrainedMoveEvent(MouseEvent e) {
GraphUI ui = graph.getUI();
if (ui instanceof BasicGraphUI)
return ((BasicGraphUI) ui).isConstrainedMoveEvent(e);
return false;
}
/**
* Returning true signifies a mouse event adds a new point to an edge.
*/
public boolean isAddPointEvent(MouseEvent event) {
return SwingUtilities.isRightMouseButton(event);
}
/**
* Returning true signifies a mouse event removes a given point.
*/
public boolean isRemovePointEvent(MouseEvent event) {
return SwingUtilities.isRightMouseButton(event);
}
protected boolean isSourceEditing() {
return source;
}
protected boolean isTargetEditing() {
return target;
}
/*
* Returns true if either the source, target, label or a point is being
* edited.
*/
protected boolean isEditing() {
return source || target || label || currentLabel >= 0
|| currentPoint != null;
}
/**
* Invoked when the mouse pointer has been moved on a component (with no
* buttons down).
*/
public void mouseMoved(MouseEvent event) {
for (int i = 0; i < r.length; i++)
if (r[i].contains(event.getPoint())) {
graph.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
event.consume();
return;
}
if (loc.contains(event.getPoint()) && graph.isMoveable()
&& GraphConstants.isMoveable(edge.getAllAttributes())) {
graph.setCursor(new Cursor(Cursor.HAND_CURSOR));
event.consume();
}
if (extraLabelLocations != null && graph.isMoveable()
&& GraphConstants.isMoveable(edge.getAllAttributes())) {
for (int i = 0; i < extraLabelLocations.length; i++) {
if (extraLabelLocations[i].contains(event.getPoint())) {
graph.setCursor(new Cursor(Cursor.HAND_CURSOR));
event.consume();
}
}
}
}
// Handle mouse pressed event.
public void mousePressed(MouseEvent event) {
/* INV: currentPoint = null; source = target = label = false; */
if (!edge.isLeaf())
return;
boolean bendable = graph.isBendable()
&& GraphConstants.isBendable(edge.getAllAttributes());
boolean disconnectable = graph.isDisconnectable()
&& GraphConstants.isDisconnectable(orig.getAllAttributes());
int x = event.getX();
int y = event.getY();
// Detect hit on control point
int index = 0;
for (index = 0; index < r.length; index++) {
if (r[index].contains(x, y)) {
currentPoint = edge.getPoint(index);
currentIndex = index;
source = index == 0
&& (edge.getSource() == null || (disconnectable && GraphConstants
.isDisconnectable(edge.getSource()
.getParentView().getAllAttributes())));
target = index == r.length - 1
&& (edge.getTarget() == null || (disconnectable && GraphConstants
.isDisconnectable(edge.getTarget()
.getParentView().getAllAttributes())));
break;
}
}
// Detect hit on label
if (!isEditing() && graph.isMoveable()
&& GraphConstants.isMoveable(edge.getAllAttributes())
&& loc != null && loc.contains(x, y)
&& !isAddPointEvent(event) && !isRemovePointEvent(event)) {
label = true;
}
// Detect hit on extra labels
else if (extraLabelLocations != null && !isEditing()
&& graph.isMoveable()
&& GraphConstants.isMoveable(edge.getAllAttributes())
&& !isAddPointEvent(event) && !isRemovePointEvent(event)) {
for (int i = 0; i < extraLabelLocations.length; i++) {
if (extraLabelLocations[i] != null
&& extraLabelLocations[i].contains(x, y)) {
currentLabel = i;
break;
}
}
}
// Remove Point
if (isRemovePointEvent(event)
&& currentPoint != null
&& !source
&& !target
&& bendable
&& (edge.getSource() == null || currentIndex > 0)
&& (edge.getTarget() == null || currentIndex < edge
.getPointCount() - 1)) {
edge.removePoint(index);
edgeModified = true;
mouseReleased(event);
// Add Point
} else if (isAddPointEvent(event) && !isEditing() && bendable) {
int s = graph.getHandleSize();
Rectangle2D rect = graph.fromScreen(new Rectangle(x - s, y - s,
2 * s, 2 * s));
if (edge.intersects(graph, rect)) {
Point2D point = graph.fromScreen(graph.snap(new Point(event
.getPoint())));
double min = Double.MAX_VALUE, dist = 0;
for (int i = 0; i < edge.getPointCount() - 1; i++) {
Point2D p = edge.getPoint(i);
Point2D p1 = edge.getPoint(i + 1);
dist = new Line2D.Double(p, p1).ptLineDistSq(point);
if (dist < min) {
min = dist;
index = i + 1;
}
}
edge.addPoint(index, point);
edgeModified = true;
currentPoint = point;
reloadPoints(edge);
paint(graph.getGraphics());
}
}
if (isEditing())
event.consume();
}
public void mouseDragged(MouseEvent event) {
edgeModified = true;
Point2D p = graph.fromScreen(new Point(event.getPoint()));
// Move Label
if (label || currentLabel >= 0) {
Rectangle2D r = edge.getBounds();
if (r != null) {
double x = p.getX();
double y = p.getY();
Point2D p0 = edge.getPoint(0);
Point2D pe = edge.getPoint(edge.getPointCount() - 1);
double p0x = p0.getX();
double p0y = p0.getY();
Point2D vector = edge.getLabelVector();
double dx = vector.getX();
double dy = vector.getY();
double pex = p0.getX() + dx;
double pey = p0.getY() + dy;
double len = Math.sqrt(dx * dx + dy * dy);
if (len > 0) {
double u = GraphConstants.PERMILLE;
double posy = len
* (-y * dx + p0y * dx + x * dy - p0x * dy)
/ (-pey * dy + p0y * dy - dx * pex + dx * p0x);
double posx = u
* (-y * pey + y * p0y + p0y * pey - p0y * p0y
- pex * x + pex * p0x + p0x * x - p0x
* p0x)
/ (-pey * dy + p0y * dy - dx * pex + dx * p0x);
p = new Point2D.Double(posx, posy);
} else {
p = new Point2D.Double(x - p0.getX(), y - p0.getY());
}
overlay(graph.getGraphics());
if (label)
edge.setLabelPosition(p);
else
edge.setExtraLabelPosition(currentLabel, p);
edge.update();
overlay(graph.getGraphics());
}
} else if (isEditing() && currentPoint != null) {
// Find Source/Target Port
if (!((source && snap(true, event.getPoint())) || (target && snap(
false, event.getPoint())))) {
// Else Use Point
boolean acceptSource = source
&& (graph.getModel().acceptsSource(edge.getCell(),
null) || graph.isPreviewInvalidNullPorts());
boolean acceptTarget = target
&& (graph.getModel().acceptsTarget(edge.getCell(),
null) || graph.isPreviewInvalidNullPorts());
if (acceptSource || acceptTarget || !(source || target)) {
overlay(graph.getGraphics());
p = graph.fromScreen(graph.snap(new Point(event
.getPoint())));
// Constrained movement
if (isConstrainedMoveEvent(event) && currentIndex >= 0) {
// Reset Initial Positions
EdgeView orig = (EdgeView) graph
.getGraphLayoutCache().getMapping(
edge.getCell(), false);
Point2D origPoint = orig.getPoint(currentIndex);
double totDx = p.getX() - origPoint.getX();
double totDy = p.getY() - origPoint.getY();
if (Math.abs(totDx) < Math.abs(totDy))
p.setLocation(origPoint.getX(), p.getY());
else
p.setLocation(p.getX(), origPoint.getY());
}
// Do not move into negative space
p.setLocation(Math.max(0, p.getX()), Math.max(0, p
.getY()));
currentPoint.setLocation(p);
if (source) {
edge.setPoint(0, p);
edge.setSource(null);
} else if (target) {
edge.setPoint(edge.getPointCount() - 1, p);
edge.setTarget(null);
}
edge.update();
overlay(graph.getGraphics());
}
}
}
} // Handle mouse released event
public void mouseReleased(MouseEvent e) {
boolean clone = e.isControlDown() && graph.isCloneable();
GraphModel model = graph.getModel();
Object source = (edge.getSource() != null) ? edge.getSource()
.getCell() : null;
Object target = (edge.getTarget() != null) ? edge.getTarget()
.getCell() : null;
if (edgeModified && model.acceptsSource(edge.getCell(), source)
&& model.acceptsTarget(edge.getCell(), target)) {
ConnectionSet cs = createConnectionSet(edge, edge.getCell(),
clone);
Map nested = GraphConstants.createAttributes(
new CellView[] { edge }, null);
if (clone) {
Map cellMap = graph.cloneCells(graph
.getDescendants(new Object[] { edge.getCell() }));
nested = GraphConstants.replaceKeys(cellMap, nested);
cs = cs.clone(cellMap);
Object[] cells = cellMap.values().toArray();
graph.getGraphLayoutCache().insert(cells, nested, cs, null,
null);
} else {
graph.getGraphLayoutCache().edit(nested, cs, null, null);
}
} else {
overlay(graph.getGraphics());
edge.refresh(graph.getModel(), graph.getGraphLayoutCache(),
false);
}
currentPoint = null;
this.edgeModified = false;
this.label = false;
this.source = false;
this.target = false;
currentLabel = -1;
currentIndex = -1;
firstOverlayCall = true;
e.consume();
}
protected ConnectionSet createConnectionSet(EdgeView view, Object edge,
boolean verbose) {
ConnectionSet cs = new ConnectionSet();
Object sourcePort = null, targetPort = null;
if (view.getSource() != null)
sourcePort = view.getSource().getCell();
if (view.getTarget() != null)
targetPort = view.getTarget().getCell();
if (verbose || sourcePort != graph.getModel().getSource(edge))
cs.connect(edge, sourcePort, true);
if (verbose || targetPort != graph.getModel().getTarget(edge))
cs.connect(edge, targetPort, false);
return cs;
}
// Update control points
protected void invalidate() {
EdgeView e = relevantEdge;
int handlesize = graph.getHandleSize();
EdgeRenderer er = (EdgeRenderer) edge.getRenderer();
for (int i = 0; i < r.length; i++) {
Point2D p = e.getPoint(i);
p = graph.toScreen(new Point2D.Double(p.getX(), p.getY()));
r[i].setFrame(p.getX() - handlesize, p.getY() - handlesize,
2 * handlesize, 2 * handlesize);
p = graph.toScreen(er.getLabelPosition(e));
Dimension d = er.getLabelSize(graph, e, graph
.convertValueToString(e));
if (p != null && d != null) {
Point2D s = graph.toScreen(new Point2D.Double(d.width,
d.height));
loc.setFrame(p.getX() - s.getX() / 2, p.getY() - s.getY()
/ 2, s.getX(), s.getY());
}
}
if (extraLabelLocations != null) {
for (int i = 0; i < extraLabelLocations.length; i++) {
Point2D p = er.getExtraLabelPosition(e, i);
if (p != null) {
p = graph.toScreen((Point2D) p.clone());
Dimension d = er.getExtraLabelSize(graph, e, i);
if (d != null) {
Point2D s = graph.toScreen(new Point2D.Double(
d.width, d.height));
extraLabelLocations[i].setFrame(p.getX() - s.getX()
/ 2, p.getY() - s.getY() / 2, s.getX(), s
.getY());
}
}
}
}
}
}
}