mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
GT-3432 - Fixed recently broken drag-n-drop from the Front End to a
running Tool
This commit is contained in:
parent
cbe5b9e9ca
commit
adbbc25542
4 changed files with 184 additions and 215 deletions
|
@ -19,18 +19,18 @@ import java.awt.datatransfer.DataFlavor;
|
||||||
|
|
||||||
import ghidra.framework.main.datatree.*;
|
import ghidra.framework.main.datatree.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class used to initialize the handling of files that are dropped onto the tool
|
||||||
|
*/
|
||||||
public class GhidraFileOpenDataFlavorHandlerService {
|
public class GhidraFileOpenDataFlavorHandlerService {
|
||||||
|
|
||||||
public GhidraFileOpenDataFlavorHandlerService() {
|
public GhidraFileOpenDataFlavorHandlerService() {
|
||||||
|
|
||||||
try {
|
//
|
||||||
DataFlavor linuxFileUrlFlavor =
|
// Note: the order of the file drop flavors/handlers is intentional. We wish to process
|
||||||
new DataFlavor("application/x-java-serialized-object;class=java.lang.String");
|
// objects first which we know to be transfered from within the current JVM. After
|
||||||
FileOpenDropHandler.addDataFlavorHandler(linuxFileUrlFlavor, new LinuxFileUrlHandler());
|
// that, then process objects given to us from the OS or another JVM.
|
||||||
}
|
//
|
||||||
catch (ClassNotFoundException cnfe) {
|
|
||||||
// should never happen as it is using java.lang.String
|
|
||||||
}
|
|
||||||
|
|
||||||
LocalTreeNodeHandler localHandler = new LocalTreeNodeHandler();
|
LocalTreeNodeHandler localHandler = new LocalTreeNodeHandler();
|
||||||
FileOpenDropHandler.addDataFlavorHandler(DataTreeDragNDropHandler.localDomainFileFlavor,
|
FileOpenDropHandler.addDataFlavorHandler(DataTreeDragNDropHandler.localDomainFileFlavor,
|
||||||
|
@ -40,7 +40,13 @@ public class GhidraFileOpenDataFlavorHandlerService {
|
||||||
|
|
||||||
FileOpenDropHandler.addDataFlavorHandler(VersionInfoTransferable.localVersionInfoFlavor,
|
FileOpenDropHandler.addDataFlavorHandler(VersionInfoTransferable.localVersionInfoFlavor,
|
||||||
new LocalVersionInfoHandler());
|
new LocalVersionInfoHandler());
|
||||||
|
|
||||||
FileOpenDropHandler.addDataFlavorHandler(DataFlavor.javaFileListFlavor,
|
FileOpenDropHandler.addDataFlavorHandler(DataFlavor.javaFileListFlavor,
|
||||||
new JavaFileListHandler());
|
new JavaFileListHandler());
|
||||||
|
|
||||||
|
DataFlavor linuxFileUrlFlavor =
|
||||||
|
new DataFlavor("application/x-java-serialized-object;class=java.lang.String",
|
||||||
|
"String file URL");
|
||||||
|
FileOpenDropHandler.addDataFlavorHandler(linuxFileUrlFlavor, new LinuxFileUrlHandler());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import java.awt.Component;
|
||||||
import java.awt.datatransfer.DataFlavor;
|
import java.awt.datatransfer.DataFlavor;
|
||||||
import java.awt.dnd.DropTargetDropEvent;
|
import java.awt.dnd.DropTargetDropEvent;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -84,8 +85,14 @@ public final class LinuxFileUrlHandler implements DataTreeFlavorHandler, FileOpe
|
||||||
try {
|
try {
|
||||||
return new File(new URL(s).toURI());
|
return new File(new URL(s).toURI());
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (MalformedURLException e) {
|
||||||
Msg.error(this, "Unable to open dropped URL: '" + s + "'", ex);
|
// this could be the case that this handler is attempting to process an arbitrary
|
||||||
|
// String that is not actually a URL
|
||||||
|
Msg.trace(this, "Not a URL: '" + s + "'", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
Msg.error(this, "Unable to open dropped URL: '" + s + "'", e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,246 +15,202 @@
|
||||||
*/
|
*/
|
||||||
package docking.dnd;
|
package docking.dnd;
|
||||||
|
|
||||||
import ghidra.util.Msg;
|
|
||||||
|
|
||||||
import java.awt.datatransfer.DataFlavor;
|
import java.awt.datatransfer.DataFlavor;
|
||||||
import java.awt.datatransfer.Transferable;
|
import java.awt.datatransfer.Transferable;
|
||||||
import java.awt.dnd.*;
|
import java.awt.dnd.*;
|
||||||
import java.util.ArrayList;
|
|
||||||
|
import ghidra.util.Msg;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to handle notifications of drag and drop operations that occur
|
* Class to handle notifications of drag and drop operations that occur on the DropTarget
|
||||||
* on the DropTarget object. The DropTarget is the component that accepts
|
* object. The DropTarget is the component that accepts drops during a drag and drop operation.
|
||||||
* drops during a drag and drop operation. The <code>drop</code>
|
* The <code>drop</code> method actually transfers the data.
|
||||||
* method actually transfers the data.
|
|
||||||
*/
|
*/
|
||||||
public class DropTgtAdapter implements DropTargetListener {
|
public class DropTgtAdapter implements DropTargetListener {
|
||||||
|
|
||||||
private Droppable dropComponent;
|
private Droppable dropComponent;
|
||||||
private int dropActions; // actions that the drop target
|
private int dropActions; // actions that the drop target can accept
|
||||||
// can accept
|
private DataFlavor[] dropFlavors; //drop flavors that the drop target can accept
|
||||||
private DataFlavor []dropFlavors; //drop flavors that the
|
|
||||||
// drop target can accept
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
* @param dropComponent the drop target
|
*
|
||||||
* @param acceptableDropActions a DnDConstants variable that defines
|
* @param dropComponent the drop target
|
||||||
* dnd actions
|
* @param acceptableDropActions a DnDConstants variable that defines dnd actions
|
||||||
* @param acceptableDropFlavors acceptable data formats that the drop
|
* @param acceptableDropFlavors acceptable data formats that the drop target can handle
|
||||||
* target can handle
|
*/
|
||||||
*/
|
public DropTgtAdapter(Droppable dropComponent,
|
||||||
public DropTgtAdapter(Droppable dropComponent,
|
int acceptableDropActions, DataFlavor[] acceptableDropFlavors) {
|
||||||
int acceptableDropActions, DataFlavor []acceptableDropFlavors) {
|
|
||||||
|
|
||||||
this.dropComponent = dropComponent;
|
this.dropComponent = dropComponent;
|
||||||
dropActions = acceptableDropActions;
|
dropActions = acceptableDropActions;
|
||||||
dropFlavors = acceptableDropFlavors;
|
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) {
|
|
||||||
|
|
||||||
if (isDropOk(e)) {
|
/**
|
||||||
e.acceptDrag(e.getDropAction());
|
* Set the data flavors acceptable to the associated drop target
|
||||||
}
|
* @param dropFlavors the flavors
|
||||||
else {
|
*/
|
||||||
dropComponent.dragUnderFeedback(false,e);
|
public void setAcceptableDropFlavors(DataFlavor[] dropFlavors) {
|
||||||
e.rejectDrag();
|
this.dropFlavors = dropFlavors;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 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) {
|
|
||||||
|
|
||||||
if (isDropOk(e)) {
|
@Override
|
||||||
dropComponent.dragUnderFeedback(true, e);
|
public void dragEnter(DropTargetDragEvent 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"
|
|
||||||
|
|
||||||
}
|
if (isDropOk(e)) {
|
||||||
/**
|
e.acceptDrag(e.getDropAction());
|
||||||
* DropTargetListener method called when the user modifies the
|
}
|
||||||
* drag action.
|
else {
|
||||||
* @param e event that has current state of drag and drop operation
|
dropComponent.dragUnderFeedback(false, e);
|
||||||
*/
|
e.rejectDrag();
|
||||||
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) {
|
|
||||||
|
|
||||||
// only handle local transfers (within same JVM) for now...
|
@Override
|
||||||
// if (!e.isLocalTransfer()) {
|
public void dragOver(DropTargetDragEvent e) {
|
||||||
// e.rejectDrop();
|
|
||||||
// dropComponent.undoDragUnderFeedback();
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
Transferable t = e.getTransferable();
|
if (isDropOk(e)) {
|
||||||
int flavorIndex=-1;
|
dropComponent.dragUnderFeedback(true, e);
|
||||||
for (int i=0; i<dropFlavors.length; i++) {
|
e.acceptDrag(e.getDropAction());
|
||||||
if (t.isDataFlavorSupported(dropFlavors[i])) {
|
}
|
||||||
flavorIndex = i;
|
else {
|
||||||
break;
|
dropComponent.dragUnderFeedback(false, e);
|
||||||
}
|
e.rejectDrag();
|
||||||
}
|
}
|
||||||
if (flavorIndex < 0) {
|
}
|
||||||
e.rejectDrop();
|
|
||||||
dropComponent.undoDragUnderFeedback();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int dropAction = e.getDropAction();
|
@Override
|
||||||
int sourceActions = e.getSourceActions();
|
public void dragExit(DropTargetEvent e) {
|
||||||
|
dropComponent.undoDragUnderFeedback();
|
||||||
|
|
||||||
if ( (dropAction & sourceActions) == 0) {
|
// Note: at this point, there is no way to tell whether the drop actually occurred;
|
||||||
e.rejectDrop();
|
// so, there is no notification for a "drop canceled"
|
||||||
dropComponent.undoDragUnderFeedback();
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// the source listener receives this action in dragDropEnd().
|
@Override
|
||||||
// if the action is DnDConstants.ACTION_COPY_OR_MOVE, then
|
public void dropActionChanged(DropTargetDragEvent e) {
|
||||||
// the source receives the MOVE.
|
dragOver(e);
|
||||||
e.acceptDrop(e.getDropAction());
|
}
|
||||||
Object data =null;
|
|
||||||
boolean error=false;
|
|
||||||
Throwable th=null;
|
|
||||||
|
|
||||||
// now get the drop flavor that matches up with that in
|
@Override
|
||||||
// the transferable object
|
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 {
|
try {
|
||||||
data = t.getTransferData(dropFlavors[flavorIndex]);
|
data = t.getTransferData(dropFlavors[flavorIndex]);
|
||||||
} catch (Throwable thr) {
|
}
|
||||||
error=true;
|
catch (Throwable throwable) {
|
||||||
th = thr;
|
e.dropComplete(false);
|
||||||
|
dropComponent.undoDragUnderFeedback();
|
||||||
|
Msg.showError(this, null, "Drop Failed", "Could not get transfer data.", throwable);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error) {
|
// this is the copy
|
||||||
e.dropComplete(false);
|
DataFlavor flavor = dropFlavors[flavorIndex];
|
||||||
dropComponent.undoDragUnderFeedback();
|
try {
|
||||||
Msg.showError(this,null, "Drop Failed", "Could not get transfer data.", th);
|
dropComponent.add(data, e, flavor);
|
||||||
}
|
e.dropComplete(true);
|
||||||
else {
|
dropComponent.undoDragUnderFeedback();
|
||||||
// this is the copy
|
}
|
||||||
DataFlavor flavor=dropFlavors[flavorIndex];
|
catch (Throwable throwable) {
|
||||||
try {
|
e.dropComplete(false);
|
||||||
dropComponent.add(data, e, flavor);
|
dropComponent.undoDragUnderFeedback();
|
||||||
// notify drag source that the drop is complete...
|
String message = throwable.getMessage();
|
||||||
e.dropComplete(true);
|
Msg.showError(this, null, "Unexpected Drag and Drop Exception", message, throwable);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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?
|
// Does this target accept the drop action type being dropped on it?
|
||||||
int da = e.getDropAction();
|
int da = e.getDropAction();
|
||||||
if ((da & dropActions) == 0) {
|
if ((da & dropActions) == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Does the event's transferable have a flavor that this drop target accepts?
|
// Does the event's transferable have a flavor that this drop target accepts?
|
||||||
if (!isDragFlavorSupported(e)) {
|
if (!isDragFlavorSupported(e)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Does the target component allow the drop.
|
// Does the target component allow the drop.
|
||||||
if (!dropComponent.isDropOk(e)) {
|
if (!dropComponent.isDropOk(e)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
DataFlavor[] transferFlavors = e.getCurrentDataFlavors();
|
||||||
for (DataFlavor acceptableFlavor : acceptableFlavors) {
|
for (DataFlavor acceptableFlavor : acceptableFlavors) {
|
||||||
for (DataFlavor transferFlavor : transferFlavors) {
|
for (DataFlavor transferFlavor : transferFlavors) {
|
||||||
if (acceptableFlavor.equals(transferFlavor)) {
|
if (acceptableFlavor.equals(transferFlavor)) {
|
||||||
return 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,8 @@ public class DataTreeDragNDropHandler implements GTreeDragNDropHandler {
|
||||||
private static Map<DataFlavor, DataTreeFlavorHandler> activeProjectDropFlavorHandlerMap =
|
private static Map<DataFlavor, DataTreeFlavorHandler> activeProjectDropFlavorHandlerMap =
|
||||||
new HashMap<>();
|
new HashMap<>();
|
||||||
public static DataFlavor localDomainFileTreeFlavor = createLocalTreeNodeFlavor();
|
public static DataFlavor localDomainFileTreeFlavor = createLocalTreeNodeFlavor();
|
||||||
public static DataFlavor localDomainFileFlavor = createLocalTreeFlavor();
|
|
||||||
|
|
||||||
|
public static DataFlavor localDomainFileFlavor = createLocalTreeFlavor();
|
||||||
public static DataFlavor[] allSupportedFlavors =
|
public static DataFlavor[] allSupportedFlavors =
|
||||||
{ localDomainFileTreeFlavor, localDomainFileFlavor, DataFlavor.stringFlavor };
|
{ localDomainFileTreeFlavor, localDomainFileFlavor, DataFlavor.stringFlavor };
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ public class DataTreeDragNDropHandler implements GTreeDragNDropHandler {
|
||||||
.map(node -> ((DomainFileNode) node).getDomainFile())
|
.map(node -> ((DomainFileNode) node).getDomainFile())
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
else if (flavor == DataFlavor.stringFlavor) {
|
else if (flavor.equals(DataFlavor.stringFlavor)) {
|
||||||
// allow users to copy the names of nodes
|
// allow users to copy the names of nodes
|
||||||
return transferNodes.stream()
|
return transferNodes.stream()
|
||||||
.map(node -> node.getName())
|
.map(node -> node.getName())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue