public void figureMoved(IFigure source) {

          Rectangle newBounds = source.getBounds().getCopy();

          if (algorithm.updateObstacle((Rectangle) figuresToBounds.get(source), newBounds)) {
            queueSomeRouting();
            isDirty = true;
          }

          // Skip labels as routing obstacles
          if (!(source instanceof TransparentLabel)) {
            figuresToBounds.put(source, newBounds);
          }
        }
 void removeChild(IFigure child) {
   if (connectionToPaths == null) {
     return;
   }
   Rectangle bounds = child.getBounds().getCopy();
   boolean change = false;
   algorithm.removeObstacle(bounds);
   figuresToBounds.remove(child);
   child.removeFigureListener(figureListener);
   if (change) {
     isDirty = true;
     queueSomeRouting();
   }
 }
  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();
  }
  void addChild(IFigure child) {
    if (connectionToPaths == null) {
      return;
    }
    if (figuresToBounds.containsKey(child)) {
      return;
    }
    Rectangle bounds = child.getBounds().getCopy();

    // Skip labels as routing obstacles
    if (!(child instanceof TransparentLabel)) {
      algorithm.addObstacle(bounds);
      figuresToBounds.put(child, bounds);
      child.addFigureListener(figureListener);
      isDirty = true;
    }
  }
 @Override
 public void remove(Connection connection) {
   staleConnections.remove(connection);
   constraintMap.remove(connection);
   if (connectionToPaths == null) {
     return;
   }
   Path path = (Path) connectionToPaths.remove(connection);
   algorithm.removePath(path);
   isDirty = true;
   if (connectionToPaths.isEmpty()) {
     unhookAll();
     connectionToPaths = null;
   } else {
     // Make sure one of the remaining is revalidated so that we can re-route again.
     queueSomeRouting();
   }
 }
  @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;
    }
  }
 /**
  * Sets the default space that should be maintained on either side of a connection. This causes
  * the connections to be separated from each other and from the obstacles. The default value is 4.
  *
  * @param spacing the connection spacing
  * @since 3.2
  */
 public void setSpacing(int spacing) {
   algorithm.setSpacing(spacing);
 }
 /**
  * Returns the default spacing maintained on either side of a connection. The default value is 4.
  *
  * @return the connection spacing
  * @since 3.2
  */
 public int getSpacing() {
   return algorithm.getSpacing();
 }