blob: 6c18763051235076be478e82e3759dfaac2e908e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 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.tools;
import java.util.List;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.draw2d.rap.swt.SWT;
import org.eclipse.gef.DragTracker;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.UnexecutableCommand;
/**
* A simple drag tracker implementation that does not perform targeting. For
* example, resizing a shape or bendpoint does not involve any target editpart.
*/
public abstract class SimpleDragTracker extends AbstractTool implements
DragTracker {
private static final int FLAG_SOURCE_FEEDBACK = AbstractTool.MAX_FLAG << 1;
/**
* The maximum bit-mask used as a flag constant. Subclasses should start
* using the next highest bitmask.
*/
protected static final int MAX_FLAG = FLAG_SOURCE_FEEDBACK;
private Request sourceRequest;
/**
* Null constructor.
*/
protected SimpleDragTracker() {
}
/**
* @see org.eclipse.gef.tools.AbstractTool#calculateCursor()
*/
protected Cursor calculateCursor() {
if (isInState(STATE_INITIAL | STATE_DRAG | STATE_ACCESSIBLE_DRAG))
return getDefaultCursor();
return super.calculateCursor();
}
/**
* @see DragTracker#commitDrag()
*/
public void commitDrag() {
eraseSourceFeedback();
performDrag();
setState(STATE_TERMINAL);
}
/**
* Creates and returns a new Request that is used during the drag.
*
* @return a new source request
*/
protected Request createSourceRequest() {
return new Request();
}
/**
* @see org.eclipse.gef.Tool#deactivate()
*/
public void deactivate() {
eraseSourceFeedback();
sourceRequest = null;
super.deactivate();
}
/**
* Show the source drag feedback for the drag occurring within the viewer.
*/
protected void eraseSourceFeedback() {
if (!isShowingFeedback())
return;
setFlag(FLAG_SOURCE_FEEDBACK, false);
List editParts = getOperationSet();
for (int i = 0; i < editParts.size(); i++) {
EditPart editPart = (EditPart) editParts.get(i);
editPart.eraseSourceFeedback(getSourceRequest());
}
}
/**
* Returns the request for the source of the drag, creating it if necessary.
*
* @return the source request
*/
protected Request getSourceRequest() {
if (sourceRequest == null)
sourceRequest = createSourceRequest();
return sourceRequest;
}
/**
* Looks for button 1, and goes into the drag state. Any other button is
* invalid input.
*
* @see org.eclipse.gef.tools.AbstractTool#handleButtonDown(int)
*/
protected boolean handleButtonDown(int button) {
if (button != 1) {
setState(STATE_INVALID);
handleInvalidInput();
} else
stateTransition(STATE_INITIAL, STATE_DRAG);
return true;
}
/**
* If dragging is in progress, cleans up feedback and calls performDrag().
*
* @see org.eclipse.gef.tools.AbstractTool#handleButtonUp(int)
*/
protected boolean handleButtonUp(int button) {
if (stateTransition(STATE_DRAG_IN_PROGRESS, STATE_TERMINAL)) {
eraseSourceFeedback();
performDrag();
}
return true;
}
/**
* @see org.eclipse.gef.tools.AbstractTool#handleDragInProgress()
*/
protected boolean handleDragInProgress() {
if (isInDragInProgress()) {
updateSourceRequest();
showSourceFeedback();
setCurrentCommand(getCommand());
}
return true;
}
/**
* Transitions Drag to Drag in progress state.
*
* @see org.eclipse.gef.tools.AbstractTool#handleDragStarted()
*/
protected boolean handleDragStarted() {
return stateTransition(STATE_DRAG, STATE_DRAG_IN_PROGRESS);
}
/**
* Called when the mouse and/or keyboard input is invalid.
*
* @return <code>true</code>
*/
protected boolean handleInvalidInput() {
eraseSourceFeedback();
setCurrentCommand(UnexecutableCommand.INSTANCE);
return true;
}
/**
* Looks for keys which are used during accessible drags.
*
* @see org.eclipse.gef.tools.AbstractTool#handleKeyDown(org.eclipse.swt.events.KeyEvent)
*/
protected boolean handleKeyDown(KeyEvent e) {
if (acceptArrowKey(e)) {
accStepIncrement();
if (stateTransition(STATE_INITIAL,
STATE_ACCESSIBLE_DRAG_IN_PROGRESS))
setStartLocation(getLocation());
switch (e.keyCode) {
case SWT.ARROW_DOWN:
placeMouseInViewer(getLocation().getTranslated(0, accGetStep()));
break;
case SWT.ARROW_UP:
placeMouseInViewer(getLocation()
.getTranslated(0, -accGetStep()));
break;
case SWT.ARROW_RIGHT:
int stepping = accGetStep();
if (isCurrentViewerMirrored())
stepping = -stepping;
placeMouseInViewer(getLocation().getTranslated(stepping, 0));
break;
case SWT.ARROW_LEFT:
int step = -accGetStep();
if (isCurrentViewerMirrored())
step = -step;
placeMouseInViewer(getLocation().getTranslated(step, 0));
break;
}
return true;
}
return false;
}
/**
* @see org.eclipse.gef.tools.AbstractTool#handleKeyUp(org.eclipse.swt.events.KeyEvent)
*/
protected boolean handleKeyUp(KeyEvent e) {
if (acceptArrowKey(e)) {
accStepReset();
return true;
}
return false;
}
/**
* Returns <code>true</code> if feedback is being shown.
*
* @return <code>true</code> if feedback is showing
*/
protected boolean isShowingFeedback() {
return getFlag(FLAG_SOURCE_FEEDBACK);
}
/**
* Called once the drag has been interpreted. This is where the real work of
* the drag is carried out. By default, the current command is executed.
*/
protected void performDrag() {
executeCurrentCommand();
}
/**
* Show the source drag feedback for the drag occurring within the viewer.
*/
protected void showSourceFeedback() {
List editParts = getOperationSet();
for (int i = 0; i < editParts.size(); i++) {
EditPart editPart = (EditPart) editParts.get(i);
editPart.showSourceFeedback(getSourceRequest());
}
setFlag(FLAG_SOURCE_FEEDBACK, true);
}
/**
* Updates the source request.
*/
protected void updateSourceRequest() {
getSourceRequest().setType(getCommandName());
}
}