blob: 4e0b572e621b7eaf10b20c3cd8c859221387ce3d [file] [log] [blame]
/*******************************************************************************
* 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);
}
}