| /******************************************************************************* |
| * Copyright (c) 2004, 2006 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.ui.presentations; |
| |
| import org.eclipse.jface.util.Geometry; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Event; |
| import org.eclipse.swt.widgets.Listener; |
| import org.eclipse.ui.internal.dnd.DragUtil; |
| |
| /** |
| * Contains various utility methods for Presentation authors |
| * |
| * @since 3.0 |
| */ |
| public class PresentationUtil { |
| private static Point anchor; |
| |
| private final static int HYSTERESIS = 16; |
| |
| private static int initialMouseButton = 0; |
| |
| private final static String LISTENER_ID = PresentationUtil.class.getName() |
| + ".dragListener"; //$NON-NLS-1$ |
| |
| private static Event dragEvent; |
| |
| private static Listener currentListener = null; |
| |
| private static Control dragSource; |
| |
| private static Listener dragListener = new Listener() { |
| public void handleEvent(Event event) { |
| dragEvent = event; |
| if (dragSource != event.widget) { |
| dragSource = null; |
| currentListener = null; |
| } |
| } |
| }; |
| |
| /** |
| * Returns whether the mouse has moved enough to warrant |
| * opening a tracker. |
| */ |
| private static boolean hasMovedEnough(Event event) { |
| return Geometry.distanceSquared(DragUtil.getEventLoc(event), anchor) >= HYSTERESIS |
| * HYSTERESIS; |
| } |
| |
| private static Listener moveListener = new Listener() { |
| public void handleEvent(Event event) { |
| handleMouseMove(event); |
| } |
| }; |
| |
| private static Listener clickListener = new Listener() { |
| public void handleEvent(Event e) { |
| handleMouseClick(e); |
| } |
| }; |
| |
| private static Listener mouseDownListener = new Listener() { |
| public void handleEvent(Event event) { |
| if (event.widget instanceof Control) { |
| // Remember the button that started the drag so we |
| // can forward it on the call to the 'externalDragListener' |
| initialMouseButton = event.button; |
| |
| dragSource = (Control) event.widget; |
| currentListener = (Listener) dragSource.getData(LISTENER_ID); |
| anchor = DragUtil.getEventLoc(event); |
| |
| if (dragEvent != null && (dragEvent.widget != dragSource)) { |
| dragEvent = null; |
| } |
| } |
| } |
| }; |
| |
| private static void handleMouseClick(Event event) { |
| cancelDrag(); |
| } |
| |
| private static void handleMouseMove(Event e) { |
| if (currentListener != null && dragEvent != null && hasMovedEnough(e)) { |
| if (dragSource != null && !dragSource.isDisposed() |
| && dragSource == e.widget) { |
| Event de = dragEvent; |
| |
| // cache the current value so we can restore it later |
| int originalMouseButton = de.button; |
| |
| // Update the button field so that the drag listener |
| // can detect whether or not it's a 'right button' drag |
| de.button = initialMouseButton; |
| |
| Listener l = currentListener; |
| cancelDrag(); |
| l.handleEvent(de); |
| |
| // Restore the event's state so that other listeners see |
| // the original values |
| de.button = originalMouseButton; |
| } else { |
| cancelDrag(); |
| } |
| } |
| } |
| |
| private static void cancelDrag() { |
| currentListener = null; |
| dragEvent = null; |
| dragSource = null; |
| |
| initialMouseButton = 0; |
| } |
| |
| /** |
| * Adds a drag listener to the given control. The behavior is very similar |
| * to control.addListener(SWT.DragDetect, dragListener), however the listener |
| * attached by this method is less sensitive. The drag event is only fired |
| * once the user moves the cursor more than HYSTERESIS pixels. |
| * <p> |
| * This is useful for registering a listener that will trigger an editor or |
| * view drag, since an overly sensitive drag listener can cause users to accidentally |
| * drag views when trying to select a tab.</p> |
| * <p> |
| * Currently, only one such drag listener can be registered at a time. </p> |
| * |
| * @param control the control containing the drag listener |
| * @param externalDragListener the drag listener to attach |
| */ |
| public static void addDragListener(Control control, |
| Listener externalDragListener) { |
| control.addListener(SWT.DragDetect, dragListener); |
| control.addListener(SWT.MouseUp, clickListener); |
| control.addListener(SWT.MouseDoubleClick, clickListener); |
| control.addListener(SWT.MouseDown, mouseDownListener); |
| control.addListener(SWT.MouseMove, moveListener); |
| control.setData(LISTENER_ID, externalDragListener); |
| } |
| |
| /** |
| * Removes a drag listener that was previously attached using addDragListener |
| * |
| * @param control the control containing the drag listener |
| * @param externalDragListener the drag listener to remove |
| */ |
| public static void removeDragListener(Control control, |
| Listener externalDragListener) { |
| control.removeListener(SWT.DragDetect, dragListener); |
| control.removeListener(SWT.MouseUp, clickListener); |
| control.removeListener(SWT.MouseDoubleClick, clickListener); |
| control.removeListener(SWT.MouseDown, mouseDownListener); |
| control.removeListener(SWT.MouseMove, moveListener); |
| control.setData(LISTENER_ID, null); |
| if (externalDragListener == currentListener) { |
| cancelDrag(); |
| } |
| } |
| |
| } |