diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GestureManager.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GestureManager.java | 930 |
1 files changed, 0 insertions, 930 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GestureManager.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GestureManager.java deleted file mode 100644 index 98bc25e37..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GestureManager.java +++ /dev/null @@ -1,930 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.eclipse.org/org/documents/epl-v10.php - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.ide.eclipse.adt.internal.editors.layout.gle2; - -import com.android.SdkConstants; -import com.android.ide.common.api.DropFeedback; -import com.android.ide.common.api.IViewRule; -import com.android.ide.common.api.Rect; -import com.android.ide.common.api.SegmentType; -import com.android.ide.eclipse.adt.internal.editors.layout.gre.NodeProxy; -import com.android.utils.Pair; - -import org.eclipse.jface.action.IStatusLineManager; -import org.eclipse.swt.SWT; -import org.eclipse.swt.dnd.DND; -import org.eclipse.swt.dnd.DragSource; -import org.eclipse.swt.dnd.DragSourceEvent; -import org.eclipse.swt.dnd.DragSourceListener; -import org.eclipse.swt.dnd.DropTarget; -import org.eclipse.swt.dnd.DropTargetEvent; -import org.eclipse.swt.dnd.DropTargetListener; -import org.eclipse.swt.dnd.TextTransfer; -import org.eclipse.swt.events.KeyEvent; -import org.eclipse.swt.events.KeyListener; -import org.eclipse.swt.events.MouseEvent; -import org.eclipse.swt.events.MouseListener; -import org.eclipse.swt.events.MouseMoveListener; -import org.eclipse.swt.events.MouseTrackListener; -import org.eclipse.swt.events.TypedEvent; -import org.eclipse.swt.graphics.Cursor; -import org.eclipse.swt.graphics.Device; -import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.ImageData; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.IEditorSite; - -import java.util.ArrayList; -import java.util.List; - -/** - * The {@link GestureManager} is is the central manager of gestures; it is responsible - * for recognizing when particular gestures should begin and terminate. It - * listens to the drag, mouse and keyboard systems to find out when to start - * gestures and in order to update the gestures along the way. - */ -public class GestureManager { - /** The canvas which owns this GestureManager. */ - private final LayoutCanvas mCanvas; - - /** The currently executing gesture, or null. */ - private Gesture mCurrentGesture; - - /** A listener for drop target events. */ - private final DropTargetListener mDropListener = new CanvasDropListener(); - - /** A listener for drag source events. */ - private final DragSourceListener mDragSourceListener = new CanvasDragSourceListener(); - - /** Tooltip shown during the gesture, or null */ - private GestureToolTip mTooltip; - - /** - * The list of overlays associated with {@link #mCurrentGesture}. Will be - * null before it has been initialized lazily by the paint routine (the - * initialized value can never be null, but it can be an empty collection). - */ - private List<Overlay> mOverlays; - - /** - * Most recently seen mouse position (x coordinate). We keep a copy of this - * value since we sometimes need to know it when we aren't told about the - * mouse position (such as when a keystroke is received, such as an arrow - * key in order to tweak the current drop position) - */ - protected int mLastMouseX; - - /** - * Most recently seen mouse position (y coordinate). We keep a copy of this - * value since we sometimes need to know it when we aren't told about the - * mouse position (such as when a keystroke is received, such as an arrow - * key in order to tweak the current drop position) - */ - protected int mLastMouseY; - - /** - * Most recently seen mouse mask. We keep a copy of this since in some - * scenarios (such as on a drag gesture) we don't get access to it. - */ - protected int mLastStateMask; - - /** - * Listener for mouse motion, click and keyboard events. - */ - private Listener mListener; - - /** - * When we the drag leaves, we don't know if that's the last we'll see of - * this drag or if it's just temporarily outside the canvas and it will - * return. We want to restore it if it comes back. This is also necessary - * because even on a drop we'll receive a - * {@link DropTargetListener#dragLeave} right before the drop, and we need - * to restore it in the drop. Therefore, when we lose a {@link DropGesture} - * to a {@link DropTargetListener#dragLeave}, we store a reference to the - * current gesture as a {@link #mZombieGesture}, since the gesture is dead - * but might be brought back to life if we see a subsequent - * {@link DropTargetListener#dragEnter} before another gesture begins. - */ - private DropGesture mZombieGesture; - - /** - * Flag tracking whether we've set a message or error message on the global status - * line (since we only want to clear that message if we have set it ourselves). - * This is the actual message rather than a boolean such that (if we can get our - * hands on the global message) we can check to see if the current message is the - * one we set and only in that case clear it when it is no longer applicable. - */ - private String mDisplayingMessage; - - /** - * Constructs a new {@link GestureManager} for the given - * {@link LayoutCanvas}. - * - * @param canvas The canvas which controls this {@link GestureManager} - */ - public GestureManager(LayoutCanvas canvas) { - mCanvas = canvas; - } - - /** - * Returns the canvas associated with this GestureManager. - * - * @return The {@link LayoutCanvas} associated with this GestureManager. - * Never null. - */ - public LayoutCanvas getCanvas() { - return mCanvas; - } - - /** - * Returns the current gesture, if one is in progress, and otherwise returns - * null. - * - * @return The current gesture or null. - */ - public Gesture getCurrentGesture() { - return mCurrentGesture; - } - - /** - * Paints the overlays associated with the current gesture, if any. - * - * @param gc The graphics object to paint into. - */ - public void paint(GC gc) { - if (mCurrentGesture == null) { - return; - } - - if (mOverlays == null) { - mOverlays = mCurrentGesture.createOverlays(); - Device device = gc.getDevice(); - for (Overlay overlay : mOverlays) { - overlay.create(device); - } - } - for (Overlay overlay : mOverlays) { - overlay.paint(gc); - } - } - - /** - * Registers all the listeners needed by the {@link GestureManager}. - * - * @param dragSource The drag source in the {@link LayoutCanvas} to listen - * to. - * @param dropTarget The drop target in the {@link LayoutCanvas} to listen - * to. - */ - public void registerListeners(DragSource dragSource, DropTarget dropTarget) { - assert mListener == null; - mListener = new Listener(); - mCanvas.addMouseMoveListener(mListener); - mCanvas.addMouseListener(mListener); - mCanvas.addKeyListener(mListener); - - if (dragSource != null) { - dragSource.addDragListener(mDragSourceListener); - } - if (dropTarget != null) { - dropTarget.addDropListener(mDropListener); - } - } - - /** - * Unregisters all the listeners previously registered by - * {@link #registerListeners}. - * - * @param dragSource The drag source in the {@link LayoutCanvas} to stop - * listening to. - * @param dropTarget The drop target in the {@link LayoutCanvas} to stop - * listening to. - */ - public void unregisterListeners(DragSource dragSource, DropTarget dropTarget) { - if (mCanvas.isDisposed()) { - // If the LayoutCanvas is already disposed, we shouldn't try to unregister - // the listeners; they are already not active and an attempt to remove the - // listener will throw a widget-is-disposed exception. - mListener = null; - return; - } - - if (mListener != null) { - mCanvas.removeMouseMoveListener(mListener); - mCanvas.removeMouseListener(mListener); - mCanvas.removeKeyListener(mListener); - mListener = null; - } - - if (dragSource != null) { - dragSource.removeDragListener(mDragSourceListener); - } - if (dropTarget != null) { - dropTarget.removeDropListener(mDropListener); - } - } - - /** - * Starts the given gesture. - * - * @param mousePos The most recent mouse coordinate applicable to the new - * gesture, in control coordinates. - * @param gesture The gesture to initiate - */ - private void startGesture(ControlPoint mousePos, Gesture gesture, int mask) { - if (mCurrentGesture != null) { - finishGesture(mousePos, true); - assert mCurrentGesture == null; - } - - if (gesture != null) { - mCurrentGesture = gesture; - mCurrentGesture.begin(mousePos, mask); - } - } - - /** - * Updates the current gesture, if any, for the given event. - * - * @param mousePos The most recent mouse coordinate applicable to the new - * gesture, in control coordinates. - * @param event The event corresponding to this update. May be null. Don't - * make any assumptions about the type of this event - for - * example, it may not always be a MouseEvent, it could be a - * DragSourceEvent, etc. - */ - private void updateMouse(ControlPoint mousePos, TypedEvent event) { - if (mCurrentGesture != null) { - mCurrentGesture.update(mousePos); - } - } - - /** - * Finish the given gesture, either from successful completion or from - * cancellation. - * - * @param mousePos The most recent mouse coordinate applicable to the new - * gesture, in control coordinates. - * @param canceled True if and only if the gesture was canceled. - */ - private void finishGesture(ControlPoint mousePos, boolean canceled) { - if (mCurrentGesture != null) { - mCurrentGesture.end(mousePos, canceled); - if (mOverlays != null) { - for (Overlay overlay : mOverlays) { - overlay.dispose(); - } - mOverlays = null; - } - mCurrentGesture = null; - mZombieGesture = null; - mLastStateMask = 0; - updateMessage(null); - updateCursor(mousePos); - mCanvas.redraw(); - } - } - - /** - * Update the cursor to show the type of operation we expect on a mouse press: - * <ul> - * <li>Over a selection handle, show a directional cursor depending on the position of - * the selection handle - * <li>Over a widget, show a move (hand) cursor - * <li>Otherwise, show the default arrow cursor - * </ul> - */ - void updateCursor(ControlPoint controlPoint) { - // We don't hover on the root since it's not a widget per see and it is always there. - SelectionManager selectionManager = mCanvas.getSelectionManager(); - - if (!selectionManager.isEmpty()) { - Display display = mCanvas.getDisplay(); - Pair<SelectionItem, SelectionHandle> handlePair = - selectionManager.findHandle(controlPoint); - if (handlePair != null) { - SelectionHandle handle = handlePair.getSecond(); - int cursorType = handle.getSwtCursorType(); - Cursor cursor = display.getSystemCursor(cursorType); - if (cursor != mCanvas.getCursor()) { - mCanvas.setCursor(cursor); - } - return; - } - - // See if it's over a selected view - LayoutPoint layoutPoint = controlPoint.toLayout(); - for (SelectionItem item : selectionManager.getSelections()) { - if (item.getRect().contains(layoutPoint.x, layoutPoint.y) - && !item.isRoot()) { - Cursor cursor = display.getSystemCursor(SWT.CURSOR_HAND); - if (cursor != mCanvas.getCursor()) { - mCanvas.setCursor(cursor); - } - return; - } - } - } - - if (mCanvas.getCursor() != null) { - mCanvas.setCursor(null); - } - } - - /** - * Update the Eclipse status message with any feedback messages from the given - * {@link DropFeedback} object, or clean up if there is no more feedback to process - * @param feedback the feedback whose message we want to display, or null to clear the - * message if previously set - */ - void updateMessage(DropFeedback feedback) { - IEditorSite editorSite = mCanvas.getEditorDelegate().getEditor().getEditorSite(); - IStatusLineManager status = editorSite.getActionBars().getStatusLineManager(); - if (feedback == null) { - if (mDisplayingMessage != null) { - status.setMessage(null); - status.setErrorMessage(null); - mDisplayingMessage = null; - } - } else if (feedback.errorMessage != null) { - if (!feedback.errorMessage.equals(mDisplayingMessage)) { - mDisplayingMessage = feedback.errorMessage; - status.setErrorMessage(mDisplayingMessage); - } - } else if (feedback.message != null) { - if (!feedback.message.equals(mDisplayingMessage)) { - mDisplayingMessage = feedback.message; - status.setMessage(mDisplayingMessage); - } - } else if (mDisplayingMessage != null) { - // TODO: Can we check the existing message and only clear it if it's the - // same as the one we set? - mDisplayingMessage = null; - status.setMessage(null); - status.setErrorMessage(null); - } - - // Tooltip - if (feedback != null && feedback.tooltip != null) { - Pair<Boolean,Boolean> position = mCurrentGesture.getTooltipPosition(); - boolean below = position.getFirst(); - if (feedback.tooltipY != null) { - below = feedback.tooltipY == SegmentType.BOTTOM; - } - boolean toRightOf = position.getSecond(); - if (feedback.tooltipX != null) { - toRightOf = feedback.tooltipX == SegmentType.RIGHT; - } - if (mTooltip == null) { - mTooltip = new GestureToolTip(mCanvas, below, toRightOf); - } - mTooltip.update(feedback.tooltip, below, toRightOf); - } else if (mTooltip != null) { - mTooltip.dispose(); - mTooltip = null; - } - } - - /** - * Returns the current mouse position as a {@link ControlPoint} - * - * @return the current mouse position as a {@link ControlPoint} - */ - public ControlPoint getCurrentControlPoint() { - return ControlPoint.create(mCanvas, mLastMouseX, mLastMouseY); - } - - /** - * Returns the current SWT modifier key mask as an {@link IViewRule} modifier mask - * - * @return the current SWT modifier key mask as an {@link IViewRule} modifier mask - */ - public int getRuleModifierMask() { - int swtMask = mLastStateMask; - int modifierMask = 0; - if ((swtMask & SWT.MOD1) != 0) { - modifierMask |= DropFeedback.MODIFIER1; - } - if ((swtMask & SWT.MOD2) != 0) { - modifierMask |= DropFeedback.MODIFIER2; - } - if ((swtMask & SWT.MOD3) != 0) { - modifierMask |= DropFeedback.MODIFIER3; - } - return modifierMask; - } - - /** - * Helper class which implements the {@link MouseMoveListener}, - * {@link MouseListener} and {@link KeyListener} interfaces. - */ - private class Listener implements MouseMoveListener, MouseListener, MouseTrackListener, - KeyListener { - - // --- MouseMoveListener --- - - @Override - public void mouseMove(MouseEvent e) { - mLastMouseX = e.x; - mLastMouseY = e.y; - mLastStateMask = e.stateMask; - - ControlPoint controlPoint = ControlPoint.create(mCanvas, e); - if ((e.stateMask & SWT.BUTTON_MASK) != 0) { - if (mCurrentGesture != null) { - updateMouse(controlPoint, e); - mCanvas.redraw(); - } - } else { - updateCursor(controlPoint); - mCanvas.hover(e); - mCanvas.getPreviewManager().moved(controlPoint); - } - } - - // --- MouseListener --- - - @Override - public void mouseUp(MouseEvent e) { - ControlPoint mousePos = ControlPoint.create(mCanvas, e); - - if (mCurrentGesture == null) { - // If clicking on a configuration preview, just process it there - if (mCanvas.getPreviewManager().click(mousePos)) { - return; - } - - // Just a click, select - Pair<SelectionItem, SelectionHandle> handlePair = - mCanvas.getSelectionManager().findHandle(mousePos); - if (handlePair == null) { - mCanvas.getSelectionManager().select(e); - } - } - if (mCurrentGesture == null) { - updateCursor(mousePos); - } else if (mCurrentGesture instanceof DropGesture) { - // Mouse Up shouldn't be delivered in the middle of a drag & drop - - // but this can happen on some versions of Linux - // (see http://code.google.com/p/android/issues/detail?id=19057 ) - // and if we process the mouseUp it will abort the remainder of - // the drag & drop operation, so ignore this event! - } else { - finishGesture(mousePos, false); - } - mCanvas.redraw(); - } - - @Override - public void mouseDown(MouseEvent e) { - mLastMouseX = e.x; - mLastMouseY = e.y; - mLastStateMask = e.stateMask; - - // Not yet used. Should be, for Mac and Linux. - } - - @Override - public void mouseDoubleClick(MouseEvent e) { - // SWT delivers a double click event even if you click two different buttons - // in rapid succession. In any case, we only want to let you double click the - // first button to warp to XML: - if (e.button == 1) { - // Warp to the text editor and show the corresponding XML for the - // double-clicked widget - LayoutPoint p = ControlPoint.create(mCanvas, e).toLayout(); - CanvasViewInfo vi = mCanvas.getViewHierarchy().findViewInfoAt(p); - if (vi != null) { - mCanvas.show(vi); - } - } - } - - // --- MouseTrackListener --- - - @Override - public void mouseEnter(MouseEvent e) { - ControlPoint mousePos = ControlPoint.create(mCanvas, e); - mCanvas.getPreviewManager().enter(mousePos); - } - - @Override - public void mouseExit(MouseEvent e) { - ControlPoint mousePos = ControlPoint.create(mCanvas, e); - mCanvas.getPreviewManager().exit(mousePos); - } - - @Override - public void mouseHover(MouseEvent e) { - } - - // --- KeyListener --- - - @Override - public void keyPressed(KeyEvent e) { - mLastStateMask = e.stateMask; - // Workaround for the fact that in keyPressed the current state - // mask is not yet updated - if (e.keyCode == SWT.SHIFT) { - mLastStateMask |= SWT.MOD2; - } - if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_DARWIN) { - if (e.keyCode == SWT.COMMAND) { - mLastStateMask |= SWT.MOD1; - } - } else { - if (e.keyCode == SWT.CTRL) { - mLastStateMask |= SWT.MOD1; - } - } - - // Give gestures a first chance to see and consume the key press - if (mCurrentGesture != null) { - // unless it's "Escape", which cancels the gesture - if (e.keyCode == SWT.ESC) { - ControlPoint controlPoint = ControlPoint.create(mCanvas, - mLastMouseX, mLastMouseY); - finishGesture(controlPoint, true); - return; - } - - if (mCurrentGesture.keyPressed(e)) { - return; - } - } - - // Fall back to canvas actions for the key press - mCanvas.handleKeyPressed(e); - } - - @Override - public void keyReleased(KeyEvent e) { - mLastStateMask = e.stateMask; - // Workaround for the fact that in keyPressed the current state - // mask is not yet updated - if (e.keyCode == SWT.SHIFT) { - mLastStateMask &= ~SWT.MOD2; - } - if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_DARWIN) { - if (e.keyCode == SWT.COMMAND) { - mLastStateMask &= ~SWT.MOD1; - } - } else { - if (e.keyCode == SWT.CTRL) { - mLastStateMask &= ~SWT.MOD1; - } - } - - if (mCurrentGesture != null) { - mCurrentGesture.keyReleased(e); - } - } - } - - /** Listener for Drag & Drop events. */ - private class CanvasDropListener implements DropTargetListener { - public CanvasDropListener() { - } - - /** - * The cursor has entered the drop target boundaries. {@inheritDoc} - */ - @Override - public void dragEnter(DropTargetEvent event) { - mCanvas.showInvisibleViews(true); - mCanvas.getEditorDelegate().getGraphicalEditor().dismissHoverPalette(); - - if (mCurrentGesture == null) { - Gesture newGesture = mZombieGesture; - if (newGesture == null) { - newGesture = new MoveGesture(mCanvas); - } else { - mZombieGesture = null; - } - startGesture(ControlPoint.create(mCanvas, event), - newGesture, 0); - } - - if (mCurrentGesture instanceof DropGesture) { - ((DropGesture) mCurrentGesture).dragEnter(event); - } - } - - /** - * The cursor is moving over the drop target. {@inheritDoc} - */ - @Override - public void dragOver(DropTargetEvent event) { - if (mCurrentGesture instanceof DropGesture) { - ((DropGesture) mCurrentGesture).dragOver(event); - } - } - - /** - * The cursor has left the drop target boundaries OR data is about to be - * dropped. {@inheritDoc} - */ - @Override - public void dragLeave(DropTargetEvent event) { - if (mCurrentGesture instanceof DropGesture) { - DropGesture dropGesture = (DropGesture) mCurrentGesture; - dropGesture.dragLeave(event); - finishGesture(ControlPoint.create(mCanvas, event), true); - mZombieGesture = dropGesture; - } - - mCanvas.showInvisibleViews(false); - } - - /** - * The drop is about to be performed. The drop target is given a last - * chance to change the nature of the drop. {@inheritDoc} - */ - @Override - public void dropAccept(DropTargetEvent event) { - Gesture gesture = mCurrentGesture != null ? mCurrentGesture : mZombieGesture; - if (gesture instanceof DropGesture) { - ((DropGesture) gesture).dropAccept(event); - } - } - - /** - * The data is being dropped. {@inheritDoc} - */ - @Override - public void drop(final DropTargetEvent event) { - // See if we had a gesture just prior to the drop (we receive a dragLeave - // right before the drop which we don't know whether means the cursor has - // left the canvas for good or just before a drop) - Gesture gesture = mCurrentGesture != null ? mCurrentGesture : mZombieGesture; - mZombieGesture = null; - - if (gesture instanceof DropGesture) { - ((DropGesture) gesture).drop(event); - - finishGesture(ControlPoint.create(mCanvas, event), true); - } - } - - /** - * The operation being performed has changed (e.g. modifier key). - * {@inheritDoc} - */ - @Override - public void dragOperationChanged(DropTargetEvent event) { - if (mCurrentGesture instanceof DropGesture) { - ((DropGesture) mCurrentGesture).dragOperationChanged(event); - } - } - } - - /** - * Our canvas {@link DragSourceListener}. Handles drag being started and - * finished and generating the drag data. - */ - private class CanvasDragSourceListener implements DragSourceListener { - - /** - * The current selection being dragged. This may be a subset of the - * canvas selection due to the "sanitize" pass. Can be empty but never - * null. - */ - private final ArrayList<SelectionItem> mDragSelection = new ArrayList<SelectionItem>(); - - private SimpleElement[] mDragElements; - - /** - * The user has begun the actions required to drag the widget. - * <p/> - * Initiate a drag only if there is one or more item selected. If - * there's none, try to auto-select the one under the cursor. - * {@inheritDoc} - */ - @Override - public void dragStart(DragSourceEvent e) { - LayoutPoint p = LayoutPoint.create(mCanvas, e); - ControlPoint controlPoint = ControlPoint.create(mCanvas, e); - SelectionManager selectionManager = mCanvas.getSelectionManager(); - - // See if the mouse is over a selection handle; if so, start a resizing - // gesture. - Pair<SelectionItem, SelectionHandle> handle = - selectionManager.findHandle(controlPoint); - if (handle != null) { - startGesture(controlPoint, new ResizeGesture(mCanvas, handle.getFirst(), - handle.getSecond()), mLastStateMask); - e.detail = DND.DROP_NONE; - e.doit = false; - mCanvas.redraw(); - return; - } - - // We need a selection (simple or multiple) to do any transfer. - // If there's a selection *and* the cursor is over this selection, - // use all the currently selected elements. - // If there is no selection or the cursor is not over a selected - // element, *change* the selection to match the element under the - // cursor and use that. If nothing can be selected, abort the drag - // operation. - List<SelectionItem> selections = selectionManager.getSelections(); - mDragSelection.clear(); - SelectionItem primary = null; - - if (!selections.isEmpty()) { - // Is the cursor on top of a selected element? - boolean insideSelection = false; - - for (SelectionItem cs : selections) { - if (!cs.isRoot() && cs.getRect().contains(p.x, p.y)) { - primary = cs; - insideSelection = true; - break; - } - } - - if (!insideSelection) { - CanvasViewInfo vi = mCanvas.getViewHierarchy().findViewInfoAt(p); - if (vi != null && !vi.isRoot() && !vi.isHidden()) { - primary = selectionManager.selectSingle(vi); - insideSelection = true; - } - } - - if (insideSelection) { - // We should now have a proper selection that matches the - // cursor. Let's use this one. We make a copy of it since - // the "sanitize" pass below might remove some of the - // selected objects. - if (selections.size() == 1) { - // You are dragging just one element - this might or - // might not be the root, but if it's the root that is - // fine since we will let you drag the root if it is the - // only thing you are dragging. - mDragSelection.addAll(selections); - } else { - // Only drag non-root items. - for (SelectionItem cs : selections) { - if (!cs.isRoot() && !cs.isHidden()) { - mDragSelection.add(cs); - } else if (cs == primary) { - primary = null; - } - } - } - } - } - - // If you are dragging a non-selected item, select it - if (mDragSelection.isEmpty()) { - CanvasViewInfo vi = mCanvas.getViewHierarchy().findViewInfoAt(p); - if (vi != null && !vi.isRoot() && !vi.isHidden()) { - primary = selectionManager.selectSingle(vi); - mDragSelection.addAll(selections); - } - } - - SelectionManager.sanitize(mDragSelection); - - e.doit = !mDragSelection.isEmpty(); - int imageCount = mDragSelection.size(); - if (e.doit) { - mDragElements = SelectionItem.getAsElements(mDragSelection, primary); - GlobalCanvasDragInfo.getInstance().startDrag(mDragElements, - mDragSelection.toArray(new SelectionItem[imageCount]), - mCanvas, new Runnable() { - @Override - public void run() { - mCanvas.getClipboardSupport().deleteSelection("Remove", - mDragSelection); - } - }); - } - - // If you drag on the -background-, we make that into a marquee - // selection - if (!e.doit || (imageCount == 1 - && (mDragSelection.get(0).isRoot() || mDragSelection.get(0).isHidden()))) { - boolean toggle = (mLastStateMask & (SWT.CTRL | SWT.SHIFT | SWT.COMMAND)) != 0; - startGesture(controlPoint, - new MarqueeGesture(mCanvas, toggle), mLastStateMask); - e.detail = DND.DROP_NONE; - e.doit = false; - } else { - // Otherwise, the drag means you are moving something - mCanvas.showInvisibleViews(true); - startGesture(controlPoint, new MoveGesture(mCanvas), 0); - - // Render drag-images: Copy portions of the full screen render. - Image image = mCanvas.getImageOverlay().getImage(); - if (image != null) { - /** - * Transparency of the dragged image ([0-255]). We're using 30% - * translucency to make the image faint and not obscure the drag - * feedback below it. - */ - final byte DRAG_TRANSPARENCY = (byte) (0.3 * 255); - - List<Rectangle> rectangles = new ArrayList<Rectangle>(imageCount); - if (imageCount > 0) { - ImageData data = image.getImageData(); - Rectangle imageRectangle = new Rectangle(0, 0, data.width, data.height); - for (SelectionItem item : mDragSelection) { - Rectangle bounds = item.getRect(); - // Some bounds can be outside the rendered rectangle (for - // example, in an absolute layout, you can have negative - // coordinates), so create the intersection of these bounds. - Rectangle clippedBounds = imageRectangle.intersection(bounds); - rectangles.add(clippedBounds); - } - Rectangle boundingBox = ImageUtils.getBoundingRectangle(rectangles); - double scale = mCanvas.getHorizontalTransform().getScale(); - e.image = SwtUtils.drawRectangles(image, rectangles, boundingBox, scale, - DRAG_TRANSPARENCY); - - // Set the image offset such that we preserve the relative - // distance between the mouse pointer and the top left corner of - // the dragged view - int deltaX = (int) (scale * (boundingBox.x - p.x)); - int deltaY = (int) (scale * (boundingBox.y - p.y)); - e.offsetX = -deltaX; - e.offsetY = -deltaY; - - // View rules may need to know it as well - GlobalCanvasDragInfo dragInfo = GlobalCanvasDragInfo.getInstance(); - Rect dragBounds = null; - int width = (int) (scale * boundingBox.width); - int height = (int) (scale * boundingBox.height); - dragBounds = new Rect(deltaX, deltaY, width, height); - dragInfo.setDragBounds(dragBounds); - - // Record the baseline such that we can perform baseline alignment - // on the node as it's dragged around - NodeProxy firstNode = - mCanvas.getNodeFactory().create(mDragSelection.get(0).getViewInfo()); - dragInfo.setDragBaseline(firstNode.getBaseline()); - } - } - } - - // No hover during drag (since no mouse over events are delivered - // during a drag to keep the hovers up to date anyway) - mCanvas.clearHover(); - - mCanvas.redraw(); - } - - /** - * Callback invoked when data is needed for the event, typically right - * before drop. The drop side decides what type of transfer to use and - * this side must now provide the adequate data. {@inheritDoc} - */ - @Override - public void dragSetData(DragSourceEvent e) { - if (TextTransfer.getInstance().isSupportedType(e.dataType)) { - e.data = SelectionItem.getAsText(mCanvas, mDragSelection); - return; - } - - if (SimpleXmlTransfer.getInstance().isSupportedType(e.dataType)) { - e.data = mDragElements; - return; - } - - // otherwise we failed - e.detail = DND.DROP_NONE; - e.doit = false; - } - - /** - * Callback invoked when the drop has been finished either way. On a - * successful move, remove the originating elements. - */ - @Override - public void dragFinished(DragSourceEvent e) { - // Clear the selection - mDragSelection.clear(); - mDragElements = null; - GlobalCanvasDragInfo.getInstance().stopDrag(); - - finishGesture(ControlPoint.create(mCanvas, e), e.detail == DND.DROP_NONE); - mCanvas.showInvisibleViews(false); - mCanvas.redraw(); - } - } -} |