/******************************************************************************* * Copyright (c) 2000, 2005 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.SWT; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.graphics.Cursor; 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()); } }