| /******************************************************************************* |
| * Copyright (c) 2003, 2010 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.gef.internal.ui.rulers; |
| |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.draw2d.Figure; |
| import org.eclipse.draw2d.IFigure; |
| import org.eclipse.draw2d.geometry.Point; |
| import org.eclipse.draw2d.geometry.Rectangle; |
| |
| import org.eclipse.gef.EditPart; |
| import org.eclipse.gef.GraphicalEditPart; |
| import org.eclipse.gef.Request; |
| import org.eclipse.gef.SharedCursors; |
| import org.eclipse.gef.commands.Command; |
| import org.eclipse.gef.commands.UnexecutableCommand; |
| import org.eclipse.gef.editparts.ZoomManager; |
| import org.eclipse.gef.editpolicies.GraphicalEditPolicy; |
| import org.eclipse.gef.requests.ChangeBoundsRequest; |
| |
| /** |
| * @author Pratik Shah |
| */ |
| public class DragGuidePolicy extends GraphicalEditPolicy { |
| |
| private List attachedEditParts = null; |
| private IFigure dummyGuideFigure, dummyLineFigure; |
| private boolean dragInProgress = false; |
| |
| protected IFigure createDummyLineFigure() { |
| return new Figure(); |
| } |
| |
| protected GuideFigure createDummyGuideFigure() { |
| return new GuidePlaceHolder(getGuideEditPart().isHorizontal()); |
| } |
| |
| /* |
| * Fix for Bug# 65885 If you undo guide creation while dragging that guide, |
| * it was leaving behind drag feedback. This was because by the time |
| * eraseSourceFeedback() was being called, the guide edit part had been |
| * deactivated (and hence eraseSourceFeedback is never called on this |
| * policy). So we make sure that this policy cleans up when it is |
| * deactivated. |
| */ |
| public void deactivate() { |
| removeFeedback(); |
| super.deactivate(); |
| } |
| |
| private void eraseAttachedPartsFeedback(Request request) { |
| if (attachedEditParts != null) { |
| ChangeBoundsRequest req = new ChangeBoundsRequest(request.getType()); |
| req.setEditParts(attachedEditParts); |
| |
| Iterator i = attachedEditParts.iterator(); |
| |
| while (i.hasNext()) |
| ((EditPart) i.next()).eraseSourceFeedback(req); |
| attachedEditParts = null; |
| } |
| } |
| |
| public void eraseSourceFeedback(Request request) { |
| getGuideEditPart().updateLocationOfFigures( |
| getGuideEditPart().getZoomedPosition()); |
| getHostFigure().setVisible(true); |
| getGuideEditPart().getGuideLineFigure().setVisible(true); |
| removeFeedback(); |
| getGuideEditPart().setCurrentCursor(null); |
| dragInProgress = false; |
| |
| eraseAttachedPartsFeedback(request); |
| } |
| |
| private List getAttachedEditParts() { |
| if (attachedEditParts == null) |
| attachedEditParts = getGuideEditPart().getRulerProvider() |
| .getAttachedEditParts( |
| getHost().getModel(), |
| ((RulerEditPart) getHost().getParent()) |
| .getDiagramViewer()); |
| return attachedEditParts; |
| } |
| |
| public Command getCommand(Request request) { |
| Command cmd; |
| final ChangeBoundsRequest req = (ChangeBoundsRequest) request; |
| if (isDeleteRequest(req)) { |
| cmd = getGuideEditPart().getRulerProvider().getDeleteGuideCommand( |
| getHost().getModel()); |
| } else { |
| int pDelta; |
| if (getGuideEditPart().isHorizontal()) { |
| pDelta = req.getMoveDelta().y; |
| } else { |
| pDelta = req.getMoveDelta().x; |
| } |
| if (isMoveValid(getGuideEditPart().getZoomedPosition() + pDelta)) { |
| ZoomManager zoomManager = getGuideEditPart().getZoomManager(); |
| if (zoomManager != null) { |
| pDelta = (int) Math.round(pDelta / zoomManager.getZoom()); |
| } |
| cmd = getGuideEditPart().getRulerProvider() |
| .getMoveGuideCommand(getHost().getModel(), pDelta); |
| } else { |
| cmd = UnexecutableCommand.INSTANCE; |
| } |
| } |
| return cmd; |
| } |
| |
| protected IFigure getDummyGuideFigure() { |
| if (dummyGuideFigure == null) { |
| dummyGuideFigure = createDummyGuideFigure(); |
| } |
| return dummyGuideFigure; |
| } |
| |
| protected IFigure getDummyLineFigure() { |
| if (dummyLineFigure == null) { |
| dummyLineFigure = createDummyLineFigure(); |
| } |
| return dummyLineFigure; |
| } |
| |
| protected GuideEditPart getGuideEditPart() { |
| return (GuideEditPart) getHost(); |
| } |
| |
| protected boolean isDeleteRequest(ChangeBoundsRequest req) { |
| int pos, max, min; |
| if (getGuideEditPart().isHorizontal()) { |
| pos = req.getLocation().x; |
| Rectangle zone = getHostFigure().getBounds().getExpanded( |
| GuideEditPart.DELETE_THRESHOLD, 0); |
| min = zone.x; |
| max = min + zone.width; |
| } else { |
| pos = req.getLocation().y; |
| Rectangle zone = getHostFigure().getBounds().getExpanded(0, |
| GuideEditPart.DELETE_THRESHOLD); |
| min = zone.y; |
| max = min + zone.height; |
| } |
| return pos < min || pos > max; |
| } |
| |
| protected boolean isMoveValid(int zoomedPosition) { |
| boolean result = true; |
| ZoomManager zoomManager = getGuideEditPart().getZoomManager(); |
| int position = zoomedPosition; |
| if (zoomManager != null) { |
| position = (int) Math.round(position / zoomManager.getZoom()); |
| } |
| Iterator guides = getGuideEditPart().getRulerProvider().getGuides() |
| .iterator(); |
| while (guides.hasNext()) { |
| Object guide = guides.next(); |
| if (guide != getGuideEditPart().getModel()) { |
| int guidePos = getGuideEditPart().getRulerProvider() |
| .getGuidePosition(guide); |
| if (Math.abs(guidePos - position) < GuideEditPart.MIN_DISTANCE_BW_GUIDES) { |
| result = false; |
| break; |
| } |
| } |
| } |
| |
| return result; |
| } |
| |
| private void removeFeedback() { |
| if (getDummyGuideFigure().getParent() != null) { |
| getDummyGuideFigure().getParent().remove(getDummyGuideFigure()); |
| } |
| if (getDummyLineFigure().getParent() != null) { |
| getDummyLineFigure().getParent().remove(getDummyLineFigure()); |
| } |
| } |
| |
| private void showAttachedPartsFeedback(ChangeBoundsRequest request) { |
| ChangeBoundsRequest req = new ChangeBoundsRequest(request.getType()); |
| req.setEditParts(getAttachedEditParts()); |
| |
| if (getGuideEditPart().isHorizontal()) |
| req.setMoveDelta(new Point(0, request.getMoveDelta().y)); |
| else |
| req.setMoveDelta(new Point(request.getMoveDelta().x, 0)); |
| |
| Iterator i = getAttachedEditParts().iterator(); |
| |
| while (i.hasNext()) |
| ((EditPart) i.next()).showSourceFeedback(req); |
| } |
| |
| public void showSourceFeedback(Request request) { |
| if (!dragInProgress) { |
| dragInProgress = true; |
| // add the placeholder guide figure to the ruler |
| getHostFigure().getParent().add(getDummyGuideFigure(), 0); |
| ((GraphicalEditPart) getHost().getParent()).setLayoutConstraint( |
| getHost(), getDummyGuideFigure(), new Integer( |
| getGuideEditPart().getZoomedPosition())); |
| getDummyGuideFigure().setBounds(getHostFigure().getBounds()); |
| // add the invisible placeholder line figure to the primary viewer |
| getGuideEditPart().getGuideLayer().add(getDummyLineFigure(), 0); |
| getGuideEditPart().getGuideLayer().setConstraint( |
| getDummyLineFigure(), |
| new Boolean(getGuideEditPart().isHorizontal())); |
| getDummyLineFigure().setBounds( |
| getGuideEditPart().getGuideLineFigure().getBounds()); |
| // move the guide being dragged to the last index so that it's drawn |
| // on |
| // top of other guides |
| List children = getHostFigure().getParent().getChildren(); |
| children.remove(getHostFigure()); |
| children.add(getHostFigure()); |
| } |
| ChangeBoundsRequest req = (ChangeBoundsRequest) request; |
| if (isDeleteRequest(req)) { |
| getHostFigure().setVisible(false); |
| getGuideEditPart().getGuideLineFigure().setVisible(false); |
| getGuideEditPart().setCurrentCursor(SharedCursors.ARROW); |
| eraseAttachedPartsFeedback(request); |
| } else { |
| int newPosition; |
| if (getGuideEditPart().isHorizontal()) { |
| newPosition = getGuideEditPart().getZoomedPosition() |
| + req.getMoveDelta().y; |
| } else { |
| newPosition = getGuideEditPart().getZoomedPosition() |
| + req.getMoveDelta().x; |
| } |
| getHostFigure().setVisible(true); |
| getGuideEditPart().getGuideLineFigure().setVisible(true); |
| if (isMoveValid(newPosition)) { |
| getGuideEditPart().setCurrentCursor(null); |
| getGuideEditPart().updateLocationOfFigures(newPosition); |
| showAttachedPartsFeedback(req); |
| } else { |
| getGuideEditPart().setCurrentCursor(SharedCursors.NO); |
| getGuideEditPart().updateLocationOfFigures( |
| getGuideEditPart().getZoomedPosition()); |
| eraseAttachedPartsFeedback(request); |
| } |
| } |
| } |
| |
| public boolean understandsRequest(Request req) { |
| return req.getType().equals(REQ_MOVE); |
| } |
| |
| } |