/* * Copyright (c) 1997, 2015, 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.Component; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.dnd.peer.DropTargetContextPeer; import java.io.IOException; import java.io.Serializable; import java.util.Arrays; import java.util.List; /** * A DropTargetContext is created * whenever the logical cursor associated * with a Drag and Drop operation coincides with the visible geometry of * a Component associated with a DropTarget. * The DropTargetContext provides * the mechanism for a potential receiver * of a drop operation to both provide the end user with the appropriate * drag under feedback, but also to effect the subsequent data transfer * if appropriate. * * @since 1.2 */ public class DropTargetContext implements Serializable { private static final long serialVersionUID = -634158968993743371L; /** * Construct a DropTargetContext * given a specified DropTarget. * * @param dt the DropTarget to associate with */ DropTargetContext(DropTarget dt) { super(); dropTarget = dt; } /** * This method returns the DropTarget associated with this * DropTargetContext. * * @return the DropTarget associated with this DropTargetContext */ public DropTarget getDropTarget() { return dropTarget; } /** * This method returns the Component associated with * this DropTargetContext. * * @return the Component associated with this Context */ public Component getComponent() { return dropTarget.getComponent(); } /** * Called when associated with the peer object. * * @param dtcp the peer object * @throws IllegalArgumentException if provided peer is not supported */ public void addNotify(final Object dtcp) throws IllegalArgumentException { if (dtcp instanceof DropTargetContextPeer) { dropTargetContextPeer = (DropTargetContextPeer) dtcp; } else { throw new IllegalArgumentException("Unsupported peer"); } } /** * Called when disassociated with the DropTargetContextPeer. */ public void removeNotify() { dropTargetContextPeer = null; transferable = null; } /** * This method sets the current actions acceptable to * this DropTarget. * * @param actions an int representing the supported action(s) */ protected void setTargetActions(int actions) { DropTargetContextPeer peer = getDropTargetContextPeer(); if (peer != null) { synchronized (peer) { peer.setTargetActions(actions); getDropTarget().doSetDefaultActions(actions); } } else { getDropTarget().doSetDefaultActions(actions); } } /** * This method returns an int representing the * current actions this DropTarget will accept. * * @return the current actions acceptable to this DropTarget */ protected int getTargetActions() { DropTargetContextPeer peer = getDropTargetContextPeer(); return ((peer != null) ? peer.getTargetActions() : dropTarget.getDefaultActions() ); } /** * This method signals that the drop is completed and * if it was successful or not. * * @param success true for success, false if not * * @throws InvalidDnDOperationException if a drop is not outstanding/extant */ public void dropComplete(boolean success) throws InvalidDnDOperationException{ DropTargetContextPeer peer = getDropTargetContextPeer(); if (peer != null) { peer.dropComplete(success); } } /** * accept the Drag. * * @param dragOperation the supported action(s) */ protected void acceptDrag(int dragOperation) { DropTargetContextPeer peer = getDropTargetContextPeer(); if (peer != null) { peer.acceptDrag(dragOperation); } } /** * reject the Drag. */ protected void rejectDrag() { DropTargetContextPeer peer = getDropTargetContextPeer(); if (peer != null) { peer.rejectDrag(); } } /** * called to signal that the drop is acceptable * using the specified operation. * must be called during DropTargetListener.drop method invocation. * * @param dropOperation the supported action(s) */ protected void acceptDrop(int dropOperation) { DropTargetContextPeer peer = getDropTargetContextPeer(); if (peer != null) { peer.acceptDrop(dropOperation); } } /** * called to signal that the drop is unacceptable. * must be called during DropTargetListener.drop method invocation. */ protected void rejectDrop() { DropTargetContextPeer peer = getDropTargetContextPeer(); if (peer != null) { peer.rejectDrop(); } } /** * get the available DataFlavors of the * Transferable operand of this operation. * * @return a DataFlavor[] containing the * supported DataFlavors of the * Transferable operand. */ protected DataFlavor[] getCurrentDataFlavors() { DropTargetContextPeer peer = getDropTargetContextPeer(); return peer != null ? peer.getTransferDataFlavors() : new DataFlavor[0]; } /** * This method returns a the currently available DataFlavors * of the Transferable operand * as a java.util.List. * * @return the currently available * DataFlavors as a java.util.List */ protected List getCurrentDataFlavorsAsList() { return Arrays.asList(getCurrentDataFlavors()); } /** * This method returns a boolean * indicating if the given DataFlavor is * supported by this DropTargetContext. * * @param df the DataFlavor * * @return if the DataFlavor specified is supported */ protected boolean isDataFlavorSupported(DataFlavor df) { return getCurrentDataFlavorsAsList().contains(df); } /** * get the Transferable (proxy) operand of this operation * * @throws InvalidDnDOperationException if a drag is not outstanding/extant * * @return the Transferable */ protected Transferable getTransferable() throws InvalidDnDOperationException { DropTargetContextPeer peer = getDropTargetContextPeer(); if (peer == null) { throw new InvalidDnDOperationException(); } else { if (transferable == null) { Transferable t = peer.getTransferable(); boolean isLocal = peer.isTransferableJVMLocal(); synchronized (this) { if (transferable == null) { transferable = createTransferableProxy(t, isLocal); } } } return transferable; } } /** * Get the DropTargetContextPeer * * @return the platform peer */ DropTargetContextPeer getDropTargetContextPeer() { return dropTargetContextPeer; } /** * Creates a TransferableProxy to proxy for the specified * Transferable. * * @param t the Transferable to be proxied * @param local true if t represents * the result of a local drag-n-drop operation. * @return the new TransferableProxy instance. */ protected Transferable createTransferableProxy(Transferable t, boolean local) { return new TransferableProxy(t, local); } /****************************************************************************/ /** * TransferableProxy is a helper inner class that implements * Transferable interface and serves as a proxy for another * Transferable object which represents data transfer for * a particular drag-n-drop operation. *

* The proxy forwards all requests to the encapsulated transferable * and automatically performs additional conversion on the data * returned by the encapsulated transferable in case of local transfer. */ protected class TransferableProxy implements Transferable { /** * Constructs a TransferableProxy given * a specified Transferable object representing * data transfer for a particular drag-n-drop operation and * a boolean which indicates whether the * drag-n-drop operation is local (within the same JVM). * * @param t the Transferable object * @param local true, if t represents * the result of local drag-n-drop operation */ TransferableProxy(Transferable t, boolean local) { proxy = new sun.awt.datatransfer.TransferableProxy(t, local); transferable = t; isLocal = local; } /** * Returns an array of DataFlavor objects indicating the flavors * the data can be provided in by the encapsulated transferable. * * @return an array of data flavors in which the data can be * provided by the encapsulated transferable */ public DataFlavor[] getTransferDataFlavors() { return proxy.getTransferDataFlavors(); } /** * Returns whether or not the specified data flavor is supported by * the encapsulated transferable. * @param flavor the requested flavor for the data * @return true if the data flavor is supported, * false otherwise */ public boolean isDataFlavorSupported(DataFlavor flavor) { return proxy.isDataFlavorSupported(flavor); } /** * Returns an object which represents the data provided by * the encapsulated transferable for the requested data flavor. *

* In case of local transfer a serialized copy of the object * returned by the encapsulated transferable is provided when * the data is requested in application/x-java-serialized-object * data flavor. * * @param df the requested flavor for the data * @throws IOException if the data is no longer available * in the requested flavor. * @throws UnsupportedFlavorException if the requested data flavor is * not supported. */ public Object getTransferData(DataFlavor df) throws UnsupportedFlavorException, IOException { return proxy.getTransferData(df); } /* * fields */ // We don't need to worry about client code changing the values of // these variables. Since TransferableProxy is a protected class, only // subclasses of DropTargetContext can access it. And DropTargetContext // cannot be subclassed by client code because it does not have a // public constructor. /** * The encapsulated Transferable object. */ protected Transferable transferable; /** * A boolean indicating if the encapsulated * Transferable object represents the result * of local drag-n-drop operation (within the same JVM). */ protected boolean isLocal; private sun.awt.datatransfer.TransferableProxy proxy; } /****************************************************************************/ /* * fields */ /** * The DropTarget associated with this DropTargetContext. * * @serial */ private final DropTarget dropTarget; private transient DropTargetContextPeer dropTargetContextPeer; private transient Transferable transferable; }