/**
  * Get the closest anchor to point p.
  *
  * @param p the reference point
  * @return the closest anchor to point p
  */
 protected ConnectionAnchor getClosestAnchorAt(Point p) {
   if (anchorMap == null) fillAnchorMap();
   ConnectionAnchor closest = null;
   double min = Long.MAX_VALUE;
   for (ConnectionAnchor anchor : anchorMap.values()) {
     Point p2 = anchor.getLocation(null);
     double d = p.getDistance(p2);
     if (d < min) {
       min = d;
       closest = anchor;
     }
   }
   return closest;
 }
예제 #2
0
 public ConnectionAnchor getTargetConnectionAnchorAt(Point p) {
   ConnectionAnchor closest = null;
   long min = Long.MAX_VALUE;
   Enumeration e = getTargetConnectionAnchors().elements();
   while (e.hasMoreElements()) {
     ConnectionAnchor c = (ConnectionAnchor) e.nextElement();
     Point p2 = c.getLocation(null);
     long d = p.getDistance2(p2);
     if (d < min) {
       min = d;
       closest = c;
     }
   }
   return closest;
 }
 public ConnectionAnchor getOutgoingConnectionAnchorAt(Point p) {
   ConnectionAnchor closest = null;
   long min = Long.MAX_VALUE;
   for (ConnectionAnchor c : outgoingConnectionAnchors) {
     Point p2 = c.getLocation(null);
     long d = p.getDistance2(p2);
     if (d < min) {
       min = d;
       closest = c;
     }
   }
   if (min > 100) {
     return defaultConnectionAnchor;
   }
   return closest;
 }
  /**
   * 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};
    }
  }