From 84c16c2b272ed7e088f74a58dbe0a999b9be663e Mon Sep 17 00:00:00 2001 From: dragonmacher Date: Thu, 28 Mar 2019 18:24:34 -0400 Subject: [PATCH 1/2] GT-2705 - File Import - fixed drag-n-drop onto Project Tree dialogs --- .../foundation/FoundationInitializer.java | 33 +++-- ...hidraFileOpenDataFlavorHandlerService.java | 22 ++- .../app/util/JavaFileListFlavorHandler.java | 48 ------- .../GhidraDataFlavorHandlerService.java | 15 +-- .../main/datatree/JavaFileListHandler.java | 45 +++++-- .../main/datatree/LinuxFileUrlHandler.java | 5 +- .../app/util/FileOpenDataFlavorHandler.java | 12 +- .../FileOpenDataFlavorHandlerService.java | 37 ----- .../ghidra/app/util/FileOpenDropHandler.java | 31 +++-- .../app/util/LocalTreeNodeFlavorHandler.java | 72 ---------- .../util/LocalVersionInfoFlavorHandler.java | 47 ------- .../datatree/DataFlavorHandlerService.java | 38 ------ .../framework/main/datatree/DataTree.java | 126 ++---------------- .../datatree/DataTreeDragNDropHandler.java | 58 +++----- ...andler.java => DataTreeFlavorHandler.java} | 12 +- .../main/datatree/LocalTreeNodeHandler.java | 45 +++++-- .../datatree/LocalVersionInfoHandler.java | 83 +++++++----- .../main/datatree/ProjectDataTreePanel.java | 71 +++------- 18 files changed, 240 insertions(+), 560 deletions(-) delete mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/util/JavaFileListFlavorHandler.java delete mode 100644 Ghidra/Framework/Project/src/main/java/ghidra/app/util/FileOpenDataFlavorHandlerService.java delete mode 100644 Ghidra/Framework/Project/src/main/java/ghidra/app/util/LocalTreeNodeFlavorHandler.java delete mode 100644 Ghidra/Framework/Project/src/main/java/ghidra/app/util/LocalVersionInfoFlavorHandler.java delete mode 100644 Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataFlavorHandlerService.java rename Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/{DataFlavorHandler.java => DataTreeFlavorHandler.java} (69%) diff --git a/Ghidra/Features/Base/src/main/java/foundation/FoundationInitializer.java b/Ghidra/Features/Base/src/main/java/foundation/FoundationInitializer.java index 40a9a6b1ea..2634a143fd 100644 --- a/Ghidra/Features/Base/src/main/java/foundation/FoundationInitializer.java +++ b/Ghidra/Features/Base/src/main/java/foundation/FoundationInitializer.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,21 +15,29 @@ */ package foundation; -import ghidra.app.factory.*; -import ghidra.app.util.*; -import ghidra.framework.*; -import ghidra.framework.data.*; -import ghidra.framework.main.datatree.*; +import ghidra.app.factory.GhidraToolStateFactory; +import ghidra.app.util.GhidraFileOpenDataFlavorHandlerService; +import ghidra.framework.ModuleInitializer; +import ghidra.framework.PluggableServiceRegistry; +import ghidra.framework.data.ToolStateFactory; +import ghidra.framework.main.datatree.GhidraDataFlavorHandlerService; import ghidra.program.database.*; public class FoundationInitializer implements ModuleInitializer { - public void run() { - PluggableServiceRegistry.registerPluggableService( ToolStateFactory.class, new GhidraToolStateFactory() ); - PluggableServiceRegistry.registerPluggableService( DataFlavorHandlerService.class, new GhidraDataFlavorHandlerService() ); - PluggableServiceRegistry.registerPluggableService( FileOpenDataFlavorHandlerService.class, new GhidraFileOpenDataFlavorHandlerService() ); - PluggableServiceRegistry.registerPluggableService( DataTypeArchiveMergeManagerFactory.class, new GhidraDataTypeArchiveMergeManagerFactory() ); - PluggableServiceRegistry.registerPluggableService( ProgramMultiUserMergeManagerFactory.class, new GhidraProgramMultiUserMergeManagerFactory() ); - } + @Override + public void run() { + PluggableServiceRegistry.registerPluggableService(ToolStateFactory.class, + new GhidraToolStateFactory()); + PluggableServiceRegistry.registerPluggableService(GhidraDataFlavorHandlerService.class, + new GhidraDataFlavorHandlerService()); + PluggableServiceRegistry.registerPluggableService( + GhidraFileOpenDataFlavorHandlerService.class, + new GhidraFileOpenDataFlavorHandlerService()); + PluggableServiceRegistry.registerPluggableService(DataTypeArchiveMergeManagerFactory.class, + new GhidraDataTypeArchiveMergeManagerFactory()); + PluggableServiceRegistry.registerPluggableService(ProgramMultiUserMergeManagerFactory.class, + new GhidraProgramMultiUserMergeManagerFactory()); + } @Override public String getName() { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/GhidraFileOpenDataFlavorHandlerService.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/GhidraFileOpenDataFlavorHandlerService.java index 938be9843d..5302137db7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/GhidraFileOpenDataFlavorHandlerService.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/GhidraFileOpenDataFlavorHandlerService.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,14 +15,13 @@ */ package ghidra.app.util; -import ghidra.framework.main.datatree.*; - import java.awt.datatransfer.DataFlavor; -public class GhidraFileOpenDataFlavorHandlerService extends FileOpenDataFlavorHandlerService { +import ghidra.framework.main.datatree.*; - @Override - protected void doRegisterDataFlavorHandlers() { +public class GhidraFileOpenDataFlavorHandlerService { + + public GhidraFileOpenDataFlavorHandlerService() { try { DataFlavor linuxFileUrlFlavor = @@ -34,15 +32,15 @@ public class GhidraFileOpenDataFlavorHandlerService extends FileOpenDataFlavorHa // should never happen as it is using java.lang.String } - LocalTreeNodeFlavorHandler localHandler = new LocalTreeNodeFlavorHandler(); + LocalTreeNodeHandler localHandler = new LocalTreeNodeHandler(); FileOpenDropHandler.addDataFlavorHandler(DataTreeDragNDropHandler.localDomainFileFlavor, localHandler); - FileOpenDropHandler.addDataFlavorHandler(VersionInfoTransferable.localVersionInfoFlavor, + FileOpenDropHandler.addDataFlavorHandler(DataTreeDragNDropHandler.localDomainFileTreeFlavor, localHandler); - FileOpenDropHandler.addDataFlavorHandler(DataFlavor.javaFileListFlavor, - new JavaFileListFlavorHandler()); - FileOpenDropHandler.addDataFlavorHandler( - DataTreeDragNDropHandler.localDomainFileTreeFlavor, localHandler); + FileOpenDropHandler.addDataFlavorHandler(VersionInfoTransferable.localVersionInfoFlavor, + new LocalVersionInfoHandler()); + FileOpenDropHandler.addDataFlavorHandler(DataFlavor.javaFileListFlavor, + new JavaFileListHandler()); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/JavaFileListFlavorHandler.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/JavaFileListFlavorHandler.java deleted file mode 100644 index 3bf09ff2e5..0000000000 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/JavaFileListFlavorHandler.java +++ /dev/null @@ -1,48 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.app.util; - -import java.awt.datatransfer.DataFlavor; -import java.awt.dnd.DropTargetDropEvent; -import java.io.File; -import java.util.List; - -import ghidra.app.services.FileImporterService; -import ghidra.framework.model.DomainFolder; -import ghidra.framework.plugintool.PluginTool; -import util.CollectionUtils; - -final class JavaFileListFlavorHandler implements FileOpenDataFlavorHandler { - @Override - public void handle(PluginTool tool, Object obj, DropTargetDropEvent e, DataFlavor f) { - List files = CollectionUtils.asList((List) obj, File.class); - - FileImporterService im = tool.getService(FileImporterService.class); - if (im == null) { - tool.setStatusInfo("ERROR: Could not get importer service."); - return; - } - - DomainFolder rootFolder = tool.getProject().getProjectData().getRootFolder(); - - if (files.size() == 1 && files.get(0).isFile()) { - im.importFile(rootFolder, files.get(0)); - } - else { - im.importFiles(rootFolder, files); - } - } -} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/datatree/GhidraDataFlavorHandlerService.java b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/datatree/GhidraDataFlavorHandlerService.java index 45967e040a..c17fe17662 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/datatree/GhidraDataFlavorHandlerService.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/datatree/GhidraDataFlavorHandlerService.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,9 +17,10 @@ package ghidra.framework.main.datatree; import java.awt.datatransfer.DataFlavor; -public class GhidraDataFlavorHandlerService extends DataFlavorHandlerService { - @Override - protected void doRegisterDataFlavorHandlers() { +public class GhidraDataFlavorHandlerService { + + public GhidraDataFlavorHandlerService() { + try { DataFlavor linuxFileUrlFlavor = new DataFlavor("application/x-java-serialized-object;class=java.lang.String"); @@ -31,15 +31,12 @@ public class GhidraDataFlavorHandlerService extends DataFlavorHandlerService { // should never happen as it is using java.lang.String } - final LocalTreeNodeHandler localTreeNodeHandler = new LocalTreeNodeHandler(); + LocalTreeNodeHandler localNodeHandler = new LocalTreeNodeHandler(); DataTreeDragNDropHandler.addActiveDataFlavorHandler( - DataTreeDragNDropHandler.localDomainFileTreeFlavor, localTreeNodeHandler); + DataTreeDragNDropHandler.localDomainFileTreeFlavor, localNodeHandler); DataTreeDragNDropHandler.addActiveDataFlavorHandler(DataFlavor.javaFileListFlavor, new JavaFileListHandler()); DataTreeDragNDropHandler.addActiveDataFlavorHandler( VersionInfoTransferable.localVersionInfoFlavor, new LocalVersionInfoHandler()); - - DataTreeDragNDropHandler.addInactiveDataFlavorHandler( - DataTreeDragNDropHandler.localDomainFileTreeFlavor, localTreeNodeHandler); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/datatree/JavaFileListHandler.java b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/datatree/JavaFileListHandler.java index 69c8bb74a5..cf3c03d8a8 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/datatree/JavaFileListHandler.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/datatree/JavaFileListHandler.java @@ -19,13 +19,15 @@ package ghidra.framework.main.datatree; import java.awt.datatransfer.DataFlavor; +import java.awt.dnd.DropTargetDropEvent; import java.io.File; import java.util.List; import docking.widgets.tree.GTreeNode; import ghidra.app.services.FileImporterService; -import ghidra.framework.main.FrontEndTool; +import ghidra.app.util.FileOpenDataFlavorHandler; import ghidra.framework.model.DomainFolder; +import ghidra.framework.plugintool.PluginTool; import ghidra.util.Msg; import util.CollectionUtils; @@ -33,24 +35,43 @@ import util.CollectionUtils; * A drag-and-drop handler for trees that is specific to List<File>. (see * {@link DataFlavor#javaFileListFlavor}). */ -final class JavaFileListHandler implements DataFlavorHandler { - @Override - public void handle(FrontEndTool tool, DataTree dataTree, GTreeNode destinationNode, - Object transferData, int dropAction) { - DomainFolder folder = getDomainFolder(destinationNode); +public final class JavaFileListHandler implements DataTreeFlavorHandler, FileOpenDataFlavorHandler { - FileImporterService im = tool.getService(FileImporterService.class); - if (im == null) { - Msg.showError(this, dataTree, "Could Not Import", "Could not find importer service"); + @Override + public void handle(PluginTool tool, Object transferData, DropTargetDropEvent e, DataFlavor f) { + + FileImporterService importer = tool.getService(FileImporterService.class); + if (importer == null) { + Msg.showError(this, null, "Could Not Import", "Could not find Importer Service"); return; } - List fileList = CollectionUtils.asList((List) transferData, File.class); + DomainFolder folder = tool.getProject().getProjectData().getRootFolder(); + doImport(importer, folder, transferData); + } + + @Override + public void handle(PluginTool tool, DataTree dataTree, GTreeNode destinationNode, + Object transferData, int dropAction) { + + FileImporterService importer = tool.getService(FileImporterService.class); + if (importer == null) { + Msg.showError(this, dataTree, "Could Not Import", "Could not find Importer Service"); + return; + } + + DomainFolder folder = getDomainFolder(destinationNode); + doImport(importer, folder, transferData); + } + + private void doImport(FileImporterService importer, DomainFolder folder, Object files) { + + List fileList = CollectionUtils.asList((List) files, File.class); if (fileList.size() == 1 && fileList.get(0).isFile()) { - im.importFile(folder, fileList.get(0)); + importer.importFile(folder, fileList.get(0)); } else { - im.importFiles(folder, fileList); + importer.importFiles(folder, fileList); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/datatree/LinuxFileUrlHandler.java b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/datatree/LinuxFileUrlHandler.java index 9c6f1c115b..16a7e690ef 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/datatree/LinuxFileUrlHandler.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/datatree/LinuxFileUrlHandler.java @@ -27,7 +27,6 @@ import java.util.function.Function; import docking.widgets.tree.GTreeNode; import ghidra.app.services.FileImporterService; import ghidra.app.util.FileOpenDataFlavorHandler; -import ghidra.framework.main.FrontEndTool; import ghidra.framework.model.DomainFolder; import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.ServiceProvider; @@ -38,11 +37,11 @@ import ghidra.util.Msg; * duty in that it opens files for DataTrees and for Tools (signaled via the interfaces it * implements). */ -public final class LinuxFileUrlHandler implements DataFlavorHandler, FileOpenDataFlavorHandler { +public final class LinuxFileUrlHandler implements DataTreeFlavorHandler, FileOpenDataFlavorHandler { @Override // This is for the DataFlavorHandler interface for handling node drops in DataTrees - public void handle(FrontEndTool tool, DataTree dataTree, GTreeNode destinationNode, + public void handle(PluginTool tool, DataTree dataTree, GTreeNode destinationNode, Object transferData, int dropAction) { DomainFolder folder = getDomainFolder(destinationNode); diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/app/util/FileOpenDataFlavorHandler.java b/Ghidra/Framework/Project/src/main/java/ghidra/app/util/FileOpenDataFlavorHandler.java index f4bdd441cc..4852c85c39 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/app/util/FileOpenDataFlavorHandler.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/app/util/FileOpenDataFlavorHandler.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,11 +15,14 @@ */ package ghidra.app.util; -import ghidra.framework.plugintool.*; +import java.awt.datatransfer.DataFlavor; +import java.awt.dnd.DropTargetDropEvent; -import java.awt.datatransfer.*; -import java.awt.dnd.*; +import ghidra.framework.plugintool.PluginTool; +/** + * Interface for classes that will handle drop actions for files dropped onto the tool + */ public interface FileOpenDataFlavorHandler { - public void handle(PluginTool tool, Object obj, DropTargetDropEvent e, DataFlavor f); + public void handle(PluginTool tool, Object obj, DropTargetDropEvent e, DataFlavor f); } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/app/util/FileOpenDataFlavorHandlerService.java b/Ghidra/Framework/Project/src/main/java/ghidra/app/util/FileOpenDataFlavorHandlerService.java deleted file mode 100644 index 687e6aed63..0000000000 --- a/Ghidra/Framework/Project/src/main/java/ghidra/app/util/FileOpenDataFlavorHandlerService.java +++ /dev/null @@ -1,37 +0,0 @@ -/* ### - * IP: GHIDRA - * REVIEWED: YES - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.app.util; - -import ghidra.framework.PluggableServiceRegistry; -import ghidra.framework.main.datatree.DataTreeDragNDropHandler; -import ghidra.framework.main.datatree.VersionInfoTransferable; - -public class FileOpenDataFlavorHandlerService { - static { - PluggableServiceRegistry.registerPluggableService(FileOpenDataFlavorHandlerService.class, new FileOpenDataFlavorHandlerService()); - } - - public static void registerDataFlavorHandlers() { - FileOpenDataFlavorHandlerService factory = PluggableServiceRegistry.getPluggableService(FileOpenDataFlavorHandlerService.class); - factory.doRegisterDataFlavorHandlers(); - } - - protected void doRegisterDataFlavorHandlers() { - FileOpenDropHandler.addDataFlavorHandler(DataTreeDragNDropHandler.localDomainFileFlavor, new LocalTreeNodeFlavorHandler()); - FileOpenDropHandler.addDataFlavorHandler(VersionInfoTransferable.localVersionInfoFlavor, new LocalTreeNodeFlavorHandler()); - } -} diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/app/util/FileOpenDropHandler.java b/Ghidra/Framework/Project/src/main/java/ghidra/app/util/FileOpenDropHandler.java index 7a16da0504..6a4e4428ce 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/app/util/FileOpenDropHandler.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/app/util/FileOpenDropHandler.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,9 +15,6 @@ */ package ghidra.app.util; -import ghidra.framework.plugintool.PluginTool; -import ghidra.util.CascadedDropTarget; - import java.awt.Component; import java.awt.Container; import java.awt.datatransfer.DataFlavor; @@ -33,6 +29,8 @@ import javax.swing.CellRendererPane; import docking.DropTargetHandler; import docking.dnd.DropTgtAdapter; import docking.dnd.Droppable; +import ghidra.framework.plugintool.PluginTool; +import ghidra.util.CascadedDropTarget; /** * Handles drag/drop events on a given component such that a file @@ -44,9 +42,6 @@ import docking.dnd.Droppable; public class FileOpenDropHandler implements DropTargetHandler, Droppable, ContainerListener { private static HashMap handlers = new HashMap(); - static { - FileOpenDataFlavorHandlerService.registerDataFlavorHandlers(); - } private DropTgtAdapter dropTargetAdapter; private DropTarget globalDropTarget; @@ -75,11 +70,13 @@ public class FileOpenDropHandler implements DropTargetHandler, Droppable, Contai /** * Dispose this drop handler. */ + @Override public void dispose() { deinitializeComponents(component); globalDropTarget.removeDropTargetListener(dropTargetAdapter); } + @Override public boolean isDropOk(DropTargetDragEvent e) { Set flavors = handlers.keySet(); for (DataFlavor dataFlavor : flavors) { @@ -90,6 +87,7 @@ public class FileOpenDropHandler implements DropTargetHandler, Droppable, Contai return false; } + @Override public void add(Object obj, DropTargetDropEvent e, DataFlavor f) { FileOpenDataFlavorHandler handler = handlers.get(f); if (handler != null) { @@ -97,24 +95,28 @@ public class FileOpenDropHandler implements DropTargetHandler, Droppable, Contai } } + @Override public void dragUnderFeedback(boolean ok, DropTargetDragEvent e) { // nothing to display or do } + @Override public void undoDragUnderFeedback() { // nothing to display or do } private void initializeComponents(Component comp) { - if (comp instanceof CellRendererPane) + if (comp instanceof CellRendererPane) { return; + } if (comp instanceof Container) { Container c = (Container) comp; c.addContainerListener(this); Component comps[] = c.getComponents(); - for (Component element : comps) + for (Component element : comps) { initializeComponents(element); + } } DropTarget primaryDropTarget = comp.getDropTarget(); if (primaryDropTarget != null) { @@ -123,15 +125,17 @@ public class FileOpenDropHandler implements DropTargetHandler, Droppable, Contai } private void deinitializeComponents(Component comp) { - if (comp instanceof CellRendererPane) + if (comp instanceof CellRendererPane) { return; + } if (comp instanceof Container) { Container c = (Container) comp; c.removeContainerListener(this); Component comps[] = c.getComponents(); - for (Component element : comps) + for (Component element : comps) { deinitializeComponents(element); + } } DropTarget dt = comp.getDropTarget(); if (dt instanceof CascadedDropTarget) { @@ -141,15 +145,18 @@ public class FileOpenDropHandler implements DropTargetHandler, Droppable, Contai } } + @Override public void componentAdded(ContainerEvent e) { initializeComponents(e.getChild()); } + @Override public void componentRemoved(ContainerEvent e) { deinitializeComponents(e.getChild()); } - public static void addDataFlavorHandler(DataFlavor dataFlavor, FileOpenDataFlavorHandler handler) { + public static void addDataFlavorHandler(DataFlavor dataFlavor, + FileOpenDataFlavorHandler handler) { handlers.put(dataFlavor, handler); } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/app/util/LocalTreeNodeFlavorHandler.java b/Ghidra/Framework/Project/src/main/java/ghidra/app/util/LocalTreeNodeFlavorHandler.java deleted file mode 100644 index fe87e5cf59..0000000000 --- a/Ghidra/Framework/Project/src/main/java/ghidra/app/util/LocalTreeNodeFlavorHandler.java +++ /dev/null @@ -1,72 +0,0 @@ -/* ### - * IP: GHIDRA - * REVIEWED: YES - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * - */ -package ghidra.app.util; - -import ghidra.framework.main.GetVersionedObjectTask; -import ghidra.framework.main.datatree.*; -import ghidra.framework.model.*; -import ghidra.framework.plugintool.PluginTool; - -import java.awt.datatransfer.DataFlavor; -import java.awt.dnd.DropTargetDropEvent; -import java.util.List; - -final class LocalTreeNodeFlavorHandler implements FileOpenDataFlavorHandler { - public void handle(PluginTool tool, Object obj, DropTargetDropEvent e, DataFlavor f) { - if (f.equals(DataTreeDragNDropHandler.localDomainFileFlavor)) { - List files = (List) obj; - DomainFile[] domainFiles = new DomainFile[files.size()]; - for (int i = 0; i < files.size(); i++) { - domainFiles[i] = (DomainFile) files.get(i); - } - tool.acceptDomainFiles(domainFiles); - } - else if (f.equals(DataTreeDragNDropHandler.localDomainFileTreeFlavor)) { - List files = (List) obj; - DomainFile[] domainFiles = new DomainFile[files.size()]; - for (int i = 0; i < files.size(); i++) { - DomainFileNode node = (DomainFileNode) files.get(i); - domainFiles[i] = node.getDomainFile(); - } - tool.acceptDomainFiles(domainFiles); - } - else if (f.equals(VersionInfoTransferable.localVersionInfoFlavor)) { - VersionInfo info = (VersionInfo) obj; - Project project = tool.getProject(); - ProjectData projectData = project.getProjectData(); - DomainFile file = projectData.getFile(info.getDomainFilePath()); - DomainObject versionedObj = getVersionedObject(tool, file, info.getVersionNumber()); - - if (versionedObj != null) { - DomainFile domainFile = versionedObj.getDomainFile(); - if (domainFile != null) { - tool.acceptDomainFiles(new DomainFile[] { domainFile }); - } - versionedObj.release(this); - } - } - } - - private DomainObject getVersionedObject(PluginTool tool, DomainFile file, int versionNumber) { - GetVersionedObjectTask task = new GetVersionedObjectTask(this, file, versionNumber); - tool.execute(task, 250); - return task.getVersionedObject(); - } -} diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/app/util/LocalVersionInfoFlavorHandler.java b/Ghidra/Framework/Project/src/main/java/ghidra/app/util/LocalVersionInfoFlavorHandler.java deleted file mode 100644 index 62d2bd7e75..0000000000 --- a/Ghidra/Framework/Project/src/main/java/ghidra/app/util/LocalVersionInfoFlavorHandler.java +++ /dev/null @@ -1,47 +0,0 @@ -/* ### - * IP: GHIDRA - * REVIEWED: YES - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * - */ -package ghidra.app.util; - -import ghidra.framework.main.*; -import ghidra.framework.main.datatree.*; -import ghidra.framework.model.*; -import ghidra.framework.plugintool.*; - -import java.awt.datatransfer.*; -import java.awt.dnd.*; - -final class LocalVersionInfoFlavorHandler implements - FileOpenDataFlavorHandler { - public void handle(PluginTool tool, Object obj, DropTargetDropEvent e, DataFlavor f) { - VersionInfo info = (VersionInfo) obj; - - DomainFile file = tool.getProject().getProjectData().getFile(info.getDomainFilePath()); - GetVersionedObjectTask task = new GetVersionedObjectTask(this, file, - info.getVersionNumber()); - tool.execute(task, 250); - DomainObject versionedObj = task.getVersionedObject(); - - if (versionedObj != null) { - DomainFile vfile = versionedObj.getDomainFile(); - tool.acceptDomainFiles(new DomainFile[] {vfile}); - versionedObj.release(this); - } - } -} diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataFlavorHandlerService.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataFlavorHandlerService.java deleted file mode 100644 index 3d6bedb22b..0000000000 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataFlavorHandlerService.java +++ /dev/null @@ -1,38 +0,0 @@ -/* ### - * IP: GHIDRA - * REVIEWED: YES - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.framework.main.datatree; - -import ghidra.framework.PluggableServiceRegistry; - -public class DataFlavorHandlerService { - static { - PluggableServiceRegistry.registerPluggableService(DataFlavorHandlerService.class, new DataFlavorHandlerService()); - } - - public static void registerDataFlavorHandlers() { - DataFlavorHandlerService factory = PluggableServiceRegistry.getPluggableService(DataFlavorHandlerService.class); - factory.doRegisterDataFlavorHandlers(); - } - - protected void doRegisterDataFlavorHandlers() { - final LocalTreeNodeHandler localTreeNodeHandler = new LocalTreeNodeHandler(); - DataTreeDragNDropHandler.addActiveDataFlavorHandler(DataTreeDragNDropHandler.localDomainFileTreeFlavor, localTreeNodeHandler); - DataTreeDragNDropHandler.addActiveDataFlavorHandler(VersionInfoTransferable.localVersionInfoFlavor, new LocalVersionInfoHandler()); - - DataTreeDragNDropHandler.addInactiveDataFlavorHandler(DataTreeDragNDropHandler.localDomainFileTreeFlavor, localTreeNodeHandler); - } -} diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTree.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTree.java index 513e2aab26..d2e3c8d145 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTree.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTree.java @@ -16,8 +16,7 @@ package ghidra.framework.main.datatree; import java.awt.Component; -import java.awt.event.*; -import java.util.List; +import java.awt.event.KeyEvent; import javax.swing.JTree; import javax.swing.KeyStroke; @@ -30,20 +29,13 @@ import docking.widgets.tree.support.GTreeRenderer; import ghidra.framework.main.FrontEndTool; /** - * Tree that shows the folders and domain files in a Project. + * Tree that shows the folders and domain files in a Project */ public class DataTree extends GTree { - static { - DataFlavorHandlerService.registerDataFlavorHandlers(); - } private boolean isActive; private DataTreeDragNDropHandler dragNDropHandler; - /** - * Constructor - * @param folder root domain folder for the project. - */ DataTree(FrontEndTool tool, GTreeRootNode root) { super(root); @@ -53,30 +45,11 @@ public class DataTree extends GTree { docking.ToolTipManager.sharedInstance().registerComponent(this); - //When the user right clicks, change selection to what the mouse was under - addMouseListener(new MouseAdapter() { - @Override - public void mousePressed(MouseEvent evt) { - if (evt.getButton() == MouseEvent.BUTTON3) { - //Find the would-be newly selected path - TreePath newPath = getPathForLocation(evt.getX(), evt.getY()); - if (newPath == null) { - return; - } - //Determine if the path is already selected--If so, do not change the selection - TreePath[] paths = getSelectionPaths(); - if (paths != null) { - for (TreePath element : paths) { - if (element.equals(newPath)) { - return; - } - } - } - } - } - }); - dragNDropHandler = new DataTreeDragNDropHandler(tool, this, isActive); - setDragNDropHandler(dragNDropHandler); + if (tool != null) { + dragNDropHandler = new DataTreeDragNDropHandler(tool, this, isActive); + setDragNDropHandler(dragNDropHandler); + } + initializeKeyEvents(); } @@ -92,74 +65,10 @@ public class DataTree extends GTree { KeyStroke.getKeyStroke(KeyEvent.VK_X, DockingUtils.CONTROL_KEY_MODIFIER_MASK)); } - void setProjectActive(boolean b) { - dragNDropHandler.setProjectActive(b); - } - - /** - * Return true if this path has all of its subpaths expanded. - */ - public boolean allPathsExpanded(TreePath path) { - - GTreeNode node = (GTreeNode) path.getLastPathComponent(); - if (node.isLeaf()) { - return true; + void setProjectActive(boolean isActive) { + if (dragNDropHandler != null) { + dragNDropHandler.setProjectActive(isActive); } - if (isCollapsed(path)) { - return false; - } - - boolean allLeaves = true; - - List children = node.getChildren(); - for (GTreeNode child : children) { - if (child.isLeaf()) { - continue; - } - allLeaves = false; - if (!isExpanded(child.getTreePath())) { - return false; - } - - if (!allPathsExpanded(child.getTreePath())) { - return false; - } - } - if (allLeaves) { - return isExpanded(path); - } - return true; - } - - /** - * Return true if this path has all of its subpaths collapsed. - */ - public boolean allPathsCollapsed(TreePath path) { - GTreeNode node = (GTreeNode) path.getLastPathComponent(); - - if (isExpanded(path)) { - return false; - } - boolean allLeaves = true; // variable for knowing whether all children are leaves - - node.getChildren(); - for (GTreeNode child : node) { - if (child.isLeaf()) { - continue; - } - allLeaves = false; - if (!isCollapsed(child.getTreePath())) { - return false; - } - - if (!allPathsCollapsed(child.getTreePath())) { - return false; - } - } - if (allLeaves) { - return isCollapsed(path); - } - return true; } public void clearSelection() { @@ -183,20 +92,7 @@ public class DataTree extends GTree { getJTree().stopEditing(); } - ////////////////////////////////////////////////////////////////////// - // *** private methods - ////////////////////////////////////////////////////////////////////// - /** - * Tree cell renderer to use the appropriate icons for the - * DataTreeNodes. - */ private class DataTreeCellRenderer extends GTreeRenderer { - - /** - * Configures the renderer based on the passed in components. - * The icon is set according to value, expanded, and leaf - * parameters. - */ @Override public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean doesHaveFocus) { @@ -209,7 +105,5 @@ public class DataTree extends GTree { } return this; } - } - } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeDragNDropHandler.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeDragNDropHandler.java index a7b9f32770..70293082f3 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeDragNDropHandler.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeDragNDropHandler.java @@ -30,9 +30,7 @@ import ghidra.util.Msg; import ghidra.util.exception.AssertException; public class DataTreeDragNDropHandler implements GTreeDragNDropHandler { - private static Map activeProjectDropFlavorHandlerMap = - new HashMap<>(); - private static Map inactiveProjectDropFlavorHandlerMap = + private static Map activeProjectDropFlavorHandlerMap = new HashMap<>(); public static DataFlavor localDomainFileTreeFlavor = createLocalTreeNodeFlavor(); public static DataFlavor localDomainFileFlavor = createLocalTreeFlavor(); @@ -79,29 +77,31 @@ public class DataTreeDragNDropHandler implements GTreeDragNDropHandler { public void drop(GTreeNode destination, Transferable transferable, int dropAction) { DataFlavor[] transferDataFlavors = transferable.getTransferDataFlavors(); for (DataFlavor dataFlavor : transferDataFlavors) { - DataFlavorHandler flavorHandler = getFlavorHandler(dataFlavor); + DataTreeFlavorHandler flavorHandler = getFlavorHandler(dataFlavor); if (flavorHandler != null) { - try { - Object transferData = transferable.getTransferData(dataFlavor); - flavorHandler.handle(tool, tree, destination, transferData, dropAction); - } - catch (UnsupportedFlavorException e) { - throw new AssertException( - "Got unsupported flavor from using a supported flavor"); - } - catch (IOException e) { - Msg.showError(this, null, "IO Error", "Error during drop", e); - } + handleDrop(destination, transferable, dropAction, dataFlavor, flavorHandler); return; } } } - private DataFlavorHandler getFlavorHandler(DataFlavor flavor) { - if (isActiveProject) { - return activeProjectDropFlavorHandlerMap.get(flavor); + private void handleDrop(GTreeNode destination, Transferable transferable, int dropAction, + DataFlavor dataFlavor, DataTreeFlavorHandler flavorHandler) { + + try { + Object transferData = transferable.getTransferData(dataFlavor); + flavorHandler.handle(tool, tree, destination, transferData, dropAction); } - return inactiveProjectDropFlavorHandlerMap.get(flavor); + catch (UnsupportedFlavorException e) { + throw new AssertException("Got unsupported flavor from using a supported flavor"); + } + catch (IOException e) { + Msg.showError(this, null, "IO Error", "Error during drop", e); + } + } + + private DataTreeFlavorHandler getFlavorHandler(DataFlavor flavor) { + return activeProjectDropFlavorHandlerMap.get(flavor); } @Override @@ -134,13 +134,6 @@ public class DataTreeDragNDropHandler implements GTreeDragNDropHandler { @Override public DataFlavor[] getSupportedDataFlavors(List transferNodes) { return allSupportedFlavors; -// Set keySet = null; -// if (isActiveProject) { -// keySet = activeProjectDropFlavorHandlerMap.keySet(); -// } else { -// keySet = inactiveProjectDropFlavorHandlerMap.keySet(); -// } -// return keySet.toArray(new DataFlavor[keySet.size()]); } @Override @@ -196,24 +189,15 @@ public class DataTreeDragNDropHandler implements GTreeDragNDropHandler { return false; } - public static void addActiveDataFlavorHandler(DataFlavor flavor, DataFlavorHandler handler) { + public static void addActiveDataFlavorHandler(DataFlavor flavor, DataTreeFlavorHandler handler) { activeProjectDropFlavorHandlerMap.put(flavor, handler); } - public static void addInactiveDataFlavorHandler(DataFlavor flavor, DataFlavorHandler handler) { - inactiveProjectDropFlavorHandlerMap.put(flavor, handler); - } - - public static DataFlavorHandler removeActiveDataFlavorHandler(DataFlavor flavor) { + public static DataTreeFlavorHandler removeActiveDataFlavorHandler(DataFlavor flavor) { return activeProjectDropFlavorHandlerMap.remove(flavor); } - public static DataFlavorHandler removeInctiveDataFlavorHandler(DataFlavor flavor) { - return inactiveProjectDropFlavorHandlerMap.remove(flavor); - } - public void setProjectActive(boolean b) { isActiveProject = b; } - } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataFlavorHandler.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeFlavorHandler.java similarity index 69% rename from Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataFlavorHandler.java rename to Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeFlavorHandler.java index f63e22469c..18aba84d63 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataFlavorHandler.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeFlavorHandler.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,10 +15,13 @@ */ package ghidra.framework.main.datatree; -import ghidra.framework.main.FrontEndTool; import docking.widgets.tree.GTreeNode; +import ghidra.framework.plugintool.PluginTool; -public interface DataFlavorHandler { - public void handle(FrontEndTool tool, DataTree dataTree, GTreeNode destinationNode, - Object transferData, int dropAction); +/** + * Interface for classes that will handle drop actions for {@link DataTree}s. + */ +public interface DataTreeFlavorHandler { + public void handle(PluginTool tool, DataTree dataTree, GTreeNode destinationNode, + Object transferData, int dropAction); } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/LocalTreeNodeHandler.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/LocalTreeNodeHandler.java index a31fcc76af..bcc70cdd84 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/LocalTreeNodeHandler.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/LocalTreeNodeHandler.java @@ -15,29 +15,55 @@ */ package ghidra.framework.main.datatree; +import java.awt.datatransfer.DataFlavor; import java.awt.dnd.DnDConstants; +import java.awt.dnd.DropTargetDropEvent; import java.io.IOException; import java.util.List; -import javax.swing.SwingUtilities; - import docking.widgets.tree.GTreeNode; import docking.widgets.tree.GTreeState; -import ghidra.framework.main.FrontEndTool; +import ghidra.app.util.FileOpenDataFlavorHandler; import ghidra.framework.model.DomainFile; import ghidra.framework.model.DomainFolder; +import ghidra.framework.plugintool.PluginTool; import ghidra.util.Msg; +import ghidra.util.SystemUtilities; import ghidra.util.exception.DuplicateFileException; import ghidra.util.exception.FileInUseException; import ghidra.util.task.*; -final class LocalTreeNodeHandler implements DataFlavorHandler { +public final class LocalTreeNodeHandler + implements DataTreeFlavorHandler, FileOpenDataFlavorHandler { + private DataTree dataTree; private GTreeState treeState; + @Override + public void handle(PluginTool tool, Object obj, DropTargetDropEvent e, DataFlavor f) { + + if (f.equals(DataTreeDragNDropHandler.localDomainFileFlavor)) { + List files = (List) obj; + DomainFile[] domainFiles = new DomainFile[files.size()]; + for (int i = 0; i < files.size(); i++) { + domainFiles[i] = (DomainFile) files.get(i); + } + tool.acceptDomainFiles(domainFiles); + } + else if (f.equals(DataTreeDragNDropHandler.localDomainFileTreeFlavor)) { + List files = (List) obj; + DomainFile[] domainFiles = new DomainFile[files.size()]; + for (int i = 0; i < files.size(); i++) { + DomainFileNode node = (DomainFileNode) files.get(i); + domainFiles[i] = node.getDomainFile(); + } + tool.acceptDomainFiles(domainFiles); + } + } + @Override @SuppressWarnings("unchecked") - public void handle(FrontEndTool tool, DataTree tree, GTreeNode destinationNode, + public void handle(PluginTool tool, DataTree tree, GTreeNode destinationNode, Object transferData, int dropAction) { this.dataTree = tree; @@ -52,12 +78,9 @@ final class LocalTreeNodeHandler implements DataFlavorHandler { new TaskLauncher(task, dataTree, 1000); if (treeState != null) { // is set to null if drag results in a task - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - treeState.updateStateForMovedNodes(); - dataTree.restoreTreeState(treeState); - } + SystemUtilities.runSwingLater(() -> { + treeState.updateStateForMovedNodes(); + dataTree.restoreTreeState(treeState); }); } } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/LocalVersionInfoHandler.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/LocalVersionInfoHandler.java index 3dc8e451ec..294f45895d 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/LocalVersionInfoHandler.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/LocalVersionInfoHandler.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,42 +13,64 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** - * - */ package ghidra.framework.main.datatree; -import ghidra.framework.client.*; -import ghidra.framework.main.FrontEndTool; -import ghidra.framework.model.DomainFile; -import ghidra.framework.model.DomainFolder; -import ghidra.util.task.TaskLauncher; - +import java.awt.datatransfer.DataFlavor; +import java.awt.dnd.DropTargetDropEvent; import java.io.IOException; import docking.widgets.tree.GTreeNode; +import ghidra.app.util.FileOpenDataFlavorHandler; +import ghidra.framework.client.*; +import ghidra.framework.main.GetVersionedObjectTask; +import ghidra.framework.model.*; +import ghidra.framework.plugintool.PluginTool; +import ghidra.util.task.TaskLauncher; -final class LocalVersionInfoHandler implements DataFlavorHandler { - public void handle(FrontEndTool tool, DataTree dataTree, GTreeNode destinationNode, - Object transferData, int dropAction) { - DomainFolder folder = getDomainFolder(destinationNode); - - VersionInfo info = (VersionInfo) transferData; - RepositoryAdapter rep = tool.getProject().getProjectData().getRepository(); - try { - if (rep != null) { - rep.connect(); - } - DomainFile file = tool.getProject().getProjectData().getFile(info.getDomainFilePath()); - if (file != null) { - new TaskLauncher(new CopyFileVersionTask(file, info.getVersionNumber(), folder), dataTree, 500); - } - } - catch (NotConnectedException exc) {} - catch (IOException exc) { - ClientUtil.handleException(rep, exc, "Repository Connection", tool.getToolFrame()); - } - } +public final class LocalVersionInfoHandler + implements DataTreeFlavorHandler, FileOpenDataFlavorHandler { + + @Override + public void handle(PluginTool tool, Object obj, DropTargetDropEvent e, DataFlavor f) { + VersionInfo info = (VersionInfo) obj; + + DomainFile file = tool.getProject().getProjectData().getFile(info.getDomainFilePath()); + GetVersionedObjectTask task = + new GetVersionedObjectTask(this, file, info.getVersionNumber()); + tool.execute(task, 250); + DomainObject versionedObj = task.getVersionedObject(); + + if (versionedObj != null) { + DomainFile vfile = versionedObj.getDomainFile(); + tool.acceptDomainFiles(new DomainFile[] { vfile }); + versionedObj.release(this); + } + } + + @Override + public void handle(PluginTool tool, DataTree dataTree, GTreeNode destinationNode, + Object transferData, int dropAction) { + DomainFolder folder = getDomainFolder(destinationNode); + + VersionInfo info = (VersionInfo) transferData; + RepositoryAdapter rep = tool.getProject().getProjectData().getRepository(); + try { + if (rep != null) { + rep.connect(); + } + DomainFile file = tool.getProject().getProjectData().getFile(info.getDomainFilePath()); + if (file != null) { + new TaskLauncher(new CopyFileVersionTask(file, info.getVersionNumber(), folder), + dataTree, 500); + } + } + catch (NotConnectedException exc) { + // not sure why we squash this? + } + catch (IOException exc) { + ClientUtil.handleException(rep, exc, "Repository Connection", tool.getToolFrame()); + } + } private DomainFolder getDomainFolder(GTreeNode destinationNode) { if (destinationNode instanceof DomainFolderNode) { diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/ProjectDataTreePanel.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/ProjectDataTreePanel.java index 1651798827..4070ac82c0 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/ProjectDataTreePanel.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/ProjectDataTreePanel.java @@ -55,33 +55,26 @@ public class ProjectDataTreePanel extends JPanel { private ChangeManager changeMgr; private boolean isActiveProject; - private FrontEndTool tool; // may be null if the panel is inside of the - + // these may be null if the panel is inside of a dialog + private FrontEndTool tool; private FrontEndPlugin plugin; - // data tree dialog - /** - * Construct an empty panel that is going to be used as the active - * panel. - * @param tool front end tool + * Construct an empty panel that is going to be used as the active panel + * @param plugin front end plugin */ public ProjectDataTreePanel(FrontEndPlugin plugin) { this(null, true, plugin, null); } /** - * Construct a new DataTreePanel. + * Constructor + * * @param projectName name of project - * @param projectData object that provides access to all the user data - * folders in a project * @param isActiveProject true if the project is active, and the * data tree may be modified - * @param tool front end tool; will be null if the panel is used in a dialog - * @param actionMgr class to handle enablement of actions; an ActionManager - * is passed in when several data tree panels all need to use the - * same ActionManager, e.g., the viewed projects in the front end tool; - * actionMgr will be null if the panel is used in a dialog + * @param plugin front end plugin; will be null if the panel is used in a dialog + * @param filter optional filter that is used to hide programs from view */ public ProjectDataTreePanel(String projectName, boolean isActiveProject, FrontEndPlugin plugin, DomainFileFilter filter) { @@ -211,9 +204,6 @@ public class ProjectDataTreePanel extends JPanel { } } - /** - * Set the help location for the data tree. - */ public void setHelpLocation(HelpLocation helpLocation) { HelpService help = Help.getHelpService(); help.registerHelp(tree, helpLocation); @@ -228,8 +218,9 @@ public class ProjectDataTreePanel extends JPanel { } /** - * Get the number of selected items in the tree. - * These could be either DomainFile's or DomainFolder's. + * Get the number of selected items in the tree. These could be either files or folders. + * + * @return the number of selected items in the tree. */ public int getSelectedItemCount() { return tree.getSelectionCount(); @@ -279,47 +270,31 @@ public class ProjectDataTreePanel extends JPanel { tree.removeGTreeSelectionListener(l); } - /** - * Add a mouse listener to the data tree. - */ public void addTreeMouseListener(MouseListener l) { tree.addMouseListener(l); } - /** - * Remove the mouse listener from the data tree. - */ public void removeTreeMouseListener(MouseListener l) { tree.removeMouseListener(l); } - /** - * Set the preferred size of the scroll pane that contains the - * data tree. - */ public void setPreferredTreePanelSize(Dimension d) { tree.setPreferredSize(d); } - /** - * Get the project data that this data tree panel is operating on. - */ public ProjectData getProjectData() { return projectData; } /** * Notification that the project was renamed; update the root node name - * and reload the node. + * and reload the node + * @param newName the new project name */ public void projectRenamed(String newName) { updateProjectName(newName); } - /** - * Notification that panel is being disposed. - * - */ public void dispose() { if (projectData != null) { projectData.removeDomainFolderChangeListener(changeMgr); @@ -328,10 +303,12 @@ public class ProjectDataTreePanel extends JPanel { } /** - * Get the data tree node that is selected. - * @param e mouse event for the popup; may be null if this is being - * called as a result of the key binding pressed - * @return null if there is no selection + * Get the data tree node that is selected + * + * @param provider the provider with which to construct the new context + * @param e mouse event for the popup; may be null if this is being called as a result of + * the key binding pressed + * @return the new context; null if there is no selection */ public ActionContext getActionContext(ComponentProvider provider, MouseEvent e) { if (root instanceof NoProjectNode) { @@ -364,9 +341,6 @@ public class ProjectDataTreePanel extends JPanel { domainFolderList, domainFileList, tree, isActiveProject); } - /** - * get the data tree for this data tree panel. - */ public DataTree getDataTree() { return tree; } @@ -380,17 +354,10 @@ public class ProjectDataTreePanel extends JPanel { tree.setFilterVisible(enabled); } - /** - * Return true if this data tree panel is listening to domain folder - * changes. - */ boolean domainFolderListenerAdded() { return changeMgr != null; } - /** - * Get the folder change listener. - */ DomainFolderChangeListener getFolderChangeListener() { return changeMgr; } From f3ef6956c92996e45bf4c67ad4ade13190677d0e Mon Sep 17 00:00:00 2001 From: dragonmacher Date: Thu, 28 Mar 2019 18:25:09 -0400 Subject: [PATCH 2/2] GT-2705 - File Import - review fixes; updated transient project dialogs to not have copy/paste actions etc --- .../core/datamgr/DataTypesActionContext.java | 14 +-- .../ghidra/framework/main/DataTreeDialog.java | 12 +- .../src/main/java/docking/ActionContext.java | 11 +- .../tree/support/GTreeNodeTransferable.java | 119 +++++++++--------- .../datatable/ProjectDataActionContext.java | 17 +++ .../datatable/ProjectDataContextAction.java | 29 ++++- .../ProjectDataContextToggleAction.java | 23 +++- .../ProjectDataTreeContextAction.java | 27 +++- .../main/datatree/DataTreeClipboardUtils.java | 16 +-- .../datatree/DataTreeNodeTransferable.java | 30 ----- .../ProjectDataTreeActionContext.java | 8 +- .../main/datatree/ProjectDataTreePanel.java | 7 +- .../actions/ProjectDataCollapseAction.java | 2 +- .../actions/ProjectDataCopyAction.java | 2 +- .../actions/ProjectDataCutAction.java | 2 +- .../actions/ProjectDataExpandAction.java | 2 +- .../actions/ProjectDataNewFolderAction.java | 6 + .../actions/ProjectDataPasteAction.java | 2 +- .../actions/ProjectDataReadOnlyAction.java | 4 + .../actions/ProjectDataSelectAction.java | 2 +- 20 files changed, 201 insertions(+), 134 deletions(-) delete mode 100644 Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeNodeTransferable.java diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesActionContext.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesActionContext.java index 40aed341b9..4b8ebb9d45 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesActionContext.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesActionContext.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +15,12 @@ */ package ghidra.app.plugin.core.datamgr; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.tree.TreePath; + +import docking.widgets.tree.GTreeNode; import ghidra.app.context.ProgramActionContext; import ghidra.app.plugin.core.datamgr.archive.ProjectArchive; import ghidra.app.plugin.core.datamgr.tree.DataTypeArchiveGTree; @@ -24,13 +29,6 @@ import ghidra.framework.main.datatable.DomainFileProvider; import ghidra.framework.model.DomainFile; import ghidra.program.model.listing.Program; -import java.util.ArrayList; -import java.util.List; - -import javax.swing.tree.TreePath; - -import docking.widgets.tree.GTreeNode; - public class DataTypesActionContext extends ProgramActionContext implements DomainFileProvider { private final GTreeNode clickedNode; private final boolean isToolbarAction; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/DataTreeDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/DataTreeDialog.java index cee3dd427a..526202aadd 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/DataTreeDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/DataTreeDialog.java @@ -26,6 +26,7 @@ import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import docking.*; +import docking.event.mouse.GMouseListenerAdapter; import docking.widgets.tree.support.GTreeSelectionEvent; import docking.widgets.tree.support.GTreeSelectionListener; import ghidra.framework.main.datatree.ClearCutAction; @@ -40,7 +41,7 @@ import ghidra.util.layout.PairLayout; * Dialog to open or save domain data items to a new location or name. */ public class DataTreeDialog extends DialogComponentProvider -implements GTreeSelectionListener, ActionListener { + implements GTreeSelectionListener, ActionListener { /** * Dialog type for opening domain data files. @@ -540,10 +541,11 @@ implements GTreeSelectionListener, ActionListener { protected void addTreeListeners() { if (type == OPEN) { - treePanel.addTreeMouseListener(new MouseAdapter() { + + treePanel.addTreeMouseListener(new GMouseListenerAdapter() { @Override - public void mousePressed(MouseEvent e) { - if (e.getClickCount() == 2 && okButton.isEnabled()) { + public void doubleClickTriggered(MouseEvent e) { + if (okButton.isEnabled()) { okCallback(); } } @@ -671,7 +673,7 @@ implements GTreeSelectionListener, ActionListener { // populate the combo box DefaultComboBoxModel model = - (DefaultComboBoxModel) projectComboBox.getModel(); + (DefaultComboBoxModel) projectComboBox.getModel(); model.removeAllElements(); Set map = new HashSet<>(); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/ActionContext.java b/Ghidra/Framework/Docking/src/main/java/docking/ActionContext.java index 3fed77d232..f9d950e63e 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/ActionContext.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/ActionContext.java @@ -47,7 +47,12 @@ public class ActionContext { } /** - * For Testing + * Constructor + * + * @param provider the ComponentProvider that generated this context. + * @param contextObject an optional contextObject that the ComponentProvider can provide + * @param sourceObject an optional source object; this can be anything that actions wish to + * later retrieve */ public ActionContext(ComponentProvider provider, Object contextObject, Object sourceObject) { this(provider, contextObject); @@ -55,8 +60,8 @@ public class ActionContext { } /** - * Returns the {@link #ComponentProvider} that generated this ActionContext - * @return + * Returns the {@link ComponentProvider} that generated this ActionContext + * @return the provider */ public ComponentProvider getComponentProvider() { return provider; diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/support/GTreeNodeTransferable.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/support/GTreeNodeTransferable.java index db434c3374..7a517077b1 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/support/GTreeNodeTransferable.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/support/GTreeNodeTransferable.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,69 +18,75 @@ package docking.widgets.tree.support; import java.awt.datatransfer.*; import java.io.IOException; import java.util.List; +import java.util.Objects; import docking.widgets.tree.GTreeNode; /** - * A transferable for sharing data via drag/drop and clipboard operations for GTrees. + * A transferable for sharing data via drag/drop and clipboard operations for GTrees */ public class GTreeNodeTransferable implements Transferable { - private final List selectedData; - private final GTreeTransferHandler transferHandler; + private final List selectedData; + private final GTreeTransferHandler transferHandler; - /** - * Creates this transferable based upon the selected data and uses the given transfer - * handler to perform {@link Transferable} operations. - * @param handler the handler used to perform transfer operations. - * @param selectedData The - */ - public GTreeNodeTransferable( GTreeTransferHandler handler, List selectedData) { - this.selectedData = selectedData; - this.transferHandler = handler; - } - - /** - * Returns all of the original selected data contained by this transferable. - * @return all of the original selected data contained by this transferable - */ - public List getAllData() { - return selectedData; - } - - /** - * Gets the transfer data from the selection based upon the given flavor. - * @param transferNodes The nodes from which to get the data. - * @param flavor The flavor of data to retreive from the given selection. - * @return the transfer data from the selection based upon the given flavor. - * @throws UnsupportedFlavorException if the given flavor is not one of the supported flavors - * returned by {@link #getSupportedDataFlavors(List)}. - */ - public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { - return transferHandler.getTransferData(selectedData, flavor); - } - - /** - * Returns the DataFlavors for the types of data that this transferable supports, based upon - * the given selection. - * @param transferNodes The nodes to base the DataFlavor selection upon. - * @return the DataFlavors for the types of data that this transferable supports, based upon - * the given selection. + /** + * Creates this transferable based upon the selected data and uses the given transfer + * handler to perform {@link Transferable} operations + * + * @param handler the handler used to perform transfer operations + * @param selectedData The selected tree nodes */ - public DataFlavor[] getTransferDataFlavors() { - return transferHandler.getSupportedDataFlavors(selectedData); - } + public GTreeNodeTransferable(GTreeTransferHandler handler, List selectedData) { + this.transferHandler = Objects.requireNonNull(handler); + this.selectedData = Objects.requireNonNull(selectedData); + } - /** - * A convenience method to determine if this transferable supports the given flavor. - * @return true if this transferable supports the given flavor. - */ - public boolean isDataFlavorSupported(DataFlavor flavor) { - DataFlavor[] flavors = transferHandler.getSupportedDataFlavors(selectedData); - for(int i=0;i getAllData() { + return selectedData; + } + + /** + * Gets the transfer data from the selection based upon the given flavor + + * @param flavor The flavor of data to retrieve from the given selection. + * @return the transfer data from the selection based upon the given flavor. + * @throws UnsupportedFlavorException if the given flavor is not one of the supported flavors + * returned by {@link #getTransferDataFlavors()} + */ + @Override + public Object getTransferData(DataFlavor flavor) + throws UnsupportedFlavorException, IOException { + return transferHandler.getTransferData(selectedData, flavor); + } + + /** + * Returns the DataFlavors for the types of data that this transferable supports, based upon + * the given selection + * + * @return the DataFlavors for the types of data that this transferable supports, based upon + * the given selection + */ + @Override + public DataFlavor[] getTransferDataFlavors() { + return transferHandler.getSupportedDataFlavors(selectedData); + } + + /** + * A convenience method to determine if this transferable supports the given flavor + * @return true if this transferable supports the given flavor + */ + @Override + public boolean isDataFlavorSupported(DataFlavor flavor) { + DataFlavor[] flavors = transferHandler.getSupportedDataFlavors(selectedData); + for (DataFlavor f : flavors) { + if (f.equals(flavor)) { + return true; + } + } + return false; + } } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataActionContext.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataActionContext.java index 179325b06a..c2acecdda6 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataActionContext.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataActionContext.java @@ -30,6 +30,7 @@ public class ProjectDataActionContext extends ActionContext implements DomainFil private Component comp; private boolean isActiveProject; private ProjectData projectData; + private boolean isTransient; public ProjectDataActionContext(ComponentProvider provider, ProjectData projectData, Object contextObject, List selectedFolders, @@ -112,4 +113,20 @@ public class ProjectDataActionContext extends ActionContext implements DomainFil } return false; } + + /** + * Transient data is that which will appear in a temporary project dialog + * @param isTransient true if transient + */ + public void setTransient(boolean isTransient) { + this.isTransient = isTransient; + } + + /** + * Transient data is that which will appear in a temporary project dialog + * @return true if transient + */ + public boolean isTransient() { + return isTransient; + } } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataContextAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataContextAction.java index 5e9daa17eb..dd853ebb3a 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataContextAction.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataContextAction.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,20 +25,42 @@ public abstract class ProjectDataContextAction extends DockingAction { } @Override - public final boolean isEnabledForContext(ActionContext actionContext) { + public boolean isEnabledForContext(ActionContext actionContext) { if (!(actionContext instanceof ProjectDataActionContext)) { return false; } + ProjectDataActionContext context = (ProjectDataActionContext) actionContext; + if (ignoreTransientProject(context)) { + return false; + } + return isEnabledForContext(context); } + protected boolean ignoreTransientProject(ProjectDataActionContext context) { + if (supportsTransientProjectData()) { + return false; + } + return context.isTransient(); + } + + /** + * Signals that this action can work on normal project data, as well as transient data. + * Transient data is that which will appear in a temporary project dialog. + * + * @return true if this action works on transient project data + */ + protected boolean supportsTransientProjectData() { + return false; + } + protected boolean isEnabledForContext(ProjectDataActionContext context) { return context.hasOneOrMoreFilesAndFolders(); } @Override - public final void actionPerformed(ActionContext context) { + public void actionPerformed(ActionContext context) { actionPerformed((ProjectDataActionContext) context); } @@ -59,7 +80,7 @@ public abstract class ProjectDataContextAction extends DockingAction { @Override public boolean isAddToPopup(ActionContext context) { - if (!(context instanceof ProjectDataActionContext)) { + if (!isEnabledForContext(context)) { return false; } return isAddToPopup((ProjectDataActionContext) context); diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataContextToggleAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataContextToggleAction.java index d1fcb555f5..2b9dc7b39c 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataContextToggleAction.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataContextToggleAction.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,10 +29,32 @@ public abstract class ProjectDataContextToggleAction extends ToggleDockingAction if (!(actionContext instanceof ProjectDataActionContext)) { return false; } + ProjectDataActionContext context = (ProjectDataActionContext) actionContext; + if (ignoreTransientProject(context)) { + return false; + } + return isEnabledForContext(context); } + protected boolean ignoreTransientProject(ProjectDataActionContext context) { + if (supportsTransientProjectData()) { + return false; + } + return context.isTransient(); + } + + /** + * Signals that this action can work on normal project data, as well as transient data. + * Transient data is that which will appear in a temporary project dialog. + * + * @return true if this action works on transient project data + */ + protected boolean supportsTransientProjectData() { + return false; + } + protected boolean isEnabledForContext(ProjectDataActionContext context) { return context.hasOneOrMoreFilesAndFolders(); } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataTreeContextAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataTreeContextAction.java index 137b73986f..7df40012df 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataTreeContextAction.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataTreeContextAction.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,9 +15,9 @@ */ package ghidra.framework.main.datatable; -import ghidra.framework.main.datatree.ProjectDataTreeActionContext; import docking.ActionContext; import docking.action.DockingAction; +import ghidra.framework.main.datatree.ProjectDataTreeActionContext; public abstract class ProjectDataTreeContextAction extends DockingAction { @@ -31,10 +30,32 @@ public abstract class ProjectDataTreeContextAction extends DockingAction { if (!(actionContext instanceof ProjectDataTreeActionContext)) { return false; } + ProjectDataTreeActionContext context = (ProjectDataTreeActionContext) actionContext; + if (ignoreTransientProject(context)) { + return false; + } + return isEnabledForContext(context); } + protected boolean ignoreTransientProject(ProjectDataActionContext context) { + if (supportsTransientProjectData()) { + return false; + } + return context.isTransient(); + } + + /** + * Signals that this action can work on normal project data, as well as transient data. + * Transient data is that which will appear in a temporary project dialog. + * + * @return true if this action works on transient project data + */ + protected boolean supportsTransientProjectData() { + return false; + } + protected boolean isEnabledForContext(ProjectDataTreeActionContext context) { return context.hasOneOrMoreFilesAndFolders(); } @@ -60,7 +81,7 @@ public abstract class ProjectDataTreeContextAction extends DockingAction { @Override public boolean isAddToPopup(ActionContext context) { - if (!(context instanceof ProjectDataTreeActionContext)) { + if (!isEnabledForContext(context)) { return false; } return isAddToPopup((ProjectDataTreeActionContext) context); diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeClipboardUtils.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeClipboardUtils.java index 40cdb3a720..f522152a2a 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeClipboardUtils.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeClipboardUtils.java @@ -23,6 +23,7 @@ import javax.swing.tree.TreePath; import docking.dnd.GClipboard; import docking.widgets.tree.GTreeNode; +import docking.widgets.tree.support.GTreeNodeTransferable; import ghidra.util.Msg; /** @@ -35,14 +36,8 @@ public class DataTreeClipboardUtils { * Static instance of a callback handler that is notified when the clipboard is changed * and our data is discarded. */ - private static final ClipboardOwner DATATREE_CLIPBOARD_OWNER = new ClipboardOwner() { - @Override - public void lostOwnership(Clipboard clipboard, Transferable contents) { - // This is called when something other than this class modifies the clipboard - // and our data is discarded. - clearCuttables(contents); - } - }; + private static final ClipboardOwner DATATREE_CLIPBOARD_OWNER = + (clipboard, contents) -> clearCuttables(contents); /** * Pushes the GTreeNodes in the specified TreePath array to the clipboard. @@ -59,8 +54,9 @@ public class DataTreeClipboardUtils { GTreeNode node = (GTreeNode) element.getLastPathComponent(); list.add(node); } - DataTreeNodeTransferable contents = - new DataTreeNodeTransferable(tree.getDragNDropHandler(), list); + + GTreeNodeTransferable contents = + new GTreeNodeTransferable(tree.getDragNDropHandler(), list); try { clipboard.setContents(contents, DATATREE_CLIPBOARD_OWNER); diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeNodeTransferable.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeNodeTransferable.java deleted file mode 100644 index 793a178278..0000000000 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/DataTreeNodeTransferable.java +++ /dev/null @@ -1,30 +0,0 @@ -/* ### - * IP: GHIDRA - * REVIEWED: YES - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.framework.main.datatree; - -import java.util.List; - -import docking.widgets.tree.GTreeNode; -import docking.widgets.tree.support.GTreeNodeTransferable; -import docking.widgets.tree.support.GTreeTransferHandler; - -public class DataTreeNodeTransferable extends GTreeNodeTransferable { - public DataTreeNodeTransferable(GTreeTransferHandler handler, List selectedData) { - super(handler, selectedData); - } - -} diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/ProjectDataTreeActionContext.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/ProjectDataTreeActionContext.java index 63eba46ece..cffbbc0d28 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/ProjectDataTreeActionContext.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/ProjectDataTreeActionContext.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,14 +15,13 @@ */ package ghidra.framework.main.datatree; -import ghidra.framework.main.datatable.ProjectDataActionContext; -import ghidra.framework.model.*; - import java.util.List; import javax.swing.tree.TreePath; import docking.ComponentProvider; +import ghidra.framework.main.datatable.ProjectDataActionContext; +import ghidra.framework.model.*; public class ProjectDataTreeActionContext extends ProjectDataActionContext { @@ -52,7 +50,7 @@ public class ProjectDataTreeActionContext extends ProjectDataActionContext { return selectionPaths; } - public DataTree getDataTree() { + public DataTree getTree() { return tree; } } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/ProjectDataTreePanel.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/ProjectDataTreePanel.java index 4070ac82c0..a3514f5748 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/ProjectDataTreePanel.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/ProjectDataTreePanel.java @@ -337,8 +337,11 @@ public class ProjectDataTreePanel extends JPanel { } } - return new ProjectDataTreeActionContext(provider, projectData, selectionPaths, - domainFolderList, domainFileList, tree, isActiveProject); + ProjectDataTreeActionContext context = new ProjectDataTreeActionContext(provider, + projectData, selectionPaths, domainFolderList, domainFileList, tree, isActiveProject); + boolean isTransient = tool == null; // null for stand-alone dialog, not the project's tree + context.setTransient(isTransient); + return context; } public DataTree getDataTree() { diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataCollapseAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataCollapseAction.java index fdec297512..6e60a4ad5b 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataCollapseAction.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataCollapseAction.java @@ -33,7 +33,7 @@ public class ProjectDataCollapseAction extends ProjectDataTreeContextAction { @Override protected void actionPerformed(ProjectDataTreeActionContext context) { - DataTree tree = context.getDataTree(); + DataTree tree = context.getTree(); TreePath[] paths = context.getSelectionPaths(); collapse(tree, paths[0]); } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataCopyAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataCopyAction.java index 858fb08888..c1207ec325 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataCopyAction.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataCopyAction.java @@ -40,7 +40,7 @@ public class ProjectDataCopyAction extends ProjectDataCopyCutBaseAction { protected void actionPerformed(ProjectDataTreeActionContext context) { TreePath[] paths = adjustSelectionPaths(context.getSelectionPaths()); - DataTreeClipboardUtils.setClipboardContents(context.getDataTree(), paths); + DataTreeClipboardUtils.setClipboardContents(context.getTree(), paths); } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataCutAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataCutAction.java index 9341248252..ee80774d39 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataCutAction.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataCutAction.java @@ -40,7 +40,7 @@ public class ProjectDataCutAction extends ProjectDataCopyCutBaseAction { protected void actionPerformed(ProjectDataTreeActionContext context) { TreePath[] paths = adjustSelectionPaths(context.getSelectionPaths()); - DataTreeClipboardUtils.setClipboardContents(context.getDataTree(), paths); + DataTreeClipboardUtils.setClipboardContents(context.getTree(), paths); markNodesCut(paths); } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataExpandAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataExpandAction.java index 393457277e..576ce289c3 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataExpandAction.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataExpandAction.java @@ -33,7 +33,7 @@ public class ProjectDataExpandAction extends ProjectDataTreeContextAction { @Override protected void actionPerformed(ProjectDataTreeActionContext context) { - DataTree tree = context.getDataTree(); + DataTree tree = context.getTree(); TreePath[] paths = context.getSelectionPaths(); expand(tree, paths[0]); } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataNewFolderAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataNewFolderAction.java index 2e658cf93d..44d8dddf06 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataNewFolderAction.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataNewFolderAction.java @@ -41,6 +41,12 @@ public class ProjectDataNewFolderAction extends ProjectDataContextAction { markHelpUnnecessary(); } + @Override + protected boolean supportsTransientProjectData() { + // we allow the user to create new folders even in transient projects + return true; + } + @Override protected void actionPerformed(ProjectDataActionContext context) { createNewFolder(context); diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataPasteAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataPasteAction.java index 9bbaee00c5..5bf29f7245 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataPasteAction.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataPasteAction.java @@ -44,7 +44,7 @@ public class ProjectDataPasteAction extends ProjectDataCopyCutBaseAction { GTreeNode node = (GTreeNode) context.getContextObject(); DomainFolderNode destNode = getFolderForNode(node); - paste(context.getDataTree(), destNode); + paste(context.getTree(), destNode); } @Override diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataReadOnlyAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataReadOnlyAction.java index b7e8837547..4ca5086dcf 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataReadOnlyAction.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataReadOnlyAction.java @@ -50,6 +50,10 @@ public class ProjectDataReadOnlyAction extends ProjectDataContextToggleAction { if (context.getFolderCount() != 0 || context.getFileCount() != 1) { return false; } + if (ignoreTransientProject(context)) { + return false; + } + DomainFile domainFile = context.getSelectedFiles().get(0); setSelected(domainFile.isReadOnly()); return true; diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataSelectAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataSelectAction.java index f584babf9d..f3fa36668e 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataSelectAction.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/ProjectDataSelectAction.java @@ -36,7 +36,7 @@ public class ProjectDataSelectAction extends ProjectDataTreeContextAction { @Override protected void actionPerformed(ProjectDataTreeActionContext context) { - DataTree tree = context.getDataTree(); + DataTree tree = context.getTree(); TreePath[] paths = context.getSelectionPaths(); GTreeNode node = (GTreeNode) paths[0].getLastPathComponent(); selectAllChildren(tree, node);