/******************************************************************************* * Copyright (c) 2006 Sybase, Inc. 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: * Sybase, Inc. - initial API and implementation *******************************************************************************/ package org.eclipse.jst.pagedesigner.tools; import java.util.Collections; import org.eclipse.draw2d.Cursors; import org.eclipse.gef.DragTracker; import org.eclipse.gef.EditPart; import org.eclipse.gef.EditPartViewer; import org.eclipse.gef.RequestConstants; import org.eclipse.gef.requests.SelectionRequest; import org.eclipse.gef.tools.TargetingTool; import org.eclipse.jst.pagedesigner.parts.NodeEditPart; import org.eclipse.jst.pagedesigner.parts.TextEditPart; import org.eclipse.jst.pagedesigner.range.RangeUtil; import org.eclipse.jst.pagedesigner.validation.caret.ActionData; import org.eclipse.jst.pagedesigner.validation.caret.IPositionMediator; import org.eclipse.jst.pagedesigner.validation.caret.InlineEditingPositionMediator; import org.eclipse.jst.pagedesigner.validation.caret.Target; import org.eclipse.jst.pagedesigner.viewer.DesignPosition; import org.eclipse.jst.pagedesigner.viewer.DesignRange; import org.eclipse.jst.pagedesigner.viewer.EditPartPositionHelper; import org.eclipse.jst.pagedesigner.viewer.IHTMLGraphicalViewer; import org.eclipse.swt.graphics.Cursor; /** * @author mengbo */ public class RangeDragTracker extends TargetingTool implements DragTracker { /** Flag to indicate selection has been performed. */ private static final int FLAG_SELECTION_PERFORMED = TargetingTool.MAX_FLAG << 1; private EditPart editpart; /** * Constructs a new SelectEditPartTracker with the given edit part as the * source. * * @param owner * the source edit part */ public RangeDragTracker(EditPart owner) { setSourceEditPart(owner); } /** * @see org.eclipse.gef.tools.AbstractTool#calculateCursor() */ protected Cursor calculateCursor() { return Cursors.IBEAM; // if (isInState(STATE_INITIAL)) // { // return Cursors.IBEAM; // } // else if (isInState(STATE_DRAG | STATE_ACCESSIBLE_DRAG)) // { // return getDefaultCursor(); // } // return Cursors.IBEAM; // return super.calculateCursor(); } /** * @see org.eclipse.gef.tools.AbstractTool#getCommandName() */ protected String getCommandName() { return "Range Drag Tracker";//$NON-NLS-1$ } /** * @see org.eclipse.gef.tools.AbstractTool#getDebugName() */ protected String getDebugName() { return "Range Drag Tracker";//$NON-NLS-1$ } /** * Returns the source edit part. * * @return the source edit part */ protected EditPart getSourceEditPart() { return editpart; } /** * Performs a conditional selection if needed (if right or left mouse button * have been pressed) and goes into the drag state. If any other button has * been pressed, the tool goes into the invalid state. * * @see org.eclipse.gef.tools.AbstractTool#handleButtonDown(int) */ protected boolean handleButtonDown(int button) { if (button == 3 && isInState(STATE_INITIAL)) { EditPart sourcePart = this.getSourceEditPart(); IHTMLGraphicalViewer viewer = (IHTMLGraphicalViewer) sourcePart .getViewer(); if (viewer != null && viewer.isInRangeMode()) { DesignRange range = viewer.getRangeSelection(); if (range != null && range.isValid()) { if (RangeUtil.intersect(range, sourcePart)) { return true; } } } } if ((button == 1 || button == 3) && isInState(STATE_INITIAL)) { peroformSelectionBegin(); } if (button != 1) { setState(STATE_INVALID); if (button == 3) setState(STATE_TERMINAL); handleInvalidInput(); } else { stateTransition(STATE_INITIAL, STATE_DRAG); } return true; } /** * If the * source is selected and there are no modifier keys pressed (i.e. the user * isn't selecting multiple edit parts or deselecting edit parts), sets the * direct edit flag so that when the mouse is released, a direct edit will * be performed. */ protected void peroformSelectionBegin() { // if (getCurrentInput().isControlKeyDown()) // { // // when control key is down, switch to object selection mode. // getHTMLGraphicalViewer().ensureObjectSelectionMode(); // setFlag(FLAG_SELECTION_PERFORMED, true); // EditPartViewer viewer = getCurrentViewer(); // List selectedObjects = viewer.getSelectedEditParts(); // // if (selectedObjects.contains(getSourceEditPart())) // viewer.deselect(getSourceEditPart()); // else // viewer.appendSelection(getSourceEditPart()); // } // else if (getCurrentInput().isShiftKeyDown()) { getHTMLGraphicalViewer().ensureRangeSelectionMode(); rangeSelection(true); } else { if (shouldStartRangeSelection()) { rangeSelection(false); } else { getCurrentViewer().select(getSourceEditPart()); } } } /** * If in the drag state, the tool selects the source edit part. If the * edit part is newly selected and not completely visible, * {@link org.eclipse.gef.EditPartViewer#reveal(EditPart)}is called to show the selected * edit part. * * @see org.eclipse.gef.tools.AbstractTool#handleButtonUp(int) */ protected boolean handleButtonUp(int button) { if (isInState(STATE_DRAG)) { // XXX: commented the following two line (lium) // performSelection(); // if (button == 1 && getSourceEditPart().getSelected() != // EditPart.SELECTED_NONE) // getCurrentViewer().reveal(getSourceEditPart()); setState(STATE_TERMINAL); return true; } return false; } /** * Calls {@link #performOpen()}if the double click was with mouse button 1. * * @see org.eclipse.gef.tools.AbstractTool#handleDoubleClick(int) */ protected boolean handleDoubleClick(int button) { if (button == 1) { performOpen(); } return true; } /** * @see org.eclipse.gef.tools.AbstractTool#handleDragStarted() */ protected boolean handleDragStarted() { return stateTransition(STATE_DRAG, STATE_DRAG_IN_PROGRESS); } /* * (non-Javadoc) * * @see org.eclipse.gef.tools.AbstractTool#handleDragInProgress() */ protected boolean handleDragInProgress() { if (getHTMLGraphicalViewer().isInRangeMode()) { rangeSelection(true); return true; } return super.handleDragInProgress(); } /** * Returns <code>true</code> if selection has already occured. * * @return <code>true</code> if selection has occured */ protected boolean hasSelectionOccurred() { return getFlag(FLAG_SELECTION_PERFORMED); } /** * Creates a {@link SelectionRequest}and sends it to the source edit part * via {@link EditPart#performRequest(org.eclipse.gef.Request)}. Possible uses are to open * the selected item in another editor or replace the current editor's * contents based on the selected item. */ protected void performOpen() { SelectionRequest request = new SelectionRequest(); request.setLocation(getLocation()); request.setType(RequestConstants.REQ_OPEN); getSourceEditPart().performRequest(request); } /** * @see org.eclipse.gef.tools.AbstractTool#resetFlags() */ protected void resetFlags() { super.resetFlags(); setFlag(FLAG_SELECTION_PERFORMED, false); } /** * Sets the source edit part. * * @param part * the source edit part */ protected void setSourceEditPart(EditPart part) { this.editpart = part; } /** * @return the html graphical viewer */ public IHTMLGraphicalViewer getHTMLGraphicalViewer() { return (IHTMLGraphicalViewer) getCurrentViewer(); } /** * @return */ private boolean shouldStartRangeSelection() { IPositionMediator positionMediator = new InlineEditingPositionMediator( new ActionData(ActionData.INLINE_EDIT, null)); if (positionMediator.isEditable(new Target(getSourceEditPart()))) { return getSourceEditPart() instanceof TextEditPart || !(((NodeEditPart) getSourceEditPart()).isWidget()); } return false; } /** * @param b * true means remain the old range start position. */ private void rangeSelection(boolean b) { // XXX: not using updateTargetEditPartUnderMouse. Maybe should. Don't // want to // go through the request mechanism, so simple implementation for now. //to avoid 219038 and possibility of current viewer changing final EditPartViewer viewer = getCurrentViewer(); final IHTMLGraphicalViewer graphicalViewer = (IHTMLGraphicalViewer)viewer; EditPart editPart = viewer.findObjectAtExcluding( getLocation(), Collections.EMPTY_LIST); IPositionMediator positionMediator = new InlineEditingPositionMediator( new ActionData(ActionData.INLINE_EDIT, null)); ExposeHelper exposeHelper = new ExposeHelper(graphicalViewer); exposeHelper.adjustVertical(getCurrentInput().getMouseLocation()); DesignPosition position = EditPartPositionHelper.findEditPartPosition( editPart, getCurrentInput().getMouseLocation(), positionMediator); if (b) { graphicalViewer.setRangeEndPosition(position); } else { graphicalViewer.setRange(position, position); } graphicalViewer.updateHorizontalPos(); } protected boolean handleHover() { boolean retValue = super.handleHover(); refreshCursor(); return retValue; } }