/** * {@inheritDoc} * * @see org.eclipse.draw2d.AbstractRouter#invalidate(org.eclipse.draw2d.Connection) */ @Override public void invalidate(final Connection conn) { if (conn.getSourceAnchor() == null || conn.getSourceAnchor().getOwner() == null || conn.getTargetAnchor() == null || conn.getTargetAnchor().getOwner() == null) { return; } final ListIterator li = Lists.newArrayList(connectionList).listIterator(); while (li.hasNext()) { final Connection connNext = (Connection) li.next(); if (!trunkVertexEqual(connNext, conn)) { updateConstraint(connNext); } } }
/** @param conn */ private void internalRoute(final Connection conn) { if (conn.getSourceAnchor() == null || conn.getSourceAnchor().getOwner() == null || conn.getTargetAnchor() == null || conn.getTargetAnchor().getOwner() == null) { super.route(conn); return; } if (!connectionList.contains(conn)) { connectionList.add(conn); } checkTrunkVertex(conn); getBranchRouter().route(conn); invalidate(conn); }
/** * UpdateConstraint Updates the constraint value for the connection based on the tree vertex. * * @param conn Connection whose constraint is to be updated. */ protected void updateConstraint(final Connection conn) { boolean update = conn != null && conn.getSourceAnchor() != null && conn.getTargetAnchor() != null; update = update && conn.getSourceAnchor().getOwner() != null && conn.getTargetAnchor().getOwner() != null; if (update) { if (isUpdatingPeers()) { return; } List bendpoints = (List) conn.getRoutingConstraint(); if (bendpoints == null) { bendpoints = new ArrayList(conn.getPoints().size()); } final Point sourceRefPoint = conn.getSourceAnchor().getReferencePoint(); conn.translateToRelative(sourceRefPoint); final Point targetRefPoint = conn.getTargetAnchor().getReferencePoint(); conn.translateToRelative(targetRefPoint); final Point ptTrunk = getTrunkLocation(conn); final Point ptSource = getBranchRouter().getSourceLocation(conn, ptTrunk); bendpoints.clear(); final PointList pts = getBranchRouter().recreateBranch(conn, ptSource, ptTrunk); for (int i = 0; i < pts.size(); i++) { final Bendpoint bp = new AbsoluteBendpoint(pts.getPoint(i)); bendpoints.add(bp); } setUpdatingPeers(true); try { setConstraint(conn, bendpoints); conn.invalidate(); conn.validate(); } finally { setUpdatingPeers(false); } } }
/** * {@inheritDoc} * * @see org.eclipse.draw2d.BendpointConnectionRouter#remove(org.eclipse.draw2d.Connection) */ @Override public void remove(final Connection conn) { if (conn.getSourceAnchor() == null || conn.getTargetAnchor() == null) { return; } final int index = connectionList.indexOf(conn); connectionList.remove(conn); for (int i = index + 1; i < connectionList.size(); i++) { ((Connection) connectionList.get(i)).revalidate(); } getBranchRouter().remove(conn); }
private void processStaleConnections() { Iterator<Connection> iter = staleConnections.iterator(); if (iter.hasNext() && connectionToPaths == null) { connectionToPaths = new HashMap<Connection, Path>(); hookAll(); } while (iter.hasNext()) { Connection conn = (Connection) iter.next(); Path path = (Path) connectionToPaths.get(conn); if (path == null) { path = new Path(conn); connectionToPaths.put(conn, path); algorithm.addPath(path); } List<?> constraint = (List<?>) getConstraint(conn); if (constraint == null) { constraint = Collections.EMPTY_LIST; } Point start = conn.getSourceAnchor().getReferencePoint().getCopy(); Point end = conn.getTargetAnchor().getReferencePoint().getCopy(); container.translateToRelative(start); container.translateToRelative(end); path.setStartPoint(start); path.setEndPoint(end); if (!constraint.isEmpty()) { PointList bends = new PointList(constraint.size()); for (int i = 0; i < constraint.size(); i++) { Bendpoint bp = (Bendpoint) constraint.get(i); bends.addPoint(bp.getLocation()); } path.setBendPoints(bends); } else { path.setBendPoints(null); } isDirty |= path.isDirty; } staleConnections.clear(); }
@Override public void route(Connection conn) { if (isDirty) { ignoreInvalidate = true; processStaleConnections(); isDirty = false; List<?> updated = algorithm.solve(); Connection current; for (int i = 0; i < updated.size(); i++) { Path path = (Path) updated.get(i); current = (Connection) path.data; current.revalidate(); PointList points = path.getPoints().getCopy(); Point ref1; Point ref2; Point start; Point end; ref1 = new PrecisionPoint(points.getPoint(1)); ref2 = new PrecisionPoint(points.getPoint(points.size() - 2)); current.translateToAbsolute(ref1); current.translateToAbsolute(ref2); start = current.getSourceAnchor().getLocation(ref1).getCopy(); end = current.getTargetAnchor().getLocation(ref2).getCopy(); current.translateToRelative(start); current.translateToRelative(end); points.setPoint(start, 0); points.setPoint(end, points.size() - 1); current.setPoints(points); } ignoreInvalidate = false; } }
private Rectangle getSourceAnchorRelativeBounds(final Connection conn) { final Rectangle bounds = conn.getSourceAnchor().getOwner().getBounds().getCopy(); conn.getSourceAnchor().getOwner().translateToAbsolute(bounds); conn.translateToRelative(bounds); return bounds; }
/** * Computes clipping rectangle(s) for a given connection. Will consider all enclosing viewports, * excluding the root viewport. */ protected Rectangle[] getEdgeClippingRectangle(Connection connection) { // start with clipping the connection at its original bounds Rectangle clipRect = getAbsoluteBoundsAsCopy(connection); // in case we cannot infer source and target of the connection (e.g. // if XYAnchors are used), returning the bounds is all we can do ConnectionAnchor sourceAnchor = connection.getSourceAnchor(); ConnectionAnchor targetAnchor = connection.getTargetAnchor(); if (sourceAnchor == null || sourceAnchor.getOwner() == null || targetAnchor == null || targetAnchor.getOwner() == null) { return new Rectangle[] {clipRect}; } // source and target figure are known, see if there is common // viewport // the connection has to be clipped at. IFigure sourceFigure = sourceAnchor.getOwner(); IFigure targetFigure = targetAnchor.getOwner(); Viewport nearestEnclosingCommonViewport = ViewportUtilities.getNearestCommonViewport(sourceFigure, targetFigure); if (nearestEnclosingCommonViewport == null) { return new Rectangle[] {clipRect}; } // if the nearest common viewport is not the root viewport, we may // start with clipping the connection at this viewport. if (nearestEnclosingCommonViewport != getRootViewport()) { clipRect.intersect(getNodeClippingRectangle(nearestEnclosingCommonViewport)); } // if the nearest common viewport of source and target is not // simultaneously // the nearest enclosing viewport of source and target respectively, the // connection has to be further clipped (the connection may even not be // visible at all) Viewport nearestEnclosingSourceViewport = ViewportUtilities.getNearestEnclosingViewport(sourceFigure); Viewport nearestEnclosingTargetViewport = ViewportUtilities.getNearestEnclosingViewport(targetFigure); if (nearestEnclosingSourceViewport != nearestEnclosingTargetViewport) { // compute if source and target anchor are visible // within the nearest common enclosing viewport (which may // itself be nested in other viewports). Rectangle sourceClipRect = getAbsoluteBoundsAsCopy(connection); if (nearestEnclosingSourceViewport != nearestEnclosingCommonViewport) { clipAtViewports( sourceClipRect, ViewportUtilities.getViewportsPath( nearestEnclosingSourceViewport, nearestEnclosingCommonViewport, false)); } Rectangle targetClipRect = getAbsoluteBoundsAsCopy(connection); if (nearestEnclosingTargetViewport != nearestEnclosingCommonViewport) { clipAtViewports( targetClipRect, ViewportUtilities.getViewportsPath( nearestEnclosingTargetViewport, nearestEnclosingCommonViewport, false)); } PointList absolutePointsAsCopy = getAbsolutePointsAsCopy(connection); boolean sourceAnchorVisible = sourceClipRect.getExpanded(PRIVATE_INSETS).contains(absolutePointsAsCopy.getFirstPoint()); boolean targetAnchorVisible = targetClipRect.getExpanded(PRIVATE_INSETS).contains(absolutePointsAsCopy.getLastPoint()); if (!sourceAnchorVisible || !targetAnchorVisible) { // one (or both) of source or target anchor is invisible // within the nearest common viewport, so up to now // we regard the edge as invisible. return new Rectangle[] {}; // TODO: We could come up with a more decent strategy here, // which also computes clipping fragments in those cases // where source/target are not visible but the edge // intersects with the enclosing source/target viewport's // parents bounds. } else { // both ends are visible, so just return what we have // computed before // (clipping at nearest enclosing viewport) return new Rectangle[] {clipRect}; } } else { // source and target share the same enclosing viewport, so just // return what we have computed before (clipping at nearest // enclosing viewport) return new Rectangle[] {clipRect}; } }