0N/A/*
2362N/A * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage java.awt.dnd;
0N/A
0N/Aimport java.util.TooManyListenersException;
0N/A
0N/Aimport java.io.IOException;
0N/Aimport java.io.ObjectInputStream;
0N/Aimport java.io.ObjectOutputStream;
0N/Aimport java.io.Serializable;
0N/A
0N/Aimport java.awt.Component;
0N/Aimport java.awt.Dimension;
0N/Aimport java.awt.GraphicsEnvironment;
0N/Aimport java.awt.HeadlessException;
0N/Aimport java.awt.Insets;
0N/Aimport java.awt.Point;
0N/Aimport java.awt.Rectangle;
0N/Aimport java.awt.Toolkit;
0N/Aimport java.awt.event.ActionEvent;
0N/Aimport java.awt.event.ActionListener;
0N/Aimport java.awt.datatransfer.FlavorMap;
0N/Aimport java.awt.datatransfer.SystemFlavorMap;
0N/Aimport javax.swing.Timer;
0N/Aimport java.awt.peer.ComponentPeer;
0N/Aimport java.awt.peer.LightweightPeer;
0N/Aimport java.awt.dnd.peer.DropTargetPeer;
0N/A
0N/A
0N/A/**
0N/A * The <code>DropTarget</code> is associated
0N/A * with a <code>Component</code> when that <code>Component</code>
0N/A * wishes
0N/A * to accept drops during Drag and Drop operations.
0N/A * <P>
0N/A * Each
0N/A * <code>DropTarget</code> is associated with a <code>FlavorMap</code>.
0N/A * The default <code>FlavorMap</code> hereafter designates the
0N/A * <code>FlavorMap</code> returned by <code>SystemFlavorMap.getDefaultFlavorMap()</code>.
0N/A *
0N/A * @since 1.2
0N/A */
0N/A
0N/Apublic class DropTarget implements DropTargetListener, Serializable {
0N/A
0N/A private static final long serialVersionUID = -6283860791671019047L;
0N/A
0N/A /**
0N/A * Creates a new DropTarget given the <code>Component</code>
0N/A * to associate itself with, an <code>int</code> representing
0N/A * the default acceptable action(s) to
0N/A * support, a <code>DropTargetListener</code>
0N/A * to handle event processing, a <code>boolean</code> indicating
0N/A * if the <code>DropTarget</code> is currently accepting drops, and
0N/A * a <code>FlavorMap</code> to use (or null for the default <CODE>FlavorMap</CODE>).
0N/A * <P>
0N/A * The Component will receive drops only if it is enabled.
0N/A * @param c The <code>Component</code> with which this <code>DropTarget</code> is associated
0N/A * @param ops The default acceptable actions for this <code>DropTarget</code>
0N/A * @param dtl The <code>DropTargetListener</code> for this <code>DropTarget</code>
0N/A * @param act Is the <code>DropTarget</code> accepting drops.
0N/A * @param fm The <code>FlavorMap</code> to use, or null for the default <CODE>FlavorMap</CODE>
0N/A * @exception HeadlessException if GraphicsEnvironment.isHeadless()
0N/A * returns true
0N/A * @see java.awt.GraphicsEnvironment#isHeadless
0N/A */
0N/A public DropTarget(Component c, int ops, DropTargetListener dtl,
0N/A boolean act, FlavorMap fm)
0N/A throws HeadlessException
0N/A {
0N/A if (GraphicsEnvironment.isHeadless()) {
0N/A throw new HeadlessException();
0N/A }
0N/A
0N/A component = c;
0N/A
0N/A setDefaultActions(ops);
0N/A
0N/A if (dtl != null) try {
0N/A addDropTargetListener(dtl);
0N/A } catch (TooManyListenersException tmle) {
0N/A // do nothing!
0N/A }
0N/A
0N/A if (c != null) {
0N/A c.setDropTarget(this);
0N/A setActive(act);
0N/A }
0N/A
86N/A if (fm != null) {
86N/A flavorMap = fm;
86N/A } else {
86N/A flavorMap = SystemFlavorMap.getDefaultFlavorMap();
86N/A }
0N/A }
0N/A
0N/A /**
0N/A * Creates a <code>DropTarget</code> given the <code>Component</code>
0N/A * to associate itself with, an <code>int</code> representing
0N/A * the default acceptable action(s)
0N/A * to support, a <code>DropTargetListener</code>
0N/A * to handle event processing, and a <code>boolean</code> indicating
0N/A * if the <code>DropTarget</code> is currently accepting drops.
0N/A * <P>
0N/A * The Component will receive drops only if it is enabled.
0N/A * @param c The <code>Component</code> with which this <code>DropTarget</code> is associated
0N/A * @param ops The default acceptable actions for this <code>DropTarget</code>
0N/A * @param dtl The <code>DropTargetListener</code> for this <code>DropTarget</code>
0N/A * @param act Is the <code>DropTarget</code> accepting drops.
0N/A * @exception HeadlessException if GraphicsEnvironment.isHeadless()
0N/A * returns true
0N/A * @see java.awt.GraphicsEnvironment#isHeadless
0N/A */
0N/A public DropTarget(Component c, int ops, DropTargetListener dtl,
0N/A boolean act)
0N/A throws HeadlessException
0N/A {
0N/A this(c, ops, dtl, act, null);
0N/A }
0N/A
0N/A /**
0N/A * Creates a <code>DropTarget</code>.
0N/A * @exception HeadlessException if GraphicsEnvironment.isHeadless()
0N/A * returns true
0N/A * @see java.awt.GraphicsEnvironment#isHeadless
0N/A */
0N/A public DropTarget() throws HeadlessException {
0N/A this(null, DnDConstants.ACTION_COPY_OR_MOVE, null, true, null);
0N/A }
0N/A
0N/A /**
0N/A * Creates a <code>DropTarget</code> given the <code>Component</code>
0N/A * to associate itself with, and the <code>DropTargetListener</code>
0N/A * to handle event processing.
0N/A * <P>
0N/A * The Component will receive drops only if it is enabled.
0N/A * @param c The <code>Component</code> with which this <code>DropTarget</code> is associated
0N/A * @param dtl The <code>DropTargetListener</code> for this <code>DropTarget</code>
0N/A * @exception HeadlessException if GraphicsEnvironment.isHeadless()
0N/A * returns true
0N/A * @see java.awt.GraphicsEnvironment#isHeadless
0N/A */
0N/A public DropTarget(Component c, DropTargetListener dtl)
0N/A throws HeadlessException
0N/A {
0N/A this(c, DnDConstants.ACTION_COPY_OR_MOVE, dtl, true, null);
0N/A }
0N/A
0N/A /**
0N/A * Creates a <code>DropTarget</code> given the <code>Component</code>
0N/A * to associate itself with, an <code>int</code> representing
0N/A * the default acceptable action(s) to support, and a
0N/A * <code>DropTargetListener</code> to handle event processing.
0N/A * <P>
0N/A * The Component will receive drops only if it is enabled.
0N/A * @param c The <code>Component</code> with which this <code>DropTarget</code> is associated
0N/A * @param ops The default acceptable actions for this <code>DropTarget</code>
0N/A * @param dtl The <code>DropTargetListener</code> for this <code>DropTarget</code>
0N/A * @exception HeadlessException if GraphicsEnvironment.isHeadless()
0N/A * returns true
0N/A * @see java.awt.GraphicsEnvironment#isHeadless
0N/A */
0N/A public DropTarget(Component c, int ops, DropTargetListener dtl)
0N/A throws HeadlessException
0N/A {
0N/A this(c, ops, dtl, true);
0N/A }
0N/A
0N/A /**
0N/A * Note: this interface is required to permit the safe association
0N/A * of a DropTarget with a Component in one of two ways, either:
0N/A * <code> component.setDropTarget(droptarget); </code>
0N/A * or <code> droptarget.setComponent(component); </code>
0N/A * <P>
0N/A * The Component will receive drops only if it is enabled.
0N/A * @param c The new <code>Component</code> this <code>DropTarget</code>
0N/A * is to be associated with.<P>
0N/A */
0N/A
0N/A public synchronized void setComponent(Component c) {
0N/A if (component == c || component != null && component.equals(c))
0N/A return;
0N/A
0N/A Component old;
0N/A ComponentPeer oldPeer = null;
0N/A
0N/A if ((old = component) != null) {
0N/A clearAutoscroll();
0N/A
0N/A component = null;
0N/A
0N/A if (componentPeer != null) {
0N/A oldPeer = componentPeer;
0N/A removeNotify(componentPeer);
0N/A }
0N/A
0N/A old.setDropTarget(null);
0N/A
0N/A }
0N/A
0N/A if ((component = c) != null) try {
0N/A c.setDropTarget(this);
0N/A } catch (Exception e) { // undo the change
0N/A if (old != null) {
0N/A old.setDropTarget(this);
0N/A addNotify(oldPeer);
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Gets the <code>Component</code> associated
0N/A * with this <code>DropTarget</code>.
0N/A * <P>
0N/A * @return the current <code>Component</code>
0N/A */
0N/A
0N/A public synchronized Component getComponent() {
0N/A return component;
0N/A }
0N/A
0N/A /**
0N/A * Sets the default acceptable actions for this <code>DropTarget</code>
0N/A * <P>
0N/A * @param ops the default actions
0N/A * <P>
0N/A * @see java.awt.dnd.DnDConstants
0N/A */
0N/A
0N/A public void setDefaultActions(int ops) {
0N/A getDropTargetContext().setTargetActions(ops & (DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_REFERENCE));
0N/A }
0N/A
0N/A /*
0N/A * Called by DropTargetContext.setTargetActions()
0N/A * with appropriate synchronization.
0N/A */
0N/A void doSetDefaultActions(int ops) {
0N/A actions = ops;
0N/A }
0N/A
0N/A /**
0N/A * Gets an <code>int</code> representing the
0N/A * current action(s) supported by this <code>DropTarget</code>.
0N/A * <P>
0N/A * @return the current default actions
0N/A */
0N/A
0N/A public int getDefaultActions() {
0N/A return actions;
0N/A }
0N/A
0N/A /**
0N/A * Sets the DropTarget active if <code>true</code>,
0N/A * inactive if <code>false</code>.
0N/A * <P>
0N/A * @param isActive sets the <code>DropTarget</code> (in)active.
0N/A */
0N/A
0N/A public synchronized void setActive(boolean isActive) {
0N/A if (isActive != active) {
0N/A active = isActive;
0N/A }
0N/A
0N/A if (!active) clearAutoscroll();
0N/A }
0N/A
0N/A /**
0N/A * Reports whether or not
0N/A * this <code>DropTarget</code>
0N/A * is currently active (ready to accept drops).
0N/A * <P>
0N/A * @return <CODE>true</CODE> if active, <CODE>false</CODE> if not
0N/A */
0N/A
0N/A public boolean isActive() {
0N/A return active;
0N/A }
0N/A
0N/A /**
0N/A * Adds a new <code>DropTargetListener</code> (UNICAST SOURCE).
0N/A * <P>
0N/A * @param dtl The new <code>DropTargetListener</code>
0N/A * <P>
0N/A * @throws <code>TooManyListenersException</code> if a
0N/A * <code>DropTargetListener</code> is already added to this
0N/A * <code>DropTarget</code>.
0N/A */
0N/A
0N/A public synchronized void addDropTargetListener(DropTargetListener dtl) throws TooManyListenersException {
0N/A if (dtl == null) return;
0N/A
0N/A if (equals(dtl)) throw new IllegalArgumentException("DropTarget may not be its own Listener");
0N/A
0N/A if (dtListener == null)
0N/A dtListener = dtl;
0N/A else
0N/A throw new TooManyListenersException();
0N/A }
0N/A
0N/A /**
0N/A * Removes the current <code>DropTargetListener</code> (UNICAST SOURCE).
0N/A * <P>
0N/A * @param dtl the DropTargetListener to deregister.
0N/A */
0N/A
0N/A public synchronized void removeDropTargetListener(DropTargetListener dtl) {
0N/A if (dtl != null && dtListener != null) {
0N/A if(dtListener.equals(dtl))
0N/A dtListener = null;
0N/A else
0N/A throw new IllegalArgumentException("listener mismatch");
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Calls <code>dragEnter</code> on the registered
0N/A * <code>DropTargetListener</code> and passes it
0N/A * the specified <code>DropTargetDragEvent</code>.
0N/A * Has no effect if this <code>DropTarget</code>
0N/A * is not active.
0N/A *
0N/A * @param dtde the <code>DropTargetDragEvent</code>
0N/A *
0N/A * @throws NullPointerException if this <code>DropTarget</code>
0N/A * is active and <code>dtde</code> is <code>null</code>
0N/A *
0N/A * @see #isActive
0N/A */
0N/A public synchronized void dragEnter(DropTargetDragEvent dtde) {
0N/A if (!active) return;
0N/A
0N/A if (dtListener != null) {
0N/A dtListener.dragEnter(dtde);
0N/A } else
0N/A dtde.getDropTargetContext().setTargetActions(DnDConstants.ACTION_NONE);
0N/A
0N/A initializeAutoscrolling(dtde.getLocation());
0N/A }
0N/A
0N/A /**
0N/A * Calls <code>dragOver</code> on the registered
0N/A * <code>DropTargetListener</code> and passes it
0N/A * the specified <code>DropTargetDragEvent</code>.
0N/A * Has no effect if this <code>DropTarget</code>
0N/A * is not active.
0N/A *
0N/A * @param dtde the <code>DropTargetDragEvent</code>
0N/A *
0N/A * @throws NullPointerException if this <code>DropTarget</code>
0N/A * is active and <code>dtde</code> is <code>null</code>
0N/A *
0N/A * @see #isActive
0N/A */
0N/A public synchronized void dragOver(DropTargetDragEvent dtde) {
0N/A if (!active) return;
0N/A
0N/A if (dtListener != null && active) dtListener.dragOver(dtde);
0N/A
0N/A updateAutoscroll(dtde.getLocation());
0N/A }
0N/A
0N/A /**
0N/A * Calls <code>dropActionChanged</code> on the registered
0N/A * <code>DropTargetListener</code> and passes it
0N/A * the specified <code>DropTargetDragEvent</code>.
0N/A * Has no effect if this <code>DropTarget</code>
0N/A * is not active.
0N/A *
0N/A * @param dtde the <code>DropTargetDragEvent</code>
0N/A *
0N/A * @throws NullPointerException if this <code>DropTarget</code>
0N/A * is active and <code>dtde</code> is <code>null</code>
0N/A *
0N/A * @see #isActive
0N/A */
0N/A public synchronized void dropActionChanged(DropTargetDragEvent dtde) {
0N/A if (!active) return;
0N/A
0N/A if (dtListener != null) dtListener.dropActionChanged(dtde);
0N/A
0N/A updateAutoscroll(dtde.getLocation());
0N/A }
0N/A
0N/A /**
0N/A * Calls <code>dragExit</code> on the registered
0N/A * <code>DropTargetListener</code> and passes it
0N/A * the specified <code>DropTargetEvent</code>.
0N/A * Has no effect if this <code>DropTarget</code>
0N/A * is not active.
0N/A * <p>
0N/A * This method itself does not throw any exception
0N/A * for null parameter but for exceptions thrown by
0N/A * the respective method of the listener.
0N/A *
0N/A * @param dte the <code>DropTargetEvent</code>
0N/A *
0N/A * @see #isActive
0N/A */
0N/A public synchronized void dragExit(DropTargetEvent dte) {
0N/A if (!active) return;
0N/A
0N/A if (dtListener != null && active) dtListener.dragExit(dte);
0N/A
0N/A clearAutoscroll();
0N/A }
0N/A
0N/A /**
0N/A * Calls <code>drop</code> on the registered
0N/A * <code>DropTargetListener</code> and passes it
0N/A * the specified <code>DropTargetDropEvent</code>
0N/A * if this <code>DropTarget</code> is active.
0N/A *
0N/A * @param dtde the <code>DropTargetDropEvent</code>
0N/A *
0N/A * @throws NullPointerException if <code>dtde</code> is null
0N/A * and at least one of the following is true: this
0N/A * <code>DropTarget</code> is not active, or there is
0N/A * no a <code>DropTargetListener</code> registered.
0N/A *
0N/A * @see #isActive
0N/A */
0N/A public synchronized void drop(DropTargetDropEvent dtde) {
0N/A clearAutoscroll();
0N/A
0N/A if (dtListener != null && active)
0N/A dtListener.drop(dtde);
0N/A else { // we should'nt get here ...
0N/A dtde.rejectDrop();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Gets the <code>FlavorMap</code>
0N/A * associated with this <code>DropTarget</code>.
0N/A * If no <code>FlavorMap</code> has been set for this
0N/A * <code>DropTarget</code>, it is associated with the default
0N/A * <code>FlavorMap</code>.
0N/A * <P>
0N/A * @return the FlavorMap for this DropTarget
0N/A */
0N/A
0N/A public FlavorMap getFlavorMap() { return flavorMap; }
0N/A
0N/A /**
0N/A * Sets the <code>FlavorMap</code> associated
0N/A * with this <code>DropTarget</code>.
0N/A * <P>
0N/A * @param fm the new <code>FlavorMap</code>, or null to
0N/A * associate the default FlavorMap with this DropTarget.
0N/A */
0N/A
0N/A public void setFlavorMap(FlavorMap fm) {
0N/A flavorMap = fm == null ? SystemFlavorMap.getDefaultFlavorMap() : fm;
0N/A }
0N/A
0N/A /**
0N/A * Notify the DropTarget that it has been associated with a Component
0N/A *
0N/A **********************************************************************
0N/A * This method is usually called from java.awt.Component.addNotify() of
0N/A * the Component associated with this DropTarget to notify the DropTarget
0N/A * that a ComponentPeer has been associated with that Component.
0N/A *
0N/A * Calling this method, other than to notify this DropTarget of the
0N/A * association of the ComponentPeer with the Component may result in
0N/A * a malfunction of the DnD system.
0N/A **********************************************************************
0N/A * <P>
0N/A * @param peer The Peer of the Component we are associated with!
0N/A *
0N/A */
0N/A
0N/A public void addNotify(ComponentPeer peer) {
0N/A if (peer == componentPeer) return;
0N/A
0N/A componentPeer = peer;
0N/A
0N/A for (Component c = component;
0N/A c != null && peer instanceof LightweightPeer; c = c.getParent()) {
0N/A peer = c.getPeer();
0N/A }
0N/A
0N/A if (peer instanceof DropTargetPeer) {
0N/A nativePeer = peer;
0N/A ((DropTargetPeer)peer).addDropTarget(this);
0N/A } else {
0N/A nativePeer = null;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Notify the DropTarget that it has been disassociated from a Component
0N/A *
0N/A **********************************************************************
0N/A * This method is usually called from java.awt.Component.removeNotify() of
0N/A * the Component associated with this DropTarget to notify the DropTarget
0N/A * that a ComponentPeer has been disassociated with that Component.
0N/A *
0N/A * Calling this method, other than to notify this DropTarget of the
0N/A * disassociation of the ComponentPeer from the Component may result in
0N/A * a malfunction of the DnD system.
0N/A **********************************************************************
0N/A * <P>
0N/A * @param peer The Peer of the Component we are being disassociated from!
0N/A */
0N/A
0N/A public void removeNotify(ComponentPeer peer) {
0N/A if (nativePeer != null)
0N/A ((DropTargetPeer)nativePeer).removeDropTarget(this);
0N/A
0N/A componentPeer = nativePeer = null;
0N/A }
0N/A
0N/A /**
0N/A * Gets the <code>DropTargetContext</code> associated
0N/A * with this <code>DropTarget</code>.
0N/A * <P>
0N/A * @return the <code>DropTargetContext</code> associated with this <code>DropTarget</code>.
0N/A */
0N/A
0N/A public DropTargetContext getDropTargetContext() {
0N/A return dropTargetContext;
0N/A }
0N/A
0N/A /**
0N/A * Creates the DropTargetContext associated with this DropTarget.
0N/A * Subclasses may override this method to instantiate their own
0N/A * DropTargetContext subclass.
0N/A *
0N/A * This call is typically *only* called by the platform's
0N/A * DropTargetContextPeer as a drag operation encounters this
0N/A * DropTarget. Accessing the Context while no Drag is current
0N/A * has undefined results.
0N/A */
0N/A
0N/A protected DropTargetContext createDropTargetContext() {
0N/A return new DropTargetContext(this);
0N/A }
0N/A
0N/A /**
0N/A * Serializes this <code>DropTarget</code>. Performs default serialization,
0N/A * and then writes out this object's <code>DropTargetListener</code> if and
0N/A * only if it can be serialized. If not, <code>null</code> is written
0N/A * instead.
0N/A *
0N/A * @serialData The default serializable fields, in alphabetical order,
0N/A * followed by either a <code>DropTargetListener</code>
0N/A * instance, or <code>null</code>.
0N/A * @since 1.4
0N/A */
0N/A private void writeObject(ObjectOutputStream s) throws IOException {
0N/A s.defaultWriteObject();
0N/A
0N/A s.writeObject(SerializationTester.test(dtListener)
0N/A ? dtListener : null);
0N/A }
0N/A
0N/A /**
0N/A * Deserializes this <code>DropTarget</code>. This method first performs
0N/A * default deserialization for all non-<code>transient</code> fields. An
0N/A * attempt is then made to deserialize this object's
0N/A * <code>DropTargetListener</code> as well. This is first attempted by
0N/A * deserializing the field <code>dtListener</code>, because, in releases
0N/A * prior to 1.4, a non-<code>transient</code> field of this name stored the
0N/A * <code>DropTargetListener</code>. If this fails, the next object in the
0N/A * stream is used instead.
0N/A *
0N/A * @since 1.4
0N/A */
0N/A private void readObject(ObjectInputStream s)
0N/A throws ClassNotFoundException, IOException
0N/A {
0N/A ObjectInputStream.GetField f = s.readFields();
0N/A
0N/A try {
0N/A dropTargetContext =
0N/A (DropTargetContext)f.get("dropTargetContext", null);
0N/A } catch (IllegalArgumentException e) {
0N/A // Pre-1.4 support. 'dropTargetContext' was previoulsy transient
0N/A }
0N/A if (dropTargetContext == null) {
0N/A dropTargetContext = createDropTargetContext();
0N/A }
0N/A
0N/A component = (Component)f.get("component", null);
0N/A actions = f.get("actions", DnDConstants.ACTION_COPY_OR_MOVE);
0N/A active = f.get("active", true);
0N/A
0N/A // Pre-1.4 support. 'dtListener' was previously non-transient
0N/A try {
0N/A dtListener = (DropTargetListener)f.get("dtListener", null);
0N/A } catch (IllegalArgumentException e) {
0N/A // 1.4-compatible byte stream. 'dtListener' was written explicitly
0N/A dtListener = (DropTargetListener)s.readObject();
0N/A }
0N/A }
0N/A
0N/A /*********************************************************************/
0N/A
0N/A /**
0N/A * this protected nested class implements autoscrolling
0N/A */
0N/A
0N/A protected static class DropTargetAutoScroller implements ActionListener {
0N/A
0N/A /**
0N/A * construct a DropTargetAutoScroller
0N/A * <P>
0N/A * @param c the <code>Component</code>
0N/A * @param p the <code>Point</code>
0N/A */
0N/A
0N/A protected DropTargetAutoScroller(Component c, Point p) {
0N/A super();
0N/A
0N/A component = c;
0N/A autoScroll = (Autoscroll)component;
0N/A
0N/A Toolkit t = Toolkit.getDefaultToolkit();
0N/A
0N/A Integer initial = Integer.valueOf(100);
0N/A Integer interval = Integer.valueOf(100);
0N/A
0N/A try {
0N/A initial = (Integer)t.getDesktopProperty("DnD.Autoscroll.initialDelay");
0N/A } catch (Exception e) {
0N/A // ignore
0N/A }
0N/A
0N/A try {
0N/A interval = (Integer)t.getDesktopProperty("DnD.Autoscroll.interval");
0N/A } catch (Exception e) {
0N/A // ignore
0N/A }
0N/A
0N/A timer = new Timer(interval.intValue(), this);
0N/A
0N/A timer.setCoalesce(true);
0N/A timer.setInitialDelay(initial.intValue());
0N/A
0N/A locn = p;
0N/A prev = p;
0N/A
0N/A try {
0N/A hysteresis = ((Integer)t.getDesktopProperty("DnD.Autoscroll.cursorHysteresis")).intValue();
0N/A } catch (Exception e) {
0N/A // ignore
0N/A }
0N/A
0N/A timer.start();
0N/A }
0N/A
0N/A /**
0N/A * update the geometry of the autoscroll region
0N/A */
0N/A
0N/A private void updateRegion() {
0N/A Insets i = autoScroll.getAutoscrollInsets();
0N/A Dimension size = component.getSize();
0N/A
0N/A if (size.width != outer.width || size.height != outer.height)
0N/A outer.reshape(0, 0, size.width, size.height);
0N/A
0N/A if (inner.x != i.left || inner.y != i.top)
0N/A inner.setLocation(i.left, i.top);
0N/A
0N/A int newWidth = size.width - (i.left + i.right);
0N/A int newHeight = size.height - (i.top + i.bottom);
0N/A
0N/A if (newWidth != inner.width || newHeight != inner.height)
0N/A inner.setSize(newWidth, newHeight);
0N/A
0N/A }
0N/A
0N/A /**
0N/A * cause autoscroll to occur
0N/A * <P>
0N/A * @param newLocn the <code>Point</code>
0N/A */
0N/A
0N/A protected synchronized void updateLocation(Point newLocn) {
0N/A prev = locn;
0N/A locn = newLocn;
0N/A
0N/A if (Math.abs(locn.x - prev.x) > hysteresis ||
0N/A Math.abs(locn.y - prev.y) > hysteresis) {
0N/A if (timer.isRunning()) timer.stop();
0N/A } else {
0N/A if (!timer.isRunning()) timer.start();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * cause autoscrolling to stop
0N/A */
0N/A
0N/A protected void stop() { timer.stop(); }
0N/A
0N/A /**
0N/A * cause autoscroll to occur
0N/A * <P>
0N/A * @param e the <code>ActionEvent</code>
0N/A */
0N/A
0N/A public synchronized void actionPerformed(ActionEvent e) {
0N/A updateRegion();
0N/A
0N/A if (outer.contains(locn) && !inner.contains(locn))
0N/A autoScroll.autoscroll(locn);
0N/A }
0N/A
0N/A /*
0N/A * fields
0N/A */
0N/A
0N/A private Component component;
0N/A private Autoscroll autoScroll;
0N/A
0N/A private Timer timer;
0N/A
0N/A private Point locn;
0N/A private Point prev;
0N/A
0N/A private Rectangle outer = new Rectangle();
0N/A private Rectangle inner = new Rectangle();
0N/A
0N/A private int hysteresis = 10;
0N/A }
0N/A
0N/A /*********************************************************************/
0N/A
0N/A /**
0N/A * create an embedded autoscroller
0N/A * <P>
0N/A * @param c the <code>Component</code>
0N/A * @param p the <code>Point</code>
0N/A */
0N/A
0N/A protected DropTargetAutoScroller createDropTargetAutoScroller(Component c, Point p) {
0N/A return new DropTargetAutoScroller(c, p);
0N/A }
0N/A
0N/A /**
0N/A * initialize autoscrolling
0N/A * <P>
0N/A * @param p the <code>Point</code>
0N/A */
0N/A
0N/A protected void initializeAutoscrolling(Point p) {
0N/A if (component == null || !(component instanceof Autoscroll)) return;
0N/A
0N/A autoScroller = createDropTargetAutoScroller(component, p);
0N/A }
0N/A
0N/A /**
0N/A * update autoscrolling with current cursor locn
0N/A * <P>
0N/A * @param dragCursorLocn the <code>Point</code>
0N/A */
0N/A
0N/A protected void updateAutoscroll(Point dragCursorLocn) {
0N/A if (autoScroller != null) autoScroller.updateLocation(dragCursorLocn);
0N/A }
0N/A
0N/A /**
0N/A * clear autoscrolling
0N/A */
0N/A
0N/A protected void clearAutoscroll() {
0N/A if (autoScroller != null) {
0N/A autoScroller.stop();
0N/A autoScroller = null;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * The DropTargetContext associated with this DropTarget.
0N/A *
0N/A * @serial
0N/A */
0N/A private DropTargetContext dropTargetContext = createDropTargetContext();
0N/A
0N/A /**
0N/A * The Component associated with this DropTarget.
0N/A *
0N/A * @serial
0N/A */
0N/A private Component component;
0N/A
0N/A /*
0N/A * That Component's Peer
0N/A */
0N/A private transient ComponentPeer componentPeer;
0N/A
0N/A /*
0N/A * That Component's "native" Peer
0N/A */
0N/A private transient ComponentPeer nativePeer;
0N/A
0N/A
0N/A /**
0N/A * Default permissible actions supported by this DropTarget.
0N/A *
0N/A * @see #setDefaultActions
0N/A * @see #getDefaultActions
0N/A * @serial
0N/A */
0N/A int actions = DnDConstants.ACTION_COPY_OR_MOVE;
0N/A
0N/A /**
0N/A * <code>true</code> if the DropTarget is accepting Drag & Drop operations.
0N/A *
0N/A * @serial
0N/A */
0N/A boolean active = true;
0N/A
0N/A /*
0N/A * the auto scrolling object
0N/A */
0N/A
0N/A private transient DropTargetAutoScroller autoScroller;
0N/A
0N/A /*
0N/A * The delegate
0N/A */
0N/A
0N/A private transient DropTargetListener dtListener;
0N/A
0N/A /*
0N/A * The FlavorMap
0N/A */
0N/A
86N/A private transient FlavorMap flavorMap;
0N/A}