mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
Merge remote-tracking branch 'origin/GT-3432-dragonmacher-drag-n-drop'
(fixes #1396)
This commit is contained in:
commit
068a2f455e
4 changed files with 184 additions and 215 deletions
|
@ -15,246 +15,202 @@
|
|||
*/
|
||||
package docking.dnd;
|
||||
|
||||
import ghidra.util.Msg;
|
||||
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.datatransfer.Transferable;
|
||||
import java.awt.dnd.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ghidra.util.Msg;
|
||||
|
||||
/**
|
||||
* Class to handle notifications of drag and drop operations that occur
|
||||
* on the DropTarget object. The DropTarget is the component that accepts
|
||||
* drops during a drag and drop operation. The <code>drop</code>
|
||||
* method actually transfers the data.
|
||||
* Class to handle notifications of drag and drop operations that occur on the DropTarget
|
||||
* object. The DropTarget is the component that accepts drops during a drag and drop operation.
|
||||
* The <code>drop</code> method actually transfers the data.
|
||||
*/
|
||||
public class DropTgtAdapter implements DropTargetListener {
|
||||
|
||||
private Droppable dropComponent;
|
||||
private int dropActions; // actions that the drop target
|
||||
// can accept
|
||||
private DataFlavor []dropFlavors; //drop flavors that the
|
||||
// drop target can accept
|
||||
private Droppable dropComponent;
|
||||
private int dropActions; // actions that the drop target can accept
|
||||
private DataFlavor[] dropFlavors; //drop flavors that the drop target can accept
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param dropComponent the drop target
|
||||
* @param acceptableDropActions a DnDConstants variable that defines
|
||||
* dnd actions
|
||||
* @param acceptableDropFlavors acceptable data formats that the drop
|
||||
* target can handle
|
||||
*/
|
||||
public DropTgtAdapter(Droppable dropComponent,
|
||||
int acceptableDropActions, DataFlavor []acceptableDropFlavors) {
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param dropComponent the drop target
|
||||
* @param acceptableDropActions a DnDConstants variable that defines dnd actions
|
||||
* @param acceptableDropFlavors acceptable data formats that the drop target can handle
|
||||
*/
|
||||
public DropTgtAdapter(Droppable dropComponent,
|
||||
int acceptableDropActions, DataFlavor[] acceptableDropFlavors) {
|
||||
|
||||
this.dropComponent = dropComponent;
|
||||
dropActions = acceptableDropActions;
|
||||
dropFlavors = acceptableDropFlavors;
|
||||
}
|
||||
/**
|
||||
* Set the data flavors acceptable to the associated drop target.
|
||||
* @param dropFlavors
|
||||
*/
|
||||
public void setAcceptableDropFlavors(DataFlavor []dropFlavors) {
|
||||
this.dropFlavors = dropFlavors;
|
||||
}
|
||||
/**
|
||||
* DropTargetListener method called when the drag operation encounters
|
||||
* the drop target.
|
||||
* @param e event that has current state of drag and drop operation
|
||||
*/
|
||||
public void dragEnter(DropTargetDragEvent e) {
|
||||
this.dropComponent = dropComponent;
|
||||
dropActions = acceptableDropActions;
|
||||
dropFlavors = acceptableDropFlavors;
|
||||
}
|
||||
|
||||
if (isDropOk(e)) {
|
||||
e.acceptDrag(e.getDropAction());
|
||||
}
|
||||
else {
|
||||
dropComponent.dragUnderFeedback(false,e);
|
||||
e.rejectDrag();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* DropTargetListener method called when the drag operation is over
|
||||
* the drop target.
|
||||
* @param e event that has current state of drag and drop operation
|
||||
*/
|
||||
public void dragOver(DropTargetDragEvent e) {
|
||||
/**
|
||||
* Set the data flavors acceptable to the associated drop target
|
||||
* @param dropFlavors the flavors
|
||||
*/
|
||||
public void setAcceptableDropFlavors(DataFlavor[] dropFlavors) {
|
||||
this.dropFlavors = dropFlavors;
|
||||
}
|
||||
|
||||
if (isDropOk(e)) {
|
||||
dropComponent.dragUnderFeedback(true, e);
|
||||
e.acceptDrag(e.getDropAction());
|
||||
}
|
||||
else {
|
||||
dropComponent.dragUnderFeedback(false,e);
|
||||
e.rejectDrag();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* DropTargetListener method called when the
|
||||
* drag operation exits the drop target without dropping. However,
|
||||
* this method is also called even when the drop completes.
|
||||
* @param e event that has current state of drag and drop operation
|
||||
*/
|
||||
public void dragExit(DropTargetEvent e) {
|
||||
dropComponent.undoDragUnderFeedback();
|
||||
// Note: at this point, there is no way to tell whether the
|
||||
// drop actually occurred; so, there is no notification
|
||||
// for a "drop canceled"
|
||||
@Override
|
||||
public void dragEnter(DropTargetDragEvent e) {
|
||||
|
||||
}
|
||||
/**
|
||||
* DropTargetListener method called when the user modifies the
|
||||
* drag action.
|
||||
* @param e event that has current state of drag and drop operation
|
||||
*/
|
||||
public void dropActionChanged(DropTargetDragEvent e){
|
||||
dragOver(e);
|
||||
}
|
||||
/**
|
||||
* DropTargetListener method called when the drag operation terminates and
|
||||
* drops onto the drop target.
|
||||
* @param e event that has current state of drag and drop operation
|
||||
*/
|
||||
public void drop(DropTargetDropEvent e) {
|
||||
if (isDropOk(e)) {
|
||||
e.acceptDrag(e.getDropAction());
|
||||
}
|
||||
else {
|
||||
dropComponent.dragUnderFeedback(false, e);
|
||||
e.rejectDrag();
|
||||
}
|
||||
}
|
||||
|
||||
// only handle local transfers (within same JVM) for now...
|
||||
// if (!e.isLocalTransfer()) {
|
||||
// e.rejectDrop();
|
||||
// dropComponent.undoDragUnderFeedback();
|
||||
// return;
|
||||
// }
|
||||
@Override
|
||||
public void dragOver(DropTargetDragEvent e) {
|
||||
|
||||
Transferable t = e.getTransferable();
|
||||
int flavorIndex=-1;
|
||||
for (int i=0; i<dropFlavors.length; i++) {
|
||||
if (t.isDataFlavorSupported(dropFlavors[i])) {
|
||||
flavorIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (flavorIndex < 0) {
|
||||
e.rejectDrop();
|
||||
dropComponent.undoDragUnderFeedback();
|
||||
return;
|
||||
}
|
||||
if (isDropOk(e)) {
|
||||
dropComponent.dragUnderFeedback(true, e);
|
||||
e.acceptDrag(e.getDropAction());
|
||||
}
|
||||
else {
|
||||
dropComponent.dragUnderFeedback(false, e);
|
||||
e.rejectDrag();
|
||||
}
|
||||
}
|
||||
|
||||
int dropAction = e.getDropAction();
|
||||
int sourceActions = e.getSourceActions();
|
||||
@Override
|
||||
public void dragExit(DropTargetEvent e) {
|
||||
dropComponent.undoDragUnderFeedback();
|
||||
|
||||
if ( (dropAction & sourceActions) == 0) {
|
||||
e.rejectDrop();
|
||||
dropComponent.undoDragUnderFeedback();
|
||||
return;
|
||||
}
|
||||
// Note: at this point, there is no way to tell whether the drop actually occurred;
|
||||
// so, there is no notification for a "drop canceled"
|
||||
}
|
||||
|
||||
// the source listener receives this action in dragDropEnd().
|
||||
// if the action is DnDConstants.ACTION_COPY_OR_MOVE, then
|
||||
// the source receives the MOVE.
|
||||
e.acceptDrop(e.getDropAction());
|
||||
Object data =null;
|
||||
boolean error=false;
|
||||
Throwable th=null;
|
||||
@Override
|
||||
public void dropActionChanged(DropTargetDragEvent e) {
|
||||
dragOver(e);
|
||||
}
|
||||
|
||||
// now get the drop flavor that matches up with that in
|
||||
// the transferable object
|
||||
@Override
|
||||
public void drop(DropTargetDropEvent e) {
|
||||
|
||||
Transferable t = e.getTransferable();
|
||||
int flavorIndex = -1;
|
||||
for (int i = 0; i < dropFlavors.length; i++) {
|
||||
if (t.isDataFlavorSupported(dropFlavors[i])) {
|
||||
flavorIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flavorIndex < 0) {
|
||||
e.rejectDrop();
|
||||
dropComponent.undoDragUnderFeedback();
|
||||
return;
|
||||
}
|
||||
|
||||
int dropAction = e.getDropAction();
|
||||
int sourceActions = e.getSourceActions();
|
||||
|
||||
if ((dropAction & sourceActions) == 0) {
|
||||
e.rejectDrop();
|
||||
dropComponent.undoDragUnderFeedback();
|
||||
return;
|
||||
}
|
||||
|
||||
// The source listener receives this action in dragDropEnd().
|
||||
// If the action is DnDConstants.ACTION_COPY_OR_MOVE, then the source receives the MOVE.
|
||||
e.acceptDrop(e.getDropAction());
|
||||
Object data = null;
|
||||
|
||||
try {
|
||||
data = t.getTransferData(dropFlavors[flavorIndex]);
|
||||
} catch (Throwable thr) {
|
||||
error=true;
|
||||
th = thr;
|
||||
}
|
||||
catch (Throwable throwable) {
|
||||
e.dropComplete(false);
|
||||
dropComponent.undoDragUnderFeedback();
|
||||
Msg.showError(this, null, "Drop Failed", "Could not get transfer data.", throwable);
|
||||
return;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
e.dropComplete(false);
|
||||
dropComponent.undoDragUnderFeedback();
|
||||
Msg.showError(this,null, "Drop Failed", "Could not get transfer data.", th);
|
||||
}
|
||||
else {
|
||||
// this is the copy
|
||||
DataFlavor flavor=dropFlavors[flavorIndex];
|
||||
try {
|
||||
dropComponent.add(data, e, flavor);
|
||||
// notify drag source that the drop is complete...
|
||||
e.dropComplete(true);
|
||||
dropComponent.undoDragUnderFeedback();
|
||||
} catch (Throwable thr) {
|
||||
e.dropComplete(false);
|
||||
dropComponent.undoDragUnderFeedback();
|
||||
String message = thr.getMessage();
|
||||
if ( message == null ) {
|
||||
message = "";
|
||||
}
|
||||
Msg.showError(this, null, "Unexpected Drag and Drop Exception", message, thr);
|
||||
}
|
||||
}
|
||||
// this is the copy
|
||||
DataFlavor flavor = dropFlavors[flavorIndex];
|
||||
try {
|
||||
dropComponent.add(data, e, flavor);
|
||||
e.dropComplete(true);
|
||||
dropComponent.undoDragUnderFeedback();
|
||||
}
|
||||
catch (Throwable throwable) {
|
||||
e.dropComplete(false);
|
||||
dropComponent.undoDragUnderFeedback();
|
||||
String message = throwable.getMessage();
|
||||
Msg.showError(this, null, "Unexpected Drag and Drop Exception", message, throwable);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the drop operation is OK. A drop is deemed to be okay if
|
||||
* <OL>
|
||||
* <LI>the drop target accepts one of the data flavors that the event's transferable provides
|
||||
* </LI>
|
||||
* <LI>the drop action (i.e. COPY, MOVE, etc.) is accepted by the target
|
||||
* </LI>
|
||||
* <LI>the drop is accepted by the Droppable component
|
||||
* </LI>
|
||||
* </OL>
|
||||
*
|
||||
* @param e event that has current state of drag and drop operation
|
||||
* @return true if the drop operation is OK
|
||||
*/
|
||||
protected boolean isDropOk(DropTargetDragEvent e) {
|
||||
|
||||
/**
|
||||
* Returns true if the drop operation is OK. A drop is deemed to be okay if
|
||||
* <br> 1. the drop target accepts one of the data flavors that the event's transferrable provides.
|
||||
* <br> 2. the drop action (i.e. COPY, MOVE, etc.) is accepted by the target.
|
||||
* <br> 3. the drop is accepted by the Droppable component.
|
||||
* @param e event that has current state of drag and drop operation
|
||||
*/
|
||||
protected boolean isDropOk(DropTargetDragEvent e) {
|
||||
// Does this target accept the drop action type being dropped on it?
|
||||
int da = e.getDropAction();
|
||||
if ((da & dropActions) == 0) {
|
||||
return false;
|
||||
}
|
||||
// Does the event's transferable have a flavor that this drop target accepts?
|
||||
int da = e.getDropAction();
|
||||
if ((da & dropActions) == 0) {
|
||||
return false;
|
||||
}
|
||||
// Does the event's transferable have a flavor that this drop target accepts?
|
||||
if (!isDragFlavorSupported(e)) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Does the target component allow the drop.
|
||||
if (!dropComponent.isDropOk(e)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Returns true if the drop target can accept the data
|
||||
* flavor that is to be dropped.
|
||||
*/
|
||||
protected boolean isDragFlavorSupported(DropTargetDragEvent e) {
|
||||
if (dropFlavors == null) {
|
||||
return false; // This drop target doesn't accept any flavors.
|
||||
}
|
||||
// Check each flavor to see that this accepts at least one flavor the event can drop.
|
||||
for (int i=0; i<dropFlavors.length; i++) {
|
||||
if (e.isDataFlavorSupported(dropFlavors[i])){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!dropComponent.isDropOk(e)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static DataFlavor getFirstMatchingFlavor(DropTargetDragEvent e, DataFlavor[] acceptableFlavors) {
|
||||
/**
|
||||
* Returns true if the drop target can accept the data flavor that is to be dropped
|
||||
* @param e event that has current state of drag and drop operation
|
||||
* @return true if the drop target can accept the data flavor that is to be dropped
|
||||
*/
|
||||
protected boolean isDragFlavorSupported(DropTargetDragEvent e) {
|
||||
if (dropFlavors == null) {
|
||||
return false; // This drop target doesn't accept any flavors.
|
||||
}
|
||||
// Check each flavor to see that this accepts at least one flavor the event can drop.
|
||||
for (DataFlavor dropFlavor : dropFlavors) {
|
||||
if (e.isDataFlavorSupported(dropFlavor)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static DataFlavor getFirstMatchingFlavor(DropTargetDragEvent e,
|
||||
DataFlavor[] acceptableFlavors) {
|
||||
DataFlavor[] transferFlavors = e.getCurrentDataFlavors();
|
||||
for (DataFlavor acceptableFlavor : acceptableFlavors) {
|
||||
for (DataFlavor transferFlavor : transferFlavors) {
|
||||
if (acceptableFlavor.equals(transferFlavor)) {
|
||||
return transferFlavor;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static DataFlavor[] getAllMatchingFlavors(DropTargetDragEvent e, DataFlavor[] acceptableFlavors) {
|
||||
ArrayList<DataFlavor> list = new ArrayList<DataFlavor>();
|
||||
DataFlavor[] transferFlavors = e.getCurrentDataFlavors();
|
||||
for (DataFlavor acceptableFlavor : acceptableFlavors) {
|
||||
for (DataFlavor transferFlavor : transferFlavors) {
|
||||
if (acceptableFlavor.equals(transferFlavor)) {
|
||||
list.add(transferFlavor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return list.toArray(new DataFlavor[list.size()]);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue