/*
* Copyright (c) 1997, 2021, 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.AWTError;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.peer.DragSourceContextPeer;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serial;
import java.io.Serializable;
import java.util.TooManyListenersException;
import sun.awt.AWTAccessor;
import sun.awt.ComponentFactory;
The DragSourceContext
class is responsible for managing the initiator side of the Drag and Drop protocol. In particular, it is responsible for managing drag event notifications to the DragSourceListeners and DragSourceMotionListeners, and providing the Transferable
representing the source data for the drag operation. Note that the DragSourceContext
itself implements the DragSourceListener
and DragSourceMotionListener
interfaces. This is to allow the platform peer (the DragSourceContextPeer
instance) created by the DragSource
to notify the DragSourceContext
of state changes in the ongoing operation. This allows the DragSourceContext
object to interpose itself between the platform and the listeners provided by the initiator of the drag operation.
By default, DragSourceContext
sets the cursor as appropriate for the current state of the drag and drop operation. For example, if the user has chosen the move action, and the pointer is over a target that accepts the move action, the default move cursor is shown. When the pointer is over an area that does not accept the transfer, the default "no drop" cursor is shown.
This default handling mechanism is disabled when a custom cursor is set by the setCursor
method. When the default handling is disabled, it becomes the responsibility of the developer to keep the cursor up to date, by listening to the DragSource
events and calling the setCursor()
method. Alternatively, you can provide custom cursor behavior by providing custom implementations of the DragSource
and the DragSourceContext
classes.
See Also: Since: 1.2
/**
* The {@code DragSourceContext} class is responsible for managing the
* initiator side of the Drag and Drop protocol. In particular, it is responsible
* for managing drag event notifications to the
* {@linkplain DragSourceListener DragSourceListeners}
* and {@linkplain DragSourceMotionListener DragSourceMotionListeners}, and providing the
* {@link Transferable} representing the source data for the drag operation.
* <p>
* Note that the {@code DragSourceContext} itself
* implements the {@code DragSourceListener} and
* {@code DragSourceMotionListener} interfaces.
* This is to allow the platform peer
* (the {@link DragSourceContextPeer} instance)
* created by the {@link DragSource} to notify
* the {@code DragSourceContext} of
* state changes in the ongoing operation. This allows the
* {@code DragSourceContext} object to interpose
* itself between the platform and the
* listeners provided by the initiator of the drag operation.
* <p>
* <a id="defaultCursor"></a>
* By default, {@code DragSourceContext} sets the cursor as appropriate
* for the current state of the drag and drop operation. For example, if
* the user has chosen {@linkplain DnDConstants#ACTION_MOVE the move action},
* and the pointer is over a target that accepts
* the move action, the default move cursor is shown. When
* the pointer is over an area that does not accept the transfer,
* the default "no drop" cursor is shown.
* <p>
* This default handling mechanism is disabled when a custom cursor is set
* by the {@link #setCursor} method. When the default handling is disabled,
* it becomes the responsibility
* of the developer to keep the cursor up to date, by listening
* to the {@code DragSource} events and calling the {@code setCursor()} method.
* Alternatively, you can provide custom cursor behavior by providing
* custom implementations of the {@code DragSource}
* and the {@code DragSourceContext} classes.
*
* @see DragSourceListener
* @see DragSourceMotionListener
* @see DnDConstants
* @since 1.2
*/
public class DragSourceContext
implements DragSourceListener, DragSourceMotionListener, Serializable {
Use serialVersionUID from JDK 1.4 for interoperability.
/**
* Use serialVersionUID from JDK 1.4 for interoperability.
*/
@Serial
private static final long serialVersionUID = -115407898692194719L;
// used by updateCurrentCursor
An int
used by updateCurrentCursor() indicating that the Cursor
should change to the default (no drop) Cursor
. /**
* An {@code int} used by updateCurrentCursor()
* indicating that the {@code Cursor} should change
* to the default (no drop) {@code Cursor}.
*/
protected static final int DEFAULT = 0;
An int
used by updateCurrentCursor() indicating that the Cursor
has entered a DropTarget
. /**
* An {@code int} used by updateCurrentCursor()
* indicating that the {@code Cursor}
* has entered a {@code DropTarget}.
*/
protected static final int ENTER = 1;
An int
used by updateCurrentCursor() indicating that the Cursor
is over a DropTarget
. /**
* An {@code int} used by updateCurrentCursor()
* indicating that the {@code Cursor} is
* over a {@code DropTarget}.
*/
protected static final int OVER = 2;
An int
used by updateCurrentCursor() indicating that the user operation has changed. /**
* An {@code int} used by updateCurrentCursor()
* indicating that the user operation has changed.
*/
protected static final int CHANGED = 3;
static {
AWTAccessor.setDragSourceContextAccessor(dsc -> dsc.peer);
}
Called from DragSource
, this constructor creates a new DragSourceContext
given the DragSourceContextPeer
for this Drag, the DragGestureEvent
that triggered the Drag, the initial Cursor
to use for the Drag, an (optional) Image
to display while the Drag is taking place, the offset of the Image
origin from the hotspot at the instant of the triggering event, the Transferable
subject data, and the DragSourceListener
to use during the Drag and Drop operation.
If DragSourceContextPeer
is null
NullPointerException
is thrown.
If DragGestureEvent
is null
NullPointerException
is thrown.
If Cursor
is null
no exception is thrown and the default drag cursor behavior is activated for this drag operation.
If Image
is null
no exception is thrown.
If Image
is not null
and the offset is null NullPointerException
is thrown.
If Transferable
is null
NullPointerException
is thrown.
If DragSourceListener
is null
no exception is thrown. Params: - trigger – the triggering event
- dragCursor – the initial
Cursor
for this drag operation or null
for the default cursor handling; see class level documentation
for more details on the cursor handling mechanism during drag and drop - dragImage – the
Image
to drag (or null
) - offset – the offset of the image origin from the hotspot at the
instant of the triggering event
- t – the
Transferable
- dsl – the
DragSourceListener
Throws: - IllegalArgumentException – if the
Component
associated with the trigger event is null
. - IllegalArgumentException – if the
DragSource
for the trigger event is null
. - IllegalArgumentException – if the drag action for the trigger event is
DnDConstants.ACTION_NONE
. - IllegalArgumentException – if the source actions for the
DragGestureRecognizer
associated with the trigger event are equal to DnDConstants.ACTION_NONE
. - NullPointerException – if dscp, trigger, or t are null, or
if dragImage is non-null and offset is null
/**
* Called from {@code DragSource}, this constructor creates a new
* {@code DragSourceContext} given the
* {@code DragSourceContextPeer} for this Drag, the
* {@code DragGestureEvent} that triggered the Drag, the initial
* {@code Cursor} to use for the Drag, an (optional)
* {@code Image} to display while the Drag is taking place, the offset
* of the {@code Image} origin from the hotspot at the instant of the
* triggering event, the {@code Transferable} subject data, and the
* {@code DragSourceListener} to use during the Drag and Drop
* operation.
* <br>
* If {@code DragSourceContextPeer} is {@code null}
* {@code NullPointerException} is thrown.
* <br>
* If {@code DragGestureEvent} is {@code null}
* {@code NullPointerException} is thrown.
* <br>
* If {@code Cursor} is {@code null} no exception is thrown and
* the default drag cursor behavior is activated for this drag operation.
* <br>
* If {@code Image} is {@code null} no exception is thrown.
* <br>
* If {@code Image} is not {@code null} and the offset is
* {@code null NullPointerException} is thrown.
* <br>
* If {@code Transferable} is {@code null}
* {@code NullPointerException} is thrown.
* <br>
* If {@code DragSourceListener} is {@code null} no exception
* is thrown.
*
* @param trigger the triggering event
* @param dragCursor the initial {@code Cursor} for this drag operation
* or {@code null} for the default cursor handling;
* see <a href="DragSourceContext.html#defaultCursor">class level documentation</a>
* for more details on the cursor handling mechanism during drag and drop
* @param dragImage the {@code Image} to drag (or {@code null})
* @param offset the offset of the image origin from the hotspot at the
* instant of the triggering event
* @param t the {@code Transferable}
* @param dsl the {@code DragSourceListener}
*
* @throws IllegalArgumentException if the {@code Component} associated
* with the trigger event is {@code null}.
* @throws IllegalArgumentException if the {@code DragSource} for the
* trigger event is {@code null}.
* @throws IllegalArgumentException if the drag action for the
* trigger event is {@code DnDConstants.ACTION_NONE}.
* @throws IllegalArgumentException if the source actions for the
* {@code DragGestureRecognizer} associated with the trigger
* event are equal to {@code DnDConstants.ACTION_NONE}.
* @throws NullPointerException if dscp, trigger, or t are null, or
* if dragImage is non-null and offset is null
*/
public DragSourceContext(DragGestureEvent trigger, Cursor dragCursor,
Image dragImage, Point offset, Transferable t,
DragSourceListener dsl) {
Toolkit toolkit = Toolkit.getDefaultToolkit();
if (!(toolkit instanceof ComponentFactory)) {
throw new AWTError("Unsupported toolkit: " + toolkit);
}
DragSourceContextPeer dscp = ((ComponentFactory) toolkit).
createDragSourceContextPeer(trigger);
if (dscp == null) {
throw new NullPointerException("DragSourceContextPeer");
}
if (trigger == null) {
throw new NullPointerException("Trigger");
}
if (trigger.getDragSource() == null) {
throw new IllegalArgumentException("DragSource");
}
if (trigger.getComponent() == null) {
throw new IllegalArgumentException("Component");
}
if (trigger.getSourceAsDragGestureRecognizer().getSourceActions() ==
DnDConstants.ACTION_NONE) {
throw new IllegalArgumentException("source actions");
}
if (trigger.getDragAction() == DnDConstants.ACTION_NONE) {
throw new IllegalArgumentException("no drag action");
}
if (t == null) {
throw new NullPointerException("Transferable");
}
if (dragImage != null && offset == null) {
throw new NullPointerException("offset");
}
peer = dscp;
this.trigger = trigger;
cursor = dragCursor;
transferable = t;
listener = dsl;
sourceActions =
trigger.getSourceAsDragGestureRecognizer().getSourceActions();
useCustomCursor = (dragCursor != null);
updateCurrentCursor(trigger.getDragAction(), getSourceActions(), DEFAULT);
}
Returns the DragSource
that instantiated this DragSourceContext
. Returns: the DragSource
that instantiated this DragSourceContext
/**
* Returns the {@code DragSource}
* that instantiated this {@code DragSourceContext}.
*
* @return the {@code DragSource} that
* instantiated this {@code DragSourceContext}
*/
public DragSource getDragSource() { return trigger.getDragSource(); }
Returns the Component
associated with this DragSourceContext
. Returns: the Component
that started the drag
/**
* Returns the {@code Component} associated with this
* {@code DragSourceContext}.
*
* @return the {@code Component} that started the drag
*/
public Component getComponent() { return trigger.getComponent(); }
Returns the DragGestureEvent
that initially triggered the drag. Returns: the Event that triggered the drag
/**
* Returns the {@code DragGestureEvent}
* that initially triggered the drag.
*
* @return the Event that triggered the drag
*/
public DragGestureEvent getTrigger() { return trigger; }
Returns a bitwise mask of DnDConstants
that represent the set of drop actions supported by the drag source for the drag operation associated with this DragSourceContext
. Returns: the drop actions supported by the drag source
/**
* Returns a bitwise mask of {@code DnDConstants} that
* represent the set of drop actions supported by the drag source for the
* drag operation associated with this {@code DragSourceContext}.
*
* @return the drop actions supported by the drag source
*/
public int getSourceActions() {
return sourceActions;
}
Sets the custom cursor for this drag operation to the specified Cursor
. If the specified Cursor
is null
, the default drag cursor behavior is activated for this drag operation, otherwise it is deactivated. Params: - c – the initial
Cursor
for this drag operation, or null
for the default cursor handling; see class
level documentation for more details on the cursor handling during drag and drop
/**
* Sets the custom cursor for this drag operation to the specified
* {@code Cursor}. If the specified {@code Cursor}
* is {@code null}, the default drag cursor behavior is
* activated for this drag operation, otherwise it is deactivated.
*
* @param c the initial {@code Cursor} for this drag operation,
* or {@code null} for the default cursor handling;
* see {@linkplain Cursor class
* level documentation} for more details
* on the cursor handling during drag and drop
*
*/
public synchronized void setCursor(Cursor c) {
useCustomCursor = (c != null);
setCursorImpl(c);
}
Returns the current custom drag Cursor
. See Also: Returns: the current custom drag Cursor
, if it was set otherwise returns null
.
/**
* Returns the current custom drag {@code Cursor}.
*
* @return the current custom drag {@code Cursor}, if it was set
* otherwise returns {@code null}.
* @see #setCursor
*/
public Cursor getCursor() { return cursor; }
Add a DragSourceListener
to this DragSourceContext
if one has not already been added. If a DragSourceListener
already exists, this method throws a TooManyListenersException
. Params: - dsl – the
DragSourceListener
to add. Note that while null
is not prohibited, it is not acceptable as a parameter.
Throws: - TooManyListenersException – if a
DragSourceListener
has already been added
/**
* Add a {@code DragSourceListener} to this
* {@code DragSourceContext} if one has not already been added.
* If a {@code DragSourceListener} already exists,
* this method throws a {@code TooManyListenersException}.
*
* @param dsl the {@code DragSourceListener} to add.
* Note that while {@code null} is not prohibited,
* it is not acceptable as a parameter.
*
* @throws TooManyListenersException if
* a {@code DragSourceListener} has already been added
*/
public synchronized void addDragSourceListener(DragSourceListener dsl) throws TooManyListenersException {
if (dsl == null) return;
if (equals(dsl)) throw new IllegalArgumentException("DragSourceContext may not be its own listener");
if (listener != null)
throw new TooManyListenersException();
else
listener = dsl;
}
Removes the specified DragSourceListener
from this DragSourceContext
. Params: - dsl – the
DragSourceListener
to remove; note that while null
is not prohibited, it is not acceptable as a parameter
/**
* Removes the specified {@code DragSourceListener}
* from this {@code DragSourceContext}.
*
* @param dsl the {@code DragSourceListener} to remove;
* note that while {@code null} is not prohibited,
* it is not acceptable as a parameter
*/
public synchronized void removeDragSourceListener(DragSourceListener dsl) {
if (listener != null && listener.equals(dsl)) {
listener = null;
} else
throw new IllegalArgumentException();
}
Notifies the peer that the Transferable
's DataFlavor
s have changed. /**
* Notifies the peer that the {@code Transferable}'s
* {@code DataFlavor}s have changed.
*/
public void transferablesFlavorsChanged() {
if (peer != null) peer.transferablesFlavorsChanged();
}
Calls dragEnter
on the DragSourceListener
s registered with this DragSourceContext
and with the associated DragSource
, and passes them the specified DragSourceDragEvent
. Params: - dsde – the
DragSourceDragEvent
/**
* Calls {@code dragEnter} on the
* {@code DragSourceListener}s registered with this
* {@code DragSourceContext} and with the associated
* {@code DragSource}, and passes them the specified
* {@code DragSourceDragEvent}.
*
* @param dsde the {@code DragSourceDragEvent}
*/
public void dragEnter(DragSourceDragEvent dsde) {
DragSourceListener dsl = listener;
if (dsl != null) {
dsl.dragEnter(dsde);
}
getDragSource().processDragEnter(dsde);
updateCurrentCursor(getSourceActions(), dsde.getTargetActions(), ENTER);
}
Calls dragOver
on the DragSourceListener
s registered with this DragSourceContext
and with the associated DragSource
, and passes them the specified DragSourceDragEvent
. Params: - dsde – the
DragSourceDragEvent
/**
* Calls {@code dragOver} on the
* {@code DragSourceListener}s registered with this
* {@code DragSourceContext} and with the associated
* {@code DragSource}, and passes them the specified
* {@code DragSourceDragEvent}.
*
* @param dsde the {@code DragSourceDragEvent}
*/
public void dragOver(DragSourceDragEvent dsde) {
DragSourceListener dsl = listener;
if (dsl != null) {
dsl.dragOver(dsde);
}
getDragSource().processDragOver(dsde);
updateCurrentCursor(getSourceActions(), dsde.getTargetActions(), OVER);
}
Calls dragExit
on the DragSourceListener
s registered with this DragSourceContext
and with the associated DragSource
, and passes them the specified DragSourceEvent
. Params: - dse – the
DragSourceEvent
/**
* Calls {@code dragExit} on the
* {@code DragSourceListener}s registered with this
* {@code DragSourceContext} and with the associated
* {@code DragSource}, and passes them the specified
* {@code DragSourceEvent}.
*
* @param dse the {@code DragSourceEvent}
*/
public void dragExit(DragSourceEvent dse) {
DragSourceListener dsl = listener;
if (dsl != null) {
dsl.dragExit(dse);
}
getDragSource().processDragExit(dse);
updateCurrentCursor(DnDConstants.ACTION_NONE, DnDConstants.ACTION_NONE, DEFAULT);
}
Calls dropActionChanged
on the DragSourceListener
s registered with this DragSourceContext
and with the associated DragSource
, and passes them the specified DragSourceDragEvent
. Params: - dsde – the
DragSourceDragEvent
/**
* Calls {@code dropActionChanged} on the
* {@code DragSourceListener}s registered with this
* {@code DragSourceContext} and with the associated
* {@code DragSource}, and passes them the specified
* {@code DragSourceDragEvent}.
*
* @param dsde the {@code DragSourceDragEvent}
*/
public void dropActionChanged(DragSourceDragEvent dsde) {
DragSourceListener dsl = listener;
if (dsl != null) {
dsl.dropActionChanged(dsde);
}
getDragSource().processDropActionChanged(dsde);
updateCurrentCursor(getSourceActions(), dsde.getTargetActions(), CHANGED);
}
Calls dragDropEnd
on the DragSourceListener
s registered with this DragSourceContext
and with the associated DragSource
, and passes them the specified DragSourceDropEvent
. Params: - dsde – the
DragSourceDropEvent
/**
* Calls {@code dragDropEnd} on the
* {@code DragSourceListener}s registered with this
* {@code DragSourceContext} and with the associated
* {@code DragSource}, and passes them the specified
* {@code DragSourceDropEvent}.
*
* @param dsde the {@code DragSourceDropEvent}
*/
public void dragDropEnd(DragSourceDropEvent dsde) {
DragSourceListener dsl = listener;
if (dsl != null) {
dsl.dragDropEnd(dsde);
}
getDragSource().processDragDropEnd(dsde);
}
Calls dragMouseMoved
on the DragSourceMotionListener
s registered with the DragSource
associated with this DragSourceContext
, and them passes the specified DragSourceDragEvent
. Params: - dsde – the
DragSourceDragEvent
Since: 1.4
/**
* Calls {@code dragMouseMoved} on the
* {@code DragSourceMotionListener}s registered with the
* {@code DragSource} associated with this
* {@code DragSourceContext}, and them passes the specified
* {@code DragSourceDragEvent}.
*
* @param dsde the {@code DragSourceDragEvent}
* @since 1.4
*/
public void dragMouseMoved(DragSourceDragEvent dsde) {
getDragSource().processDragMouseMoved(dsde);
}
Returns the Transferable
associated with this DragSourceContext
. Returns: the Transferable
/**
* Returns the {@code Transferable} associated with
* this {@code DragSourceContext}.
*
* @return the {@code Transferable}
*/
public Transferable getTransferable() { return transferable; }
If the default drag cursor behavior is active, this method
sets the default drag cursor for the specified actions
supported by the drag source, the drop target action,
and status, otherwise this method does nothing.
Params: - sourceAct – the actions supported by the drag source
- targetAct – the drop target action
- status – one of the fields
DEFAULT
, ENTER
, OVER
, CHANGED
/**
* If the default drag cursor behavior is active, this method
* sets the default drag cursor for the specified actions
* supported by the drag source, the drop target action,
* and status, otherwise this method does nothing.
*
* @param sourceAct the actions supported by the drag source
* @param targetAct the drop target action
* @param status one of the fields {@code DEFAULT},
* {@code ENTER}, {@code OVER},
* {@code CHANGED}
*/
@SuppressWarnings("fallthrough")
protected synchronized void updateCurrentCursor(int sourceAct, int targetAct, int status) {
// if the cursor has been previously set then don't do any defaults
// processing.
if (useCustomCursor) {
return;
}
// do defaults processing
Cursor c = null;
switch (status) {
default:
targetAct = DnDConstants.ACTION_NONE;
case ENTER:
case OVER:
case CHANGED:
int ra = sourceAct & targetAct;
if (ra == DnDConstants.ACTION_NONE) { // no drop possible
if ((sourceAct & DnDConstants.ACTION_LINK) == DnDConstants.ACTION_LINK)
c = DragSource.DefaultLinkNoDrop;
else if ((sourceAct & DnDConstants.ACTION_MOVE) == DnDConstants.ACTION_MOVE)
c = DragSource.DefaultMoveNoDrop;
else
c = DragSource.DefaultCopyNoDrop;
} else { // drop possible
if ((ra & DnDConstants.ACTION_LINK) == DnDConstants.ACTION_LINK)
c = DragSource.DefaultLinkDrop;
else if ((ra & DnDConstants.ACTION_MOVE) == DnDConstants.ACTION_MOVE)
c = DragSource.DefaultMoveDrop;
else
c = DragSource.DefaultCopyDrop;
}
}
setCursorImpl(c);
}
private void setCursorImpl(Cursor c) {
if (cursor == null || !cursor.equals(c)) {
cursor = c;
if (peer != null) peer.setCursor(cursor);
}
}
Serializes this DragSourceContext
. This method first performs default serialization. Next, this object's Transferable
is written out if and only if it can be serialized. If not, null
is written instead. In this case, a DragSourceContext
created from the resulting deserialized stream will contain a dummy Transferable
which supports no DataFlavor
s. Finally, this object's DragSourceListener
is written out if and only if it can be serialized. If not, null
is written instead. Params: - s – the
ObjectOutputStream
to write
Throws: - IOException – if an I/O error occurs
@serialData The default serializable fields, in alphabetical order, followed by either a Transferable
instance, or null
, followed by either a DragSourceListener
instance, or null
. Since: 1.4
/**
* Serializes this {@code DragSourceContext}. This method first
* performs default serialization. Next, this object's
* {@code Transferable} is written out if and only if it can be
* serialized. If not, {@code null} is written instead. In this case,
* a {@code DragSourceContext} created from the resulting deserialized
* stream will contain a dummy {@code Transferable} which supports no
* {@code DataFlavor}s. Finally, this object's
* {@code DragSourceListener} is written out if and only if it can be
* serialized. If not, {@code null} is written instead.
*
* @param s the {@code ObjectOutputStream} to write
* @throws IOException if an I/O error occurs
* @serialData The default serializable fields, in alphabetical order,
* followed by either a {@code Transferable} instance, or
* {@code null}, followed by either a
* {@code DragSourceListener} instance, or
* {@code null}.
* @since 1.4
*/
@Serial
private void writeObject(ObjectOutputStream s) throws IOException {
s.defaultWriteObject();
s.writeObject(SerializationTester.test(transferable)
? transferable : null);
s.writeObject(SerializationTester.test(listener)
? listener : null);
}
Deserializes this DragSourceContext
. This method first performs default deserialization for all non-transient
fields. This object's Transferable
and DragSourceListener
are then deserialized as well by using the next two objects in the stream. If the resulting Transferable
is null
, this object's Transferable
is set to a dummy Transferable
which supports no DataFlavor
s. Params: - s – the
ObjectInputStream
to read
Throws: - ClassNotFoundException – if the class of a serialized object could
not be found
- IOException – if an I/O error occurs
Since: 1.4
/**
* Deserializes this {@code DragSourceContext}. This method first
* performs default deserialization for all non-{@code transient}
* fields. This object's {@code Transferable} and
* {@code DragSourceListener} are then deserialized as well by using
* the next two objects in the stream. If the resulting
* {@code Transferable} is {@code null}, this object's
* {@code Transferable} is set to a dummy {@code Transferable}
* which supports no {@code DataFlavor}s.
*
* @param s the {@code ObjectInputStream} to read
* @throws ClassNotFoundException if the class of a serialized object could
* not be found
* @throws IOException if an I/O error occurs
* @since 1.4
*/
@Serial
private void readObject(ObjectInputStream s)
throws ClassNotFoundException, IOException
{
ObjectInputStream.GetField f = s.readFields();
DragGestureEvent newTrigger = (DragGestureEvent)f.get("trigger", null);
if (newTrigger == null) {
throw new InvalidObjectException("Null trigger");
}
if (newTrigger.getDragSource() == null) {
throw new InvalidObjectException("Null DragSource");
}
if (newTrigger.getComponent() == null) {
throw new InvalidObjectException("Null trigger component");
}
int newSourceActions = f.get("sourceActions", 0)
& (DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK);
if (newSourceActions == DnDConstants.ACTION_NONE) {
throw new InvalidObjectException("Invalid source actions");
}
int triggerActions = newTrigger.getDragAction();
if (triggerActions != DnDConstants.ACTION_COPY &&
triggerActions != DnDConstants.ACTION_MOVE &&
triggerActions != DnDConstants.ACTION_LINK) {
throw new InvalidObjectException("No drag action");
}
trigger = newTrigger;
cursor = (Cursor)f.get("cursor", null);
useCustomCursor = f.get("useCustomCursor", false);
sourceActions = newSourceActions;
transferable = (Transferable)s.readObject();
listener = (DragSourceListener)s.readObject();
// Implementation assumes 'transferable' is never null.
if (transferable == null) {
if (emptyTransferable == null) {
emptyTransferable = new Transferable() {
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[0];
}
public boolean isDataFlavorSupported(DataFlavor flavor)
{
return false;
}
public Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException
{
throw new UnsupportedFlavorException(flavor);
}
};
}
transferable = emptyTransferable;
}
}
private static Transferable emptyTransferable;
/*
* fields
*/
private final transient DragSourceContextPeer peer;
The event which triggered the start of the drag.
@serial
/**
* The event which triggered the start of the drag.
*
* @serial
*/
private DragGestureEvent trigger;
The current drag cursor.
@serial
/**
* The current drag cursor.
*
* @serial
*/
private Cursor cursor;
private transient Transferable transferable;
private transient DragSourceListener listener;
true
if the custom drag cursor is used instead of the default one. @serial
/**
* {@code true} if the custom drag cursor is used instead of the
* default one.
*
* @serial
*/
private boolean useCustomCursor;
A bitwise mask of DnDConstants
that represents the set of drop actions supported by the drag source for the drag operation associated with this DragSourceContext.
@serial
/**
* A bitwise mask of {@code DnDConstants} that represents the set of
* drop actions supported by the drag source for the drag operation associated
* with this {@code DragSourceContext.}
*
* @serial
*/
private int sourceActions;
}