/** Erases the guide and the feedback shown by the container of the elements. */
  protected void eraseSourceFeedback() {
    if (guideline.getParent() != null) {
      guideline.getParent().remove(guideline);
    }

    if (_container != null) {
      _container.eraseSourceFeedback(getSourceRequest());
    }

    ChangeBoundsRequest request = new ChangeBoundsRequest(RequestConstants.REQ_MOVE);
    request.setEditParts(Collections.emptyList());
    request.setSizeDelta(new Dimension(0, 0));
    request.setMoveDelta(new Point(0, 0));
    for (IGraphicalEditPart part : _movingShapes) {
      part.eraseSourceFeedback(request);
    }

    ChangeBoundsRequest spRequest = new ChangeBoundsRequest(RequestConstants.REQ_RESIZE);
    spRequest.setEditParts(Collections.emptyList());
    spRequest.setSizeDelta(new Dimension(0, 0));
    spRequest.setMoveDelta(new Point(0, 0));
    for (IGraphicalEditPart sp : _subProcesses) {
      sp.eraseSourceFeedback(spRequest);
    }
  }
  /** Shows a nice guideline to show the move */
  protected void showSourceFeedback() {
    if (_container == null) {
      return;
    }
    if (guideline.getParent() == null) {
      addFeedback(guideline);
    }
    Rectangle bounds = Rectangle.SINGLETON.getCopy();
    bounds.y = getCurrentPositionZoomed();

    Rectangle containerBounds = _container.getFigure().getBounds().getCopy();

    _container.getFigure().translateToAbsolute(containerBounds);

    ((DiagramEditPart) getCurrentViewer().getContents())
        .getFigure()
        .translateToRelative(containerBounds);

    bounds.x = containerBounds.x;
    bounds.height = 1;
    bounds.width = containerBounds.width;

    ZoomManager zoomManager =
        ((DiagramRootEditPart) getCurrentViewer().getRootEditPart()).getZoomManager();
    bounds.performScale(zoomManager.getZoom());

    guideline.setBounds(bounds);
    guideline.setVisible(getState() == STATE_DRAG_IN_PROGRESS);

    ChangeBoundsRequest request = new ChangeBoundsRequest(RequestConstants.REQ_MOVE);
    request.setMoveDelta(((ChangeBoundsRequest) getSourceRequest()).getMoveDelta());
    request.setSizeDelta(new Dimension(0, 0));
    request.setEditParts(_movingShapes);

    for (IGraphicalEditPart part : _movingShapes) {
      part.showSourceFeedback(request);
    }

    ChangeBoundsRequest spRequest = new ChangeBoundsRequest(RequestConstants.REQ_RESIZE);
    Point moveDelta = ((ChangeBoundsRequest) getSourceRequest()).getMoveDelta().getCopy();
    Dimension spSizeDelta = new Dimension(moveDelta.x, moveDelta.y);
    spRequest.setSizeDelta(spSizeDelta);
    spRequest.setMoveDelta(new Point(0, 0));
    spRequest.setEditParts(_subProcesses);

    for (IGraphicalEditPart sp : _subProcesses) {
      sp.showSourceFeedback(spRequest);
    }
    ((DiagramEditPart) getCurrentViewer().getContents()).getRoot().refresh();
  }
  protected Command createNodeChangeBoundCommands(final List<ShapeEditPart> sortedNodes) {

    final CompoundCommand result = new CompoundCommand();
    final Iterator<ShapeEditPart> iterEditParts = sortedNodes.iterator();
    while (iterEditParts.hasNext()) {
      final ShapeEditPart shapeEditPart = iterEditParts.next();

      final ChangeBoundsRequest request =
          new ChangeBoundsRequest(org.eclipse.gef.RequestConstants.REQ_MOVE);
      request.setEditParts(shapeEditPart);
      final Point ptLocation = new Point(0, 0);
      // the zoom.
      double scale = 1.0;
      if (shapeEditPart.getRoot() instanceof DiagramRootEditPart) {
        final ZoomManager zoomManager =
            ((DiagramRootEditPart) shapeEditPart.getRoot()).getZoomManager();
        scale = zoomManager.getZoom();
      }
      // Compute request data.
      final Point ptOldLocation = shapeEditPart.getFigure().getBounds().getLocation();

      final Dimension delta = ptLocation.getDifference(ptOldLocation);

      request.setMoveDelta(new PrecisionPoint(delta.width * scale, delta.height * scale));
      request.setLocation(new PrecisionPoint(ptLocation.x * scale, ptLocation.y * scale));

      final Command cmd = this.buildCommandWrapper(request, shapeEditPart);
      result.add(cmd);
    }

    return result;
  }
  /** {@inheritDoc} */
  @Override
  protected void updateTargetRequest() {

    super.updateTargetRequest();
    Dimension delta = getDragMoveDelta();

    if (getSourceEditPart() instanceof GraphicalEditPart) {
      Rectangle childRect = ((GraphicalEditPart) getSourceEditPart()).getFigure().getBounds();
      if (getSourceEditPart().getParent() instanceof GraphicalEditPart) {
        Rectangle parentRect =
            ((GraphicalEditPart) getSourceEditPart().getParent()).getFigure().getBounds();
        IFigure fig = ((GraphicalEditPart) getSourceEditPart().getParent()).getFigure();

        IFigure contentPane =
            ((GraphicalEditPart) getSourceEditPart().getParent()).getContentPane();

        // calculate the virtual position
        Rectangle virtualPosition = childRect.getCopy();
        virtualPosition.x = virtualPosition.x + delta.width;
        virtualPosition.y = virtualPosition.y + delta.height;

        if (virtualPosition.x < 0) {
          delta.width = 0 - childRect.x;
        }
        if (virtualPosition.y < 0) {
          delta.height = 0 - childRect.y;
        }

        if (virtualPosition.x + virtualPosition.width + getBorder() > parentRect.width) {
          delta.width = parentRect.width - childRect.width - childRect.x - getBorder();
        }

        if (virtualPosition.y + virtualPosition.height + 2 * getBorder() > parentRect.height) {
          delta.height = parentRect.height - childRect.height - childRect.y - 2 * getBorder();
        }
        ChangeBoundsRequest request = (ChangeBoundsRequest) getTargetRequest();
        Point moveDelta = new Point(delta.width, delta.height);
        request.setMoveDelta(moveDelta);

        // Very important the child element to block inside the container
        // if not test first the target editPart.
        // let the default algorithm if the target is not its parent.
        setTargetEditPart(getSourceEditPart().getParent());
      }
    }
  }
  /** @see org.eclipse.gef.tools.SimpleDragTracker#updateSourceRequest() */
  protected void updateSourceRequest() {
    ChangeBoundsRequest request = (ChangeBoundsRequest) getSourceRequest();

    if (originalLocation == null) {
      originalLocation = getStartLocation().getCopy();
    }

    Dimension delta = getDragMoveDelta();

    request.setConstrainedMove(getCurrentInput().isModKeyDown(MODIFIER_CONSTRAINED_MOVE));
    request.setSnapToEnabled(!getCurrentInput().isModKeyDown(MODIFIER_NO_SNAPPING));

    Point moveDelta = new Point(delta.width, delta.height);
    request.getExtendedData().clear();
    request.setMoveDelta(moveDelta);
    snapPoint(request);

    request.setLocation(getLocation());
    request.setType(getCommandName());
  }
 // @unused
 public static Request getNewSourceFeedbackRequest(Request request, ShapeNodeEditPart editPart) {
   if (request instanceof ChangeBoundsRequest) {
     ChangeBoundsRequest currRequest = (ChangeBoundsRequest) request;
     Dimension oldDelta = currRequest.getSizeDelta();
     Dimension newDelta =
         getSizeDeltaToFitAnchors(editPart, oldDelta, PreserveAnchorsPositionCommand.PRESERVE_Y);
     // Information for creating a new ChangeBoundsRequest has been taken
     // from org.eclipse.gef.editpolicies.ResizableEditPolicy
     ChangeBoundsRequest newRequest = new ChangeBoundsRequest();
     newRequest.setMoveDelta(currRequest.getMoveDelta());
     newRequest.setSizeDelta(newDelta);
     newRequest.setLocation(currRequest.getLocation());
     newRequest.setExtendedData(currRequest.getExtendedData());
     newRequest.setResizeDirection(currRequest.getResizeDirection());
     newRequest.setType(currRequest.getType());
     return newRequest;
   } else {
     return request;
   }
 }
 /**
  * Shows or updates feedback for a change bounds request. The request is updated by the way so
  * that the shape stays a square.
  *
  * @param request the request
  */
 @Override
 protected void showChangeBoundsFeedback(ChangeBoundsRequest request) {
   // adapt the request for a square resize
   Point move = request.getMoveDelta();
   Dimension delta = request.getSizeDelta();
   int dH = delta.height;
   int dW = delta.width;
   int signum = 0;
   if (dH <= 0 && dW <= 0) {
     signum = -1;
   } else {
     signum = 1;
   }
   int positiveResize = Math.max(dH, dW);
   if (positiveResize <= 0) {
     if (dH == 0) {
       positiveResize = -dW;
     } else if (dW == 0) {
       positiveResize = -dH;
     } else {
       positiveResize = Math.min(-dH, -dW);
     }
   }
   int newDH = signum * positiveResize;
   int newDW = newDH;
   int dir = request.getResizeDirection();
   // adjust new position if impacted by resizing
   if ((dir & PositionConstants.NORTH) > 0) {
     move.y += dH - newDH;
   }
   if ((dir & PositionConstants.WEST) > 0) {
     move.x += dW - newDW;
   }
   request.setMoveDelta(move);
   delta.height = newDH;
   delta.width = newDW;
   super.showChangeBoundsFeedback(request);
 }
  /**
   * This method can be overridden by clients to customize the snapping behavior.
   *
   * @param request the <code>ChangeBoundsRequest</code> from which the move delta can be extracted
   *     and updated
   * @since 3.4
   */
  protected void snapPoint(ChangeBoundsRequest request) {
    Point moveDelta = request.getMoveDelta();
    SnapToHelper snapToHelper =
        (SnapToHelper) getConnectionEditPart().getAdapter(SnapToHelper.class);

    Rectangle rect = new Rectangle(originalLocation.x, originalLocation.y, 1, 1);
    if (sourceRectangle == null) {
      sourceRectangle = new PrecisionRectangle(rect);
    }

    if (snapToHelper != null && request.isSnapToEnabled()) {
      PrecisionRectangle baseRect = sourceRectangle.getPreciseCopy();
      baseRect.translate(moveDelta);

      PrecisionPoint preciseDelta = new PrecisionPoint(moveDelta);
      snapToHelper.snapPoint(
          request,
          PositionConstants.HORIZONTAL | PositionConstants.VERTICAL,
          new PrecisionRectangle[] {baseRect},
          preciseDelta);
      request.setMoveDelta(preciseDelta);
    }
  }
  @Override
  protected void updateSourceRequest() {
    ChangeBoundsRequest request = (ChangeBoundsRequest) getSourceRequest();
    Dimension d = getDragMoveDelta();

    Point location = new Point(getLocation());
    Point moveDelta = new Point(0, 0);
    Dimension resizeDelta = new Dimension(0, 0);

    request.setConstrainedResize(false);

    request.setCenteredResize(getCurrentInput().isModKeyDown(SWT.MOD1));

    if ((getResizeDirection() & PositionConstants.NORTH) != 0) {
      moveDelta.y += d.height;
      resizeDelta.height -= d.height;
    }
    if ((getResizeDirection() & PositionConstants.SOUTH) != 0) {
      resizeDelta.height += d.height;
    }
    if ((getResizeDirection() & PositionConstants.WEST) != 0) {
      moveDelta.x += d.width;
      resizeDelta.width -= d.width;
    }
    if ((getResizeDirection() & PositionConstants.EAST) != 0) {
      resizeDelta.width += d.width;
    }

    request.setMoveDelta(moveDelta);
    request.setSizeDelta(resizeDelta);
    request.setLocation(location);
    request.setEditParts(getOperationSet());

    request.getExtendedData().clear();

    // TODO: snapping
  }
  private Collection<ChangeBoundsRequest> getConstrainedRegionRequests(
      ChangeBoundsRequest request) {
    Collection<ChangeBoundsRequest> constrainedRequests = Lists.newArrayList();

    RequestQuery query = new RequestQuery(request);
    Dimension sizeDelta = request.getSizeDelta().getCopy();
    Point moveDelta = request.getMoveDelta().getCopy();

    List<AbstractDiagramElementContainerEditPart> regionToResize = getRegionParts();
    int stackDirection = getStackDirection();
    // Handle first and last regions.
    Object resizePropagator = request.getExtendedData().get(REGION_RESIZE_PROPAGATOR);
    if (query.isResizeFromTop() && stackDirection == PositionConstants.NORTH_SOUTH
        || query.isResizeFromLeft() && stackDirection == PositionConstants.EAST_WEST) {
      Option<AbstractDiagramElementContainerEditPart> firstRegionPart = getFirstRegionPart();
      if (firstRegionPart.some()
          && (!request.isConstrainedResize() || resizePropagator != firstRegionPart.get())) {
        ChangeBoundsRequest req = initConstrainedRequest(request);
        req.setEditParts(firstRegionPart.get());
        req.setSizeDelta(sizeDelta.getCopy());
        constrainedRequests.add(req);
      }
      // shift all other regions.
      regionToResize.remove(firstRegionPart.get());
      if (!regionToResize.isEmpty()
          && (!request.isConstrainedResize() || !regionToResize.contains(resizePropagator))) {
        ChangeBoundsRequest req = initConstrainedRequest(request);
        req.setEditParts(Lists.newArrayList(regionToResize));

        if (stackDirection == PositionConstants.NORTH_SOUTH) {
          req.setSizeDelta(new Dimension(sizeDelta.width, 0));
          req.setMoveDelta(new Point(0, -moveDelta.y));
        } else if (stackDirection == PositionConstants.EAST_WEST) {
          req.setSizeDelta(new Dimension(0, sizeDelta.height));
          req.setMoveDelta(new Point(-moveDelta.x, 0));
        }
        constrainedRequests.add(req);
        regionToResize.clear();
      }
    } else if (query.isResizeFromBottom() && stackDirection == PositionConstants.NORTH_SOUTH
        || query.isResizeFromRight() && stackDirection == PositionConstants.EAST_WEST) {
      // Resize the last region.
      Option<AbstractDiagramElementContainerEditPart> lastRegionPart = getLastRegionPart();
      if (lastRegionPart.some()
          && (!request.isConstrainedResize() || resizePropagator != lastRegionPart.get())) {
        ChangeBoundsRequest req = initConstrainedRequest(request);
        req.setEditParts(lastRegionPart.get());
        req.setSizeDelta(sizeDelta.getCopy());
        constrainedRequests.add(req);
        regionToResize.remove(lastRegionPart.get());
      }
    }

    // Handle horizontal resize for vstacks and vertical resize for hstacks.
    if (request.isConstrainedResize() && resizePropagator != null) {
      regionToResize.remove(resizePropagator);
    }
    if (!regionToResize.isEmpty()) {
      if (stackDirection == PositionConstants.NORTH_SOUTH
          && (query.isResizeFromLeft() || query.isResizeFromRight())
          && sizeDelta.width != 0) {
        ChangeBoundsRequest req = initConstrainedRequest(request);
        req.setEditParts(Lists.newArrayList(regionToResize));
        req.setSizeDelta(new Dimension(sizeDelta.width, 0));
        constrainedRequests.add(req);
      } else if (stackDirection == PositionConstants.EAST_WEST
          && (query.isResizeFromTop() || query.isResizeFromBottom())
          && sizeDelta.height != 0) {
        ChangeBoundsRequest req = initConstrainedRequest(request);
        req.setEditParts(Lists.newArrayList(regionToResize));
        req.setSizeDelta(new Dimension(0, sizeDelta.height));
        constrainedRequests.add(req);
      }
    }

    return constrainedRequests;
  }