| /* |
| * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package java.awt.dnd; |
| |
| import java.awt.event.InputEvent; |
| import java.awt.Component; |
| import java.awt.Point; |
| |
| import java.io.InvalidObjectException; |
| import java.util.Collections; |
| import java.util.TooManyListenersException; |
| import java.util.ArrayList; |
| |
| import java.io.IOException; |
| import java.io.ObjectInputStream; |
| import java.io.ObjectOutputStream; |
| import java.io.Serializable; |
| |
| /** |
| * The {@code DragGestureRecognizer} is an |
| * abstract base class for the specification |
| * of a platform-dependent listener that can be associated with a particular |
| * {@code Component} in order to |
| * identify platform-dependent drag initiating gestures. |
| * <p> |
| * The appropriate {@code DragGestureRecognizer} |
| * subclass instance is obtained from the |
| * {@link DragSource} associated with |
| * a particular {@code Component}, or from the {@code Toolkit} object via its |
| * {@link java.awt.Toolkit#createDragGestureRecognizer createDragGestureRecognizer()} |
| * method. |
| * <p> |
| * Once the {@code DragGestureRecognizer} |
| * is associated with a particular {@code Component} |
| * it will register the appropriate listener interfaces on that |
| * {@code Component} |
| * in order to track the input events delivered to the {@code Component}. |
| * <p> |
| * Once the {@code DragGestureRecognizer} identifies a sequence of events |
| * on the {@code Component} as a drag initiating gesture, it will notify |
| * its unicast {@code DragGestureListener} by |
| * invoking its |
| * {@link java.awt.dnd.DragGestureListener#dragGestureRecognized gestureRecognized()} |
| * method. |
| * <P> |
| * When a concrete {@code DragGestureRecognizer} |
| * instance detects a drag initiating |
| * gesture on the {@code Component} it is associated with, |
| * it fires a {@link DragGestureEvent} to |
| * the {@code DragGestureListener} registered on |
| * its unicast event source for {@code DragGestureListener} |
| * events. This {@code DragGestureListener} is responsible |
| * for causing the associated |
| * {@code DragSource} to start the Drag and Drop operation (if |
| * appropriate). |
| * |
| * @author Laurence P. G. Cable |
| * @see java.awt.dnd.DragGestureListener |
| * @see java.awt.dnd.DragGestureEvent |
| * @see java.awt.dnd.DragSource |
| */ |
| |
| public abstract class DragGestureRecognizer implements Serializable { |
| |
| private static final long serialVersionUID = 8996673345831063337L; |
| |
| /** |
| * Construct a new {@code DragGestureRecognizer} |
| * given the {@code DragSource} to be used |
| * in this Drag and Drop operation, the {@code Component} |
| * this {@code DragGestureRecognizer} should "observe" |
| * for drag initiating gestures, the action(s) supported |
| * for this Drag and Drop operation, and the |
| * {@code DragGestureListener} to notify |
| * once a drag initiating gesture has been detected. |
| * |
| * @param ds the {@code DragSource} this |
| * {@code DragGestureRecognizer} |
| * will use to process the Drag and Drop operation |
| * |
| * @param c the {@code Component} |
| * this {@code DragGestureRecognizer} |
| * should "observe" the event stream to, |
| * in order to detect a drag initiating gesture. |
| * If this value is {@code null}, the |
| * {@code DragGestureRecognizer} |
| * is not associated with any {@code Component}. |
| * |
| * @param sa the set (logical OR) of the |
| * {@code DnDConstants} |
| * that this Drag and Drop operation will support |
| * |
| * @param dgl the {@code DragGestureRecognizer} |
| * to notify when a drag gesture is detected |
| * |
| * @throws IllegalArgumentException |
| * if ds is {@code null}. |
| */ |
| |
| protected DragGestureRecognizer(DragSource ds, Component c, int sa, DragGestureListener dgl) { |
| super(); |
| |
| if (ds == null) throw new IllegalArgumentException("null DragSource"); |
| |
| dragSource = ds; |
| component = c; |
| sourceActions = sa & (DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK); |
| |
| try { |
| if (dgl != null) addDragGestureListener(dgl); |
| } catch (TooManyListenersException tmle) { |
| // cant happen ... |
| } |
| } |
| |
| /** |
| * Construct a new {@code DragGestureRecognizer} |
| * given the {@code DragSource} to be used in this |
| * Drag and Drop |
| * operation, the {@code Component} this |
| * {@code DragGestureRecognizer} should "observe" |
| * for drag initiating gestures, and the action(s) |
| * supported for this Drag and Drop operation. |
| * |
| * @param ds the {@code DragSource} this |
| * {@code DragGestureRecognizer} will use to |
| * process the Drag and Drop operation |
| * |
| * @param c the {@code Component} this |
| * {@code DragGestureRecognizer} should "observe" the event |
| * stream to, in order to detect a drag initiating gesture. |
| * If this value is {@code null}, the |
| * {@code DragGestureRecognizer} |
| * is not associated with any {@code Component}. |
| * |
| * @param sa the set (logical OR) of the {@code DnDConstants} |
| * that this Drag and Drop operation will support |
| * |
| * @throws IllegalArgumentException |
| * if ds is {@code null}. |
| */ |
| |
| protected DragGestureRecognizer(DragSource ds, Component c, int sa) { |
| this(ds, c, sa, null); |
| } |
| |
| /** |
| * Construct a new {@code DragGestureRecognizer} |
| * given the {@code DragSource} to be used |
| * in this Drag and Drop operation, and |
| * the {@code Component} this |
| * {@code DragGestureRecognizer} |
| * should "observe" for drag initiating gestures. |
| * |
| * @param ds the {@code DragSource} this |
| * {@code DragGestureRecognizer} |
| * will use to process the Drag and Drop operation |
| * |
| * @param c the {@code Component} |
| * this {@code DragGestureRecognizer} |
| * should "observe" the event stream to, |
| * in order to detect a drag initiating gesture. |
| * If this value is {@code null}, |
| * the {@code DragGestureRecognizer} |
| * is not associated with any {@code Component}. |
| * |
| * @throws IllegalArgumentException |
| * if ds is {@code null}. |
| */ |
| |
| protected DragGestureRecognizer(DragSource ds, Component c) { |
| this(ds, c, DnDConstants.ACTION_NONE); |
| } |
| |
| /** |
| * Construct a new {@code DragGestureRecognizer} |
| * given the {@code DragSource} to be used in this |
| * Drag and Drop operation. |
| * |
| * @param ds the {@code DragSource} this |
| * {@code DragGestureRecognizer} will |
| * use to process the Drag and Drop operation |
| * |
| * @throws IllegalArgumentException |
| * if ds is {@code null}. |
| */ |
| |
| protected DragGestureRecognizer(DragSource ds) { |
| this(ds, null); |
| } |
| |
| /** |
| * register this DragGestureRecognizer's Listeners with the Component |
| * |
| * subclasses must override this method |
| */ |
| |
| protected abstract void registerListeners(); |
| |
| /** |
| * unregister this DragGestureRecognizer's Listeners with the Component |
| * |
| * subclasses must override this method |
| */ |
| |
| protected abstract void unregisterListeners(); |
| |
| /** |
| * This method returns the {@code DragSource} |
| * this {@code DragGestureRecognizer} |
| * will use in order to process the Drag and Drop |
| * operation. |
| * |
| * @return the DragSource |
| */ |
| |
| public DragSource getDragSource() { return dragSource; } |
| |
| /** |
| * This method returns the {@code Component} |
| * that is to be "observed" by the |
| * {@code DragGestureRecognizer} |
| * for drag initiating gestures. |
| * |
| * @return The Component this DragGestureRecognizer |
| * is associated with |
| */ |
| |
| public synchronized Component getComponent() { return component; } |
| |
| /** |
| * set the Component that the DragGestureRecognizer is associated with |
| * |
| * registerListeners() and unregisterListeners() are called as a side |
| * effect as appropriate. |
| * |
| * @param c The {@code Component} or {@code null} |
| */ |
| |
| public synchronized void setComponent(Component c) { |
| if (component != null && dragGestureListener != null) |
| unregisterListeners(); |
| |
| component = c; |
| |
| if (component != null && dragGestureListener != null) |
| registerListeners(); |
| } |
| |
| /** |
| * This method returns an int representing the |
| * type of action(s) this Drag and Drop |
| * operation will support. |
| * |
| * @return the currently permitted source action(s) |
| */ |
| |
| public synchronized int getSourceActions() { return sourceActions; } |
| |
| /** |
| * This method sets the permitted source drag action(s) |
| * for this Drag and Drop operation. |
| * |
| * @param actions the permitted source drag action(s) |
| */ |
| |
| public synchronized void setSourceActions(int actions) { |
| sourceActions = actions & (DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK); |
| } |
| |
| /** |
| * This method returns the first event in the |
| * series of events that initiated |
| * the Drag and Drop operation. |
| * |
| * @return the initial event that triggered the drag gesture |
| */ |
| |
| public InputEvent getTriggerEvent() { return events.isEmpty() ? null : events.get(0); } |
| |
| /** |
| * Reset the Recognizer, if its currently recognizing a gesture, ignore |
| * it. |
| */ |
| |
| public void resetRecognizer() { events.clear(); } |
| |
| /** |
| * Register a new {@code DragGestureListener}. |
| * |
| * @param dgl the {@code DragGestureListener} to register |
| * with this {@code DragGestureRecognizer}. |
| * |
| * @throws java.util.TooManyListenersException if a |
| * {@code DragGestureListener} has already been added. |
| */ |
| |
| public synchronized void addDragGestureListener(DragGestureListener dgl) throws TooManyListenersException { |
| if (dragGestureListener != null) |
| throw new TooManyListenersException(); |
| else { |
| dragGestureListener = dgl; |
| |
| if (component != null) registerListeners(); |
| } |
| } |
| |
| /** |
| * unregister the current DragGestureListener |
| * |
| * @param dgl the {@code DragGestureListener} to unregister |
| * from this {@code DragGestureRecognizer} |
| * |
| * @throws IllegalArgumentException if |
| * dgl is not (equal to) the currently registered {@code DragGestureListener}. |
| */ |
| |
| public synchronized void removeDragGestureListener(DragGestureListener dgl) { |
| if (dragGestureListener == null || !dragGestureListener.equals(dgl)) |
| throw new IllegalArgumentException(); |
| else { |
| dragGestureListener = null; |
| |
| if (component != null) unregisterListeners(); |
| } |
| } |
| |
| /** |
| * Notify the DragGestureListener that a Drag and Drop initiating |
| * gesture has occurred. Then reset the state of the Recognizer. |
| * |
| * @param dragAction The action initially selected by the users gesture |
| * @param p The point (in Component coords) where the gesture originated |
| */ |
| protected synchronized void fireDragGestureRecognized(int dragAction, Point p) { |
| try { |
| if (dragGestureListener != null) { |
| dragGestureListener.dragGestureRecognized(new DragGestureEvent(this, dragAction, p, events)); |
| } |
| } finally { |
| events.clear(); |
| } |
| } |
| |
| /** |
| * Listeners registered on the Component by this Recognizer shall record |
| * all Events that are recognized as part of the series of Events that go |
| * to comprise a Drag and Drop initiating gesture via this API. |
| * <P> |
| * This method is used by a {@code DragGestureRecognizer} |
| * implementation to add an {@code InputEvent} |
| * subclass (that it believes is one in a series |
| * of events that comprise a Drag and Drop operation) |
| * to the array of events that this |
| * {@code DragGestureRecognizer} maintains internally. |
| * |
| * @param awtie the {@code InputEvent} |
| * to add to this {@code DragGestureRecognizer}'s |
| * internal array of events. Note that {@code null} |
| * is not a valid value, and will be ignored. |
| */ |
| |
| protected synchronized void appendEvent(InputEvent awtie) { |
| events.add(awtie); |
| } |
| |
| /** |
| * Serializes this {@code DragGestureRecognizer}. This method first |
| * performs default serialization. Then, this object's |
| * {@code DragGestureListener} is written out if and only if it can be |
| * serialized. If not, {@code null} is written instead. |
| * |
| * @serialData The default serializable fields, in alphabetical order, |
| * followed by either a {@code DragGestureListener}, or |
| * {@code null}. |
| * @since 1.4 |
| */ |
| private void writeObject(ObjectOutputStream s) throws IOException { |
| s.defaultWriteObject(); |
| |
| s.writeObject(SerializationTester.test(dragGestureListener) |
| ? dragGestureListener : null); |
| } |
| |
| /** |
| * Deserializes this {@code DragGestureRecognizer}. This method first |
| * performs default deserialization for all non-{@code transient} |
| * fields. This object's {@code DragGestureListener} is then |
| * deserialized as well by using the next object in the stream. |
| * |
| * @since 1.4 |
| */ |
| @SuppressWarnings("unchecked") |
| private void readObject(ObjectInputStream s) |
| throws ClassNotFoundException, IOException |
| { |
| ObjectInputStream.GetField f = s.readFields(); |
| |
| DragSource newDragSource = (DragSource)f.get("dragSource", null); |
| if (newDragSource == null) { |
| throw new InvalidObjectException("null DragSource"); |
| } |
| dragSource = newDragSource; |
| |
| component = (Component)f.get("component", null); |
| sourceActions = f.get("sourceActions", 0) & (DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK); |
| events = (ArrayList<InputEvent>)f.get("events", new ArrayList<>(1)); |
| |
| dragGestureListener = (DragGestureListener)s.readObject(); |
| } |
| |
| /* |
| * fields |
| */ |
| |
| /** |
| * The {@code DragSource} |
| * associated with this |
| * {@code DragGestureRecognizer}. |
| * |
| * @serial |
| */ |
| protected DragSource dragSource; |
| |
| /** |
| * The {@code Component} |
| * associated with this {@code DragGestureRecognizer}. |
| * |
| * @serial |
| */ |
| protected Component component; |
| |
| /** |
| * The {@code DragGestureListener} |
| * associated with this {@code DragGestureRecognizer}. |
| */ |
| protected transient DragGestureListener dragGestureListener; |
| |
| /** |
| * An {@code int} representing |
| * the type(s) of action(s) used |
| * in this Drag and Drop operation. |
| * |
| * @serial |
| */ |
| protected int sourceActions; |
| |
| /** |
| * The list of events (in order) that |
| * the {@code DragGestureRecognizer} |
| * "recognized" as a "gesture" that triggers a drag. |
| * |
| * @serial |
| */ |
| protected ArrayList<InputEvent> events = new ArrayList<InputEvent>(1); |
| } |