diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesProvider.java index 89735ad4bf..3b5b709449 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesProvider.java @@ -15,6 +15,8 @@ */ package ghidra.app.plugin.core.debug.gui.modules; +import static ghidra.framework.main.DataTreeDialogType.*; + import java.awt.event.MouseEvent; import java.io.File; import java.lang.invoke.MethodHandles; @@ -1190,7 +1192,7 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter { DomainFileFilter filter = df -> Program.class.isAssignableFrom(df.getDomainObjectClass()); - return new DataTreeDialog(null, "Map Module to Program", DataTreeDialog.OPEN, filter); + return new DataTreeDialog(null, "Map Module to Program", OPEN, filter); } public DomainFile askProgram(Program program) { diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/tracemgr/DebuggerTraceManagerServicePlugin.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/tracemgr/DebuggerTraceManagerServicePlugin.java index 6d02f696c3..95c2ebefcc 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/tracemgr/DebuggerTraceManagerServicePlugin.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/tracemgr/DebuggerTraceManagerServicePlugin.java @@ -15,6 +15,8 @@ */ package ghidra.app.plugin.core.debug.service.tracemgr; +import static ghidra.framework.main.DataTreeDialogType.*; + import java.io.IOException; import java.lang.invoke.MethodHandles; import java.net.ConnectException; @@ -430,7 +432,7 @@ public class DebuggerTraceManagerServicePlugin extends Plugin } }; - return new DataTreeDialog(null, OpenTraceAction.NAME, DataTreeDialog.OPEN, filter); + return new DataTreeDialog(null, OpenTraceAction.NAME, OPEN, filter); } public DomainFile askTrace(Trace trace) { diff --git a/Ghidra/Extensions/MachineLearning/src/main/java/ghidra/machinelearning/functionfinding/FunctionStartRFParamsDialog.java b/Ghidra/Extensions/MachineLearning/src/main/java/ghidra/machinelearning/functionfinding/FunctionStartRFParamsDialog.java index 88dc479bed..683e4575b0 100644 --- a/Ghidra/Extensions/MachineLearning/src/main/java/ghidra/machinelearning/functionfinding/FunctionStartRFParamsDialog.java +++ b/Ghidra/Extensions/MachineLearning/src/main/java/ghidra/machinelearning/functionfinding/FunctionStartRFParamsDialog.java @@ -15,6 +15,8 @@ */ package ghidra.machinelearning.functionfinding; +import static ghidra.framework.main.DataTreeDialogType.*; + import java.awt.BorderLayout; import java.util.*; import java.util.stream.Collectors; @@ -483,10 +485,11 @@ public class FunctionStartRFParamsDialog extends ReusableDialogComponentProvider } private void searchOtherProgram(RandomForestRowObject modelRow) { - DataTreeDialog dtd = new DataTreeDialog(null, "Select Program", DataTreeDialog.OPEN, f -> { - Class c = f.getDomainObjectClass(); - return Program.class.isAssignableFrom(c); - }); + DataTreeDialog dtd = + new DataTreeDialog(null, "Select Program", OPEN, f -> { + Class c = f.getDomainObjectClass(); + return Program.class.isAssignableFrom(c); + }); dtd.show(); DomainFile dFile = dtd.getDomainFile(); if (dFile == null) { diff --git a/Ghidra/Features/Base/developer_scripts/FixLangId.java b/Ghidra/Features/Base/developer_scripts/FixLangId.java index 8d5187f114..52910947cd 100644 --- a/Ghidra/Features/Base/developer_scripts/FixLangId.java +++ b/Ghidra/Features/Base/developer_scripts/FixLangId.java @@ -13,6 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import static ghidra.framework.main.DataTreeDialogType.*; + import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -137,7 +139,7 @@ public class FixLangId extends GhidraScript { public DomainFile askProgramFile(String title) { final DomainFile[] domainFile = new DomainFile[] { null }; - final DataTreeDialog dtd = new DataTreeDialog(null, title, DataTreeDialog.OPEN); + final DataTreeDialog dtd = new DataTreeDialog(null, title, OPEN); dtd.addOkActionListener(e -> { dtd.close(); domainFile[0] = dtd.getDomainFile(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ProjectPathChooserEditor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ProjectPathChooserEditor.java index e836156bc7..d8d28140e4 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ProjectPathChooserEditor.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ProjectPathChooserEditor.java @@ -15,6 +15,8 @@ */ package ghidra.app.plugin.core.analysis; +import static ghidra.framework.main.DataTreeDialogType.*; + import java.awt.Component; import java.awt.event.MouseListener; import java.beans.PropertyEditorSupport; @@ -126,7 +128,7 @@ public class ProjectPathChooserEditor extends PropertyEditorSupport { private void displayFileChooser() { AtomicReference result = new AtomicReference<>(); DataTreeDialog dataTreeDialog = - new DataTreeDialog(this, title, DataTreeDialog.OPEN, filter); + new DataTreeDialog(this, title, OPEN, filter); dataTreeDialog.addOkActionListener(e -> { dataTreeDialog.close(); DomainFile df = dataTreeDialog.getDomainFile(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/DataTypeManagerHandler.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/DataTypeManagerHandler.java index 2306fb02f6..df310c70c9 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/DataTypeManagerHandler.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/archive/DataTypeManagerHandler.java @@ -15,6 +15,8 @@ */ package ghidra.app.plugin.core.datamgr.archive; +import static ghidra.framework.main.DataTreeDialogType.*; + import java.awt.Component; import java.awt.event.ActionListener; import java.io.*; @@ -31,6 +33,7 @@ import ghidra.app.plugin.core.datamgr.util.DataTypeArchiveUtility; import ghidra.app.util.HelpTopics; import ghidra.framework.client.*; import ghidra.framework.main.DataTreeDialog; +import ghidra.framework.main.DataTreeDialogType; import ghidra.framework.model.*; import ghidra.framework.options.SaveState; import ghidra.framework.plugintool.PluginTool; @@ -1410,7 +1413,7 @@ public class DataTypeManagerHandler { private DataTreeDialog getSaveDialog() { DataTreeDialog dialog = - new DataTreeDialog(null, "Save As", DataTreeDialog.SAVE, createArchiveFileFilter); + new DataTreeDialog(null, "Save As", SAVE, createArchiveFileFilter); ActionListener listener = event -> { DomainFolder folder = dialog.getDomainFolder(); @@ -1442,7 +1445,7 @@ public class DataTypeManagerHandler { private CreateDataTypeArchiveDataTreeDialog getCreateDialog() { CreateDataTypeArchiveDataTreeDialog dialog = new CreateDataTypeArchiveDataTreeDialog(null, - "Create", DataTreeDialog.CREATE, createArchiveFileFilter); + "Create", CREATE, createArchiveFileFilter); ActionListener listener = event -> { DomainFolder folder = dialog.getDomainFolder(); @@ -1498,7 +1501,7 @@ public class DataTypeManagerHandler { private DataTypeArchiveDB dataTypeArchiveDB; - CreateDataTypeArchiveDataTreeDialog(Component parent, String title, int type, + CreateDataTypeArchiveDataTreeDialog(Component parent, String title, DataTreeDialogType type, DomainFileFilter filter) { super(parent, title, type, filter); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/gotoquery/GoToHelper.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/gotoquery/GoToHelper.java index e5a54beb51..03cea1d682 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/gotoquery/GoToHelper.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/gotoquery/GoToHelper.java @@ -15,6 +15,8 @@ */ package ghidra.app.plugin.core.gotoquery; +import static ghidra.framework.main.DataTreeDialogType.*; + import java.util.Stack; import org.apache.commons.lang3.StringUtils; @@ -437,7 +439,7 @@ public class GoToHelper { } DataTreeDialog dialog = new DataTreeDialog(null, - "Choose External Program (" + extProgName + ")", DataTreeDialog.OPEN); + "Choose External Program (" + extProgName + ")", OPEN); dialog.setSearchText(extProgName); dialog.setHelpLocation(new HelpLocation("ReferencesPlugin", "ChooseExternalProgram")); tool.showDialog(dialog); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramSaveManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramSaveManager.java index 393e932cec..e850c639da 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramSaveManager.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramSaveManager.java @@ -15,6 +15,8 @@ */ package ghidra.app.plugin.core.progmgr; +import static ghidra.framework.main.DataTreeDialogType.*; + import java.awt.event.ActionListener; import java.io.IOException; import java.rmi.ConnectException; @@ -442,7 +444,7 @@ class ProgramSaveManager { private DataTreeDialog getSaveDialog() { DataTreeDialog dialog = - new DataTreeDialog(null, "Save As", DataTreeDialog.SAVE, domainFileFilter); + new DataTreeDialog(null, "Save As", SAVE, domainFileFilter); ActionListener listener = event -> { DomainFolder folder = dialog.getDomainFolder(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/EditExternalReferencePanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/EditExternalReferencePanel.java index 3de2ac89bb..d035cdd865 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/EditExternalReferencePanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/EditExternalReferencePanel.java @@ -15,6 +15,8 @@ */ package ghidra.app.plugin.core.references; +import static ghidra.framework.main.DataTreeDialogType.*; + import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.event.*; @@ -186,7 +188,7 @@ class EditExternalReferencePanel extends EditReferencePanel { */ private void popupProgramChooser() { DataTreeDialog d = - new DataTreeDialog(this.getParent(), "Choose External Program", DataTreeDialog.OPEN); + new DataTreeDialog(this.getParent(), "Choose External Program", OPEN); final DataTreeDialog dialog = d; d.addOkActionListener(new ActionListener() { @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/ExternalReferencesProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/ExternalReferencesProvider.java index d73cd3fec2..bce0cc19d1 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/ExternalReferencesProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/ExternalReferencesProvider.java @@ -15,6 +15,8 @@ */ package ghidra.app.plugin.core.references; +import static ghidra.framework.main.DataTreeDialogType.*; + import java.awt.BorderLayout; import java.awt.event.MouseEvent; import java.util.*; @@ -236,7 +238,7 @@ public class ExternalReferencesProvider extends ComponentProviderAdapter { List selectedExternalNames = getSelectedExternalNames(); String externalName = selectedExternalNames.get(0); // must be exactly one for us to be enabled. DataTreeDialog dialog = new DataTreeDialog(mainPanel, - "Choose External Program (" + externalName + ")", DataTreeDialog.OPEN); + "Choose External Program (" + externalName + ")", OPEN); dialog.setSearchText(externalName); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symboltree/EditExternalLocationPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symboltree/EditExternalLocationPanel.java index 22ec6f7d04..1790bda493 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symboltree/EditExternalLocationPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symboltree/EditExternalLocationPanel.java @@ -15,6 +15,8 @@ */ package ghidra.app.plugin.core.symboltree; +import static ghidra.framework.main.DataTreeDialogType.*; + import java.awt.*; import java.awt.event.ItemListener; import java.util.Arrays; @@ -269,7 +271,7 @@ class EditExternalLocationPanel extends JPanel { */ private void popupProgramChooser() { DataTreeDialog d = - new DataTreeDialog(this.getParent(), "Choose External Program", DataTreeDialog.OPEN); + new DataTreeDialog(this.getParent(), "Choose External Program", OPEN); final DataTreeDialog dialog = d; d.addOkActionListener(e -> { DomainFile df = dialog.getDomainFile(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symboltree/actions/SetExternalProgramAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symboltree/actions/SetExternalProgramAction.java index 2b50d93c0d..a0d63e9d83 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symboltree/actions/SetExternalProgramAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symboltree/actions/SetExternalProgramAction.java @@ -15,6 +15,8 @@ */ package ghidra.app.plugin.core.symboltree.actions; +import static ghidra.framework.main.DataTreeDialogType.*; + import javax.swing.Icon; import javax.swing.SwingUtilities; import javax.swing.tree.TreePath; @@ -81,7 +83,7 @@ public class SetExternalProgramAction extends SymbolTreeContextAction { final String externalLibraryPath = externalManager.getExternalLibraryPath(externalName); final DataTreeDialog dialog = new DataTreeDialog(provider.getComponent(), - "Choose External Program (" + externalName + ")", DataTreeDialog.OPEN); + "Choose External Program (" + externalName + ")", OPEN); dialog.setSearchText(externalName); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScript.java b/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScript.java index 9787160e46..74693f399b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScript.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScript.java @@ -15,6 +15,8 @@ */ package ghidra.app.script; +import static ghidra.framework.main.DataTreeDialogType.*; + import java.awt.Color; import java.io.*; import java.rmi.ConnectException; @@ -2304,7 +2306,7 @@ public abstract class GhidraScript extends FlatProgramAPI { DomainFolder choice = doAsk(Program.class, title, "", existingValue, lastValue -> { - DataTreeDialog dtd = new DataTreeDialog(null, title, DataTreeDialog.CHOOSE_FOLDER); + DataTreeDialog dtd = new DataTreeDialog(null, title, CHOOSE_FOLDER); dtd.show(); if (dtd.wasCancelled()) { throw new CancelledException(); @@ -2834,7 +2836,7 @@ public abstract class GhidraScript extends FlatProgramAPI { if (!isRunningHeadless()) { choice = doAsk(Program.class, title, "", choice, lastValue -> { - DataTreeDialog dtd = new DataTreeDialog(null, title, DataTreeDialog.OPEN); + DataTreeDialog dtd = new DataTreeDialog(null, title, OPEN); dtd.show(); if (dtd.wasCancelled()) { return null; @@ -2939,7 +2941,7 @@ public abstract class GhidraScript extends FlatProgramAPI { String message = ""; DomainFile choice = doAsk(DomainFile.class, title, message, existingValue, lastValue -> { - DataTreeDialog dtd = new DataTreeDialog(null, title, DataTreeDialog.OPEN); + DataTreeDialog dtd = new DataTreeDialog(null, title, OPEN); dtd.show(); if (dtd.wasCancelled()) { throw new CancelledException(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/OptionsEditorPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/OptionsEditorPanel.java index d83f0de852..cb01d55978 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/OptionsEditorPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/OptionsEditorPanel.java @@ -15,6 +15,8 @@ */ package ghidra.app.util; +import static ghidra.framework.main.DataTreeDialogType.*; + import java.awt.*; import java.util.*; import java.util.List; @@ -276,7 +278,7 @@ public class OptionsEditorPanel extends JPanel { JButton button = new BrowseButton(); button.addActionListener(e -> { DataTreeDialog dataTreeDialog = - new DataTreeDialog(this, "Choose a project folder", DataTreeDialog.CHOOSE_FOLDER); + new DataTreeDialog(this, "Choose a project folder", CHOOSE_FOLDER); String folderPath = lastFolderPath.isBlank() ? "/" : lastFolderPath; dataTreeDialog.setSelectedFolder(project.getProjectData().getFolder(folderPath)); dataTreeDialog.showComponent(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/features/base/values/AbstractProjectBrowserPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/features/base/values/AbstractProjectBrowserPanel.java index 47e71fe92f..43b62dc072 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/features/base/values/AbstractProjectBrowserPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/features/base/values/AbstractProjectBrowserPanel.java @@ -22,6 +22,7 @@ import javax.swing.*; import docking.widgets.button.BrowseButton; import ghidra.framework.main.DataTreeDialog; +import ghidra.framework.main.DataTreeDialogType; import ghidra.framework.model.*; import ghidra.framework.store.FileSystem; @@ -33,10 +34,11 @@ abstract class AbstractProjectBrowserPanel extends JPanel { protected JTextField textField; private JButton browseButton; private DomainFolder startFolder; - private int type; + private DataTreeDialogType type; protected DomainFileFilter filter = null; - AbstractProjectBrowserPanel(int type, Project project, String name, String startPath) { + AbstractProjectBrowserPanel(DataTreeDialogType type, Project project, String name, + String startPath) { super(new BorderLayout()); this.type = type; this.project = Objects.requireNonNull(project); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/features/base/values/ProjectFileValue.java b/Ghidra/Features/Base/src/main/java/ghidra/features/base/values/ProjectFileValue.java index a928e4e8ea..2a36ba83d5 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/features/base/values/ProjectFileValue.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/features/base/values/ProjectFileValue.java @@ -15,6 +15,8 @@ */ package ghidra.features.base.values; +import static ghidra.framework.main.DataTreeDialogType.*; + import javax.swing.JComponent; import javax.swing.JTextField; @@ -168,7 +170,7 @@ public class ProjectFileValue extends AbstractValue { ProjectFileBrowserPanel(Project project, String name, String startPath, Class projectFileClass) { - super(DataTreeDialog.OPEN, project, name, startPath); + super(OPEN, project, name, startPath); filter = df -> projectFileClass.isAssignableFrom(df.getDomainObjectClass()); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/features/base/values/ProjectFolderValue.java b/Ghidra/Features/Base/src/main/java/ghidra/features/base/values/ProjectFolderValue.java index 1abb02ff64..ac9814c7cb 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/features/base/values/ProjectFolderValue.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/features/base/values/ProjectFolderValue.java @@ -15,6 +15,8 @@ */ package ghidra.features.base.values; +import static ghidra.framework.main.DataTreeDialogType.*; + import javax.swing.JComponent; import javax.swing.JTextField; @@ -123,7 +125,7 @@ public class ProjectFolderValue extends AbstractValue { class ProjectFolderBrowserPanel extends AbstractProjectBrowserPanel { ProjectFolderBrowserPanel(Project project, String name, String startPath) { - super(DataTreeDialog.CHOOSE_FOLDER, project, name, startPath); + super(CHOOSE_FOLDER, project, name, startPath); } void setDomainFolder(DomainFolder value) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/AbstractDataTreeDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/AbstractDataTreeDialog.java new file mode 100644 index 0000000000..cd20562578 --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/AbstractDataTreeDialog.java @@ -0,0 +1,602 @@ +/* ### + * 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.framework.main; + +import static ghidra.framework.main.DataTreeDialogType.*; + +import java.awt.*; +import java.awt.event.*; +import java.util.HashSet; +import java.util.Set; + +import javax.swing.*; +import javax.swing.border.TitledBorder; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; + +import docking.*; +import docking.event.mouse.GMouseListenerAdapter; +import docking.widgets.combobox.GComboBox; +import docking.widgets.label.GDLabel; +import docking.widgets.label.GLabel; +import docking.widgets.tree.support.GTreeSelectionEvent; +import docking.widgets.tree.support.GTreeSelectionListener; +import ghidra.framework.main.datatree.DialogProjectTreeContext; +import ghidra.framework.main.datatree.ProjectDataTreePanel; +import ghidra.framework.main.projectdata.actions.*; +import ghidra.framework.model.*; +import ghidra.util.Msg; +import ghidra.util.Swing; +import ghidra.util.exception.AssertException; +import ghidra.util.layout.PairLayout; + +/** + * Base dialog for choosing DomainFiles. Provides and manages the base data tree panel. Subclasses + * should call the buildDataTreePanel() when they are constructing their main panels. They should + * also call the initializeFocusedComponent() method so that default focus for the dialog is in + * the text field if it is enabled or otherwise the focus should be the tree. + */ +public abstract class AbstractDataTreeDialog extends DialogComponentProvider + implements GTreeSelectionListener, ActionListener { + + protected final static int WIDTH = 350; + protected final static int HEIGHT = 500; + + protected ProjectDataTreePanel treePanel; + + private JComboBox projectComboBox; // used for open data + private ProjectLocator[] projectLocators; + private DomainFileFilter filter; + private JTextField nameField; + private JLabel folderNameLabel; + private ActionListener okActionListener; + private DomainFolder domainFolder; + private DomainFile domainFile; + private DataTreeDialogType type; + private Component parent; + + private String searchString; + private boolean cancelled = false; + + private ProjectDataExpandAction expandAction; + private ProjectDataCollapseAction collapseAction; + private ProjectDataNewFolderAction newFolderAction; + + private Integer treeSelectionMode; + private final Project project; + + /** + * Construct a new DataTreeDialog for the given project. + * + * @param parent dialog's parent + * @param title title to use + * @param type specify OPEN, SAVE, CHOOSE_FOLDER, or CHOOSE_USER_FOLDER + * @param filter filter used to control what is displayed in the data tree + * @param project the project to browse + * @throws IllegalArgumentException if invalid type is specified + */ + protected AbstractDataTreeDialog(Component parent, String title, DataTreeDialogType type, + DomainFileFilter filter, Project project) { + super(title, true, true, true, false); + + this.project = project; + this.parent = parent; + this.type = type; + this.filter = filter; + + initializeButtons(); + rootPanel.setPreferredSize(new Dimension(WIDTH, HEIGHT)); + + createActions(); + } + + protected void initializeFocusedComponent() { + Component focusComponent = nameField; + if (!nameField.isEditable()) { + focusComponent = treePanel.getFilterField(); + } + setFocusComponent(focusComponent); + } + + public void setTreeSelectionMode(int mode) { + if (treePanel != null) { + treePanel.getTreeSelectionModel().setSelectionMode(mode); + } + treeSelectionMode = mode; + } + + private void initializeButtons() { + addOKButton(); + addCancelButton(); + + if (type == SAVE) { + okButton.setText("Save"); + okButton.setMnemonic('S'); + } + else if (type == CREATE) { + okButton.setText("Create"); + okButton.setMnemonic('C'); + } + setOkEnabled(false); + + } + + private void createActions() { + String owner = "DataTreeDialogActions"; + + String groupName = "Cut/copy/paste/new"; + newFolderAction = new DialogProjectDataNewFolderAction(owner, groupName); + + groupName = "Expand/Collapse"; + expandAction = new DialogProjectDataExpandAction(owner, groupName); + collapseAction = new DialogProjectDataCollapseAction(owner, groupName); + + addAction(newFolderAction); + addAction(expandAction); + addAction(collapseAction); + } + + /** + * Add action listener that is called when the OK button is hit. + * @param l listener to add + */ + public void addOkActionListener(ActionListener l) { + okActionListener = l; + } + + @Override + public ActionContext getActionContext(MouseEvent event) { + if (treePanel == null) { + // must have been closed; some kind of timing issue + return super.getActionContext(event); + } + return treePanel.getActionContext(null, event); + } + + public void show() { + DockingWindowManager.showDialog(parent, this); + } + + /** + * Shows this dialog. The preferred show method is {@link #show()}, as it is the preferred + * nomenclature. + */ + public void showComponent() { + show(); + } + + public String getNameText() { + return nameField.getText(); + } + + public void setNameText(String name) { + nameField.setText(name.trim()); + nameField.selectAll(); + } + + /** + * Sets a domain folder as the initially selected folder when the dialog is first shown. + * + * @param folder {@link DomainFolder} to select when showing the dialog + */ + public void setSelectedFolder(DomainFolder folder) { + if (folder != null) { + treePanel.selectDomainFolder(folder); + } + } + + /** + * Get the selected domain file. + * @return null if there was no domain file selected + */ + public DomainFile getDomainFile() { + + if (domainFile != null) { + return domainFile; + } + + if (cancelled) { + return null; + } + + if (treePanel != null) { + domainFile = treePanel.getSelectedDomainFile(); + } + return domainFile; + } + + /** + * Get the selected folder. + * @return null if there was no domain folder selected + */ + public DomainFolder getDomainFolder() { + if (cancelled) { + return null; + } + if (domainFolder == null) { + domainFolder = treePanel.getSelectedDomainFolder(); + } + return domainFolder; + } + + /** + * TreeSelectionListener method that is called whenever the value of the selection changes. + * @param e the event that characterizes the change. + */ + @Override + public void valueChanged(GTreeSelectionEvent e) { + clearStatusText(); + + if (type == CHOOSE_FOLDER) { + domainFolder = treePanel.getSelectedDomainFolder(); + if (domainFolder != null) { + DomainFolder folderParent = domainFolder.getParent(); + if (folderParent != null) { + folderNameLabel.setText(folderParent.getPathname()); + } + else { + folderNameLabel.setText(" "); + } + + nameField.setText(domainFolder.getName()); + } + else { + domainFile = treePanel.getSelectedDomainFile(); + if (domainFile != null) { + domainFolder = domainFile.getParent(); + DomainFolder grandParent = domainFolder.getParent(); + if (grandParent != null) { + folderNameLabel.setText(grandParent.getPathname()); + } + else { + folderNameLabel.setText(""); + } + + nameField.setText(domainFolder.getName()); + } + else { + domainFolder = project.getProjectData().getRootFolder(); + folderNameLabel.setText(domainFolder.getPathname()); + nameField.setText(domainFolder.getName()); + } + } + } + else { + domainFile = treePanel.getSelectedDomainFile(); + if (domainFile != null) { + folderNameLabel.setText(domainFile.getParent().getPathname()); + nameField.setText(domainFile.getName()); + domainFolder = domainFile.getParent(); + } + else { + domainFolder = treePanel.getSelectedDomainFolder(); + if (domainFolder == null) { + domainFolder = project.getProjectData().getRootFolder(); + } + + folderNameLabel.setText(domainFolder.getPathname()); + if (nameField.isEditable()) { + if (nameField.getText().length() > 0) { + nameField.selectAll(); + } + } + else { + nameField.setText(""); + } + } + } + + String text = nameField.getText(); + setOkEnabled((text != null) && !text.isEmpty()); + } + + @Override + public void actionPerformed(ActionEvent event) { + int index = projectComboBox.getSelectedIndex(); + if (index < 0) { + return; + } + + ProjectLocator projectLocator = projectLocators[index]; + ProjectData pd = project.getProjectData(projectLocator); + String projectName = projectLocator.getName(); + if (pd == null) { + Msg.showError(this, getComponent(), "Error Getting Project Data", + "Could not get project data for " + projectName); + } + else { + treePanel.setProjectData(projectName, pd); + } + } + + /** + * Select the root folder in the tree. + */ + public void selectRootDataFolder() { + Swing.runLater(() -> treePanel.selectRootDataFolder()); + } + + /** + * Select a folder in the tree. + * @param folder the folder to select + */ + public void selectFolder(DomainFolder folder) { + Swing.runLater(() -> treePanel.selectDomainFolder(folder)); + } + + /** + * Select the node that corresponds to the given domain file. + * @param file the file + */ + public void selectDomainFile(DomainFile file) { + Swing.runLater(() -> treePanel.selectDomainFile(file)); + } + + @Override + public void close() { + super.close(); + removeWorkPanel(); + if (treePanel != null) { + treePanel.dispose(); + } + treePanel = null; + } + + protected JPanel buildDataTreePanel() { + + JPanel panel = new JPanel(); + panel.setLayout(new BorderLayout()); + + JPanel namePanel = createNamePanel(); + + // data tree panel must be created before the combo box + JPanel dataTreePanel = createDataTreePanel(); + ProjectData pd = project.getProjectData(); + treePanel.setProjectData(project.getName(), pd); + treePanel.selectRootDataFolder(); + + if (type == OPEN) { + JPanel comboPanel = createComboBoxPanel(); + + panel.add(comboPanel, BorderLayout.NORTH); + populateProjectModel(); + } + + panel.add(dataTreePanel, BorderLayout.CENTER); + panel.add(namePanel, BorderLayout.SOUTH); + + // can't add tree listeners until everything is built + addTreeListeners(); + return panel; + } + + @Override + protected void okCallback() { + cancelled = false; + + if (okActionListener == null) { + close(); + return; + } + okActionListener.actionPerformed(new ActionEvent(okButton, 0, okButton.getActionCommand())); + } + + public boolean wasCancelled() { + return cancelled; + } + + @Override + protected void cancelCallback() { + cancelled = true; + close(); + } + + /** + * Create the data tree panel. + */ + private JPanel createDataTreePanel() { + + JPanel panel = new JPanel(); + panel.setLayout(new BorderLayout()); + ProjectData pd = project.getProjectData(); + + treePanel = new ProjectDataTreePanel(project.getName(), true, // is for the active project + null, filter); + if (treeSelectionMode != null) { + treePanel.getTreeSelectionModel().setSelectionMode(treeSelectionMode); + } + treePanel.setProjectData(project.getName(), pd); + treePanel.addTreeSelectionListener(this); + treePanel.setPreferredTreePanelSize(new Dimension(150, 150)); + + // don't put the filter in the dialog when the user can/must type a name, as it's confusing + boolean userChoosesName = (type == SAVE) || (type == CREATE); + treePanel.setTreeFilterEnabled(!userChoosesName); + + panel.add(treePanel, BorderLayout.CENTER); + return panel; + } + + protected void addTreeListeners() { + if (type == OPEN) { + + treePanel.addTreeMouseListener(new GMouseListenerAdapter() { + @Override + public void doubleClickTriggered(MouseEvent e) { + if (okButton.isEnabled()) { + okCallback(); + } + } + }); + } + } + + /** + * Create the combo box panel that shows list of project names that + * are currently open, including the active project. + */ + private JPanel createComboBoxPanel() { + + JPanel panel = new JPanel(); + panel.setLayout(new BorderLayout()); + panel.setBorder(new TitledBorder("Current Projects")); + projectComboBox = new GComboBox<>(); + DefaultComboBoxModel model = new DefaultComboBoxModel<>(); + projectComboBox.setModel(model); + model.addElement("defaultProject"); + panel.add(projectComboBox, BorderLayout.CENTER); + projectComboBox.addActionListener(this); + + return panel; + } + + private JPanel createNamePanel() { + + JPanel outerPanel = new JPanel(); + outerPanel.setLayout(new BorderLayout(5, 0)); + + nameField = new JTextField(12); + nameField.getDocument().addDocumentListener(new DocumentListener() { + + @Override + public void removeUpdate(DocumentEvent e) { + update(); + } + + private void update() { + String text = nameField.getText(); + + switch (type) { + case OPEN: + // handled by valueChanged() + break; + case SAVE: + if (text == null || text.isEmpty()) { + DomainFile file = treePanel.getSelectedDomainFile(); + okButton.setEnabled(file != null); + } + break; + case CREATE: + if (text == null || text.isEmpty()) { + DomainFile file = treePanel.getSelectedDomainFile(); + okButton.setEnabled(file != null); + } + break; + case CHOOSE_FOLDER: + // handled by valueChanged() + break; + default: + throw new AssertException("Must handle new type!: " + type); + } + + setOkEnabled((text != null) && !text.isEmpty()); + } + + @Override + public void insertUpdate(DocumentEvent e) { + update(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + update(); + } + }); + + boolean userChoosesName = (type == SAVE) || (type == CREATE); + nameField.setEditable(userChoosesName); + nameField.setEnabled(userChoosesName); + + JPanel namePanel = new JPanel(new PairLayout(2, 5, 100)); + + if (!userChoosesName) { + namePanel.setBorder(BorderFactory.createEmptyBorder(20, 5, 5, 5)); + } + namePanel.add(new GLabel("Folder Path:", SwingConstants.RIGHT)); + + folderNameLabel = new GDLabel(" "); + namePanel.add(folderNameLabel); + + namePanel.add( + new GLabel(type == CHOOSE_FOLDER ? "Folder Name:" : "Name:", SwingConstants.RIGHT)); + namePanel.add(nameField); + + outerPanel.add(namePanel, BorderLayout.CENTER); + + FieldKeyListener l = new FieldKeyListener(); + nameField.addKeyListener(l); + nameField.addActionListener(e -> okCallback()); + + return outerPanel; + } + + private void populateProjectModel() { + ProjectLocator[] views = project.getProjectViews(); + + projectLocators = new ProjectLocator[views.length + 1]; + // make the current project the first in the list + projectLocators[0] = project.getProjectLocator(); + for (int i = 0; i < views.length; i++) { + projectLocators[i + 1] = views[i]; + } + + // populate the combo box + DefaultComboBoxModel model = + (DefaultComboBoxModel) projectComboBox.getModel(); + model.removeAllElements(); + + Set map = new HashSet<>(); + for (ProjectLocator projectLocator : projectLocators) { + String name = projectLocator.getName(); + if (map.contains(name)) { + model.addElement(name + " (" + projectLocator.getLocation() + ")"); + } + else { + map.add(name); + model.addElement(name); + } + } + map = null; + } + + public void setSearchText(String s) { + if (searchString != null) { + treePanel.findAndSelect(s); + } + } + + protected static DomainFileFilter getDefaultFilter(DataTreeDialogType type) { + if (type == CHOOSE_FOLDER || type == OPEN) { + // return filter which forces folder selection and allow navigation into linked-folders + return new DomainFileFilter() { + + @Override + public boolean accept(DomainFile df) { + return true; // show all files (legacy behavior) + } + }; + } + return null; + } + + private class FieldKeyListener extends KeyAdapter { + @Override + public void keyPressed(KeyEvent e) { + clearStatusText(); + } + } + +} 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 45d1e23cb1..767dbdb916 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 @@ -15,85 +15,26 @@ */ package ghidra.framework.main; -import java.awt.*; -import java.awt.event.*; -import java.util.HashSet; -import java.util.Set; +import java.awt.Component; -import javax.swing.*; -import javax.swing.border.TitledBorder; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; - -import docking.*; -import docking.event.mouse.GMouseListenerAdapter; -import docking.widgets.combobox.GComboBox; -import docking.widgets.label.GDLabel; -import docking.widgets.label.GLabel; -import docking.widgets.tree.support.GTreeSelectionEvent; -import docking.widgets.tree.support.GTreeSelectionListener; -import ghidra.framework.main.datatree.DialogProjectTreeContext; -import ghidra.framework.main.datatree.ProjectDataTreePanel; -import ghidra.framework.main.projectdata.actions.*; -import ghidra.framework.model.*; -import ghidra.util.Msg; -import ghidra.util.Swing; -import ghidra.util.exception.AssertException; -import ghidra.util.layout.PairLayout; +import ghidra.framework.model.DomainFileFilter; +import ghidra.framework.model.Project; /** * Dialog to open or save domain data items to a new location or name. */ -public class DataTreeDialog extends DialogComponentProvider - implements GTreeSelectionListener, ActionListener { +public class DataTreeDialog extends AbstractDataTreeDialog { - /** - * Dialog type for opening domain data files. - */ - public final static int OPEN = 0; - /** - * Dialog type for saving domain data files. - */ - public final static int SAVE = 1; - /** - * Dialog type for choosing a user folder. - */ - public final static int CHOOSE_FOLDER = 2; - /** - * Dialog type for creating domain data files. - */ - public final static int CREATE = 3; - - protected final static int WIDTH = 350; - protected final static int HEIGHT = 500; - - protected ProjectDataTreePanel treePanel; - - private JComboBox projectComboBox; // used for open data - private ProjectLocator[] projectLocators; - private DomainFileFilter filter; - private JTextField nameField; - private JLabel folderNameLabel; - private ActionListener okActionListener; - private DomainFolder domainFolder; - private DomainFile domainFile; - private int type; - private Component parent; - - private String searchString; - private boolean cancelled = false; - - private ProjectDataExpandAction expandAction; - private ProjectDataCollapseAction collapseAction; - private ProjectDataNewFolderAction newFolderAction; - - private Integer treeSelectionMode; - private final Project project; + // These are here for backwards compatibility with legacy code + public final static DataTreeDialogType OPEN = DataTreeDialogType.OPEN; + public final static DataTreeDialogType SAVE = DataTreeDialogType.SAVE; + public final static DataTreeDialogType CHOOSE_FOLDER = DataTreeDialogType.CHOOSE_FOLDER; + public final static DataTreeDialogType CREATE = DataTreeDialogType.CREATE; /** * Construct a new DataTreeDialog for the active project. This chooser will show all project - * files. Following linked-folders will only be allowed if a type of {@link #CHOOSE_FOLDER} - * or {@link #OPEN} is specified. If different behavior is required a filter should + * files. Following linked-folders will only be allowed if a type of CHOOSE_FOLDER + * or OPEN is specified. If different behavior is required a filter should * be specified using the other constructor. * * @param parent dialog's parent @@ -101,8 +42,8 @@ public class DataTreeDialog extends DialogComponentProvider * @param type specify OPEN, SAVE, CHOOSE_FOLDER, CHOOSE_USER_FOLDER, or CREATE * @throws IllegalArgumentException if invalid type is specified */ - public DataTreeDialog(Component parent, String title, int type) { - this(parent, title, type, getDefaultFilter(type), AppInfo.getActiveProject()); + public DataTreeDialog(Component parent, String title, DataTreeDialogType type) { + this(parent, title, type, getDefaultFilter(type)); } /** @@ -110,11 +51,12 @@ public class DataTreeDialog extends DialogComponentProvider * * @param parent dialog's parent * @param title title to use - * @param type specify OPEN, SAVE, CHOOSE_FOLDER, or CHOOSE_USER_FOLDER + * @param type specify OPEN, SAVE, CHOOSE_FOLDER, or CREATE * @param filter filter used to control what is displayed in the data tree * @throws IllegalArgumentException if invalid type is specified */ - public DataTreeDialog(Component parent, String title, int type, DomainFileFilter filter) { + public DataTreeDialog(Component parent, String title, DataTreeDialogType type, + DomainFileFilter filter) { this(parent, title, type, filter, AppInfo.getActiveProject()); } @@ -123,527 +65,17 @@ public class DataTreeDialog extends DialogComponentProvider * * @param parent dialog's parent * @param title title to use - * @param type specify OPEN, SAVE, CHOOSE_FOLDER, or CHOOSE_USER_FOLDER + * @param type specify OPEN, SAVE, CHOOSE_FOLDER, or CREATE * @param filter filter used to control what is displayed in the data tree * @param project the project to browse * @throws IllegalArgumentException if invalid type is specified */ - public DataTreeDialog(Component parent, String title, int type, DomainFileFilter filter, - Project project) { - super(title, true, true, true, false); - - if (type < 0 || type > CREATE) { - throw new IllegalArgumentException("Invalid type specified: " + type); - } - - this.project = project; - this.parent = parent; - this.type = type; - this.filter = filter; - - addWorkPanel(buildMainPanel()); - initializeButtons(); - rootPanel.setPreferredSize(new Dimension(WIDTH, HEIGHT)); + public DataTreeDialog(Component parent, String title, DataTreeDialogType type, + DomainFileFilter filter, Project project) { + super(parent, title, type, filter, project); + addWorkPanel(buildDataTreePanel()); initializeFocusedComponent(); - - createActions(); - } - - private void initializeFocusedComponent() { - Component focusComponent = nameField; - if (!nameField.isEditable()) { - focusComponent = treePanel.getFilterField(); - } - setFocusComponent(focusComponent); - } - - public void setTreeSelectionMode(int mode) { - if (treePanel != null) { - treePanel.getTreeSelectionModel().setSelectionMode(mode); - } - treeSelectionMode = mode; - } - - private void initializeButtons() { - addOKButton(); - addCancelButton(); - - if (type == SAVE) { - okButton.setText("Save"); - okButton.setMnemonic('S'); - } - else if (type == CREATE) { - okButton.setText("Create"); - okButton.setMnemonic('C'); - } - setOkEnabled(false); - - } - - private void createActions() { - String owner = "DataTreeDialogActions"; - - String groupName = "Cut/copy/paste/new"; - newFolderAction = new DialogProjectDataNewFolderAction(owner, groupName); - - groupName = "Expand/Collapse"; - expandAction = new DialogProjectDataExpandAction(owner, groupName); - collapseAction = new DialogProjectDataCollapseAction(owner, groupName); - - addAction(newFolderAction); - addAction(expandAction); - addAction(collapseAction); - } - - /** - * Add action listener that is called when the OK button is hit. - * @param l listener to add - */ - public void addOkActionListener(ActionListener l) { - okActionListener = l; - } - - @Override - public ActionContext getActionContext(MouseEvent event) { - if (treePanel == null) { - // must have been closed; some kind of timing issue - return super.getActionContext(event); - } - return treePanel.getActionContext(null, event); - } - - public void show() { - DockingWindowManager.showDialog(parent, this); - } - - /** - * Shows this dialog. The preferred show method is {@link #show()}, as it is the preferred - * nomenclature. - */ - public void showComponent() { - show(); - } - - public String getNameText() { - return nameField.getText(); - } - - public void setNameText(String name) { - nameField.setText(name.trim()); - nameField.selectAll(); - } - - /** - * Sets a domain folder as the initially selected folder when the dialog is first shown. - * - * @param folder {@link DomainFolder} to select when showing the dialog - */ - public void setSelectedFolder(DomainFolder folder) { - if (folder != null) { - treePanel.selectDomainFolder(folder); - } - } - - /** - * Get the selected domain file. - * @return null if there was no domain file selected - */ - public DomainFile getDomainFile() { - - if (domainFile != null) { - return domainFile; - } - - if (cancelled) { - return null; - } - - if (treePanel != null) { - domainFile = treePanel.getSelectedDomainFile(); - } - return domainFile; - } - - /** - * Get the selected folder. - * @return null if there was no domain folder selected - */ - public DomainFolder getDomainFolder() { - if (cancelled) { - return null; - } - if (domainFolder == null) { - domainFolder = treePanel.getSelectedDomainFolder(); - } - return domainFolder; - } - - /** - * TreeSelectionListener method that is called whenever the value of the selection changes. - * @param e the event that characterizes the change. - */ - @Override - public void valueChanged(GTreeSelectionEvent e) { - clearStatusText(); - - if (type == CHOOSE_FOLDER) { - domainFolder = treePanel.getSelectedDomainFolder(); - if (domainFolder != null) { - DomainFolder folderParent = domainFolder.getParent(); - if (folderParent != null) { - folderNameLabel.setText(folderParent.getPathname()); - } - else { - folderNameLabel.setText(" "); - } - - nameField.setText(domainFolder.getName()); - } - else { - domainFile = treePanel.getSelectedDomainFile(); - if (domainFile != null) { - domainFolder = domainFile.getParent(); - DomainFolder grandParent = domainFolder.getParent(); - if (grandParent != null) { - folderNameLabel.setText(grandParent.getPathname()); - } - else { - folderNameLabel.setText(""); - } - - nameField.setText(domainFolder.getName()); - } - else { - domainFolder = project.getProjectData().getRootFolder(); - folderNameLabel.setText(domainFolder.getPathname()); - nameField.setText(domainFolder.getName()); - } - } - } - else { - domainFile = treePanel.getSelectedDomainFile(); - if (domainFile != null) { - folderNameLabel.setText(domainFile.getParent().getPathname()); - nameField.setText(domainFile.getName()); - domainFolder = domainFile.getParent(); - } - else { - domainFolder = treePanel.getSelectedDomainFolder(); - if (domainFolder == null) { - domainFolder = project.getProjectData().getRootFolder(); - } - - folderNameLabel.setText(domainFolder.getPathname()); - if (nameField.isEditable()) { - if (nameField.getText().length() > 0) { - nameField.selectAll(); - } - } - else { - nameField.setText(""); - } - } - } - - String text = nameField.getText(); - setOkEnabled((text != null) && !text.isEmpty()); - } - - @Override - public void actionPerformed(ActionEvent event) { - int index = projectComboBox.getSelectedIndex(); - if (index < 0) { - return; - } - - ProjectLocator projectLocator = projectLocators[index]; - ProjectData pd = project.getProjectData(projectLocator); - String projectName = projectLocator.getName(); - if (pd == null) { - Msg.showError(this, getComponent(), "Error Getting Project Data", - "Could not get project data for " + projectName); - } - else { - treePanel.setProjectData(projectName, pd); - } - } - - /** - * Select the root folder in the tree. - */ - public void selectRootDataFolder() { - Swing.runLater(() -> treePanel.selectRootDataFolder()); - } - - /** - * Select a folder in the tree. - * @param folder the folder to select - */ - public void selectFolder(DomainFolder folder) { - Swing.runLater(() -> treePanel.selectDomainFolder(folder)); - } - - /** - * Select the node that corresponds to the given domain file. - * @param file the file - */ - public void selectDomainFile(DomainFile file) { - Swing.runLater(() -> treePanel.selectDomainFile(file)); - } - - @Override - public void close() { - super.close(); - removeWorkPanel(); - if (treePanel != null) { - treePanel.dispose(); - } - treePanel = null; - } - - protected JPanel buildMainPanel() { - - JPanel panel = new JPanel(); - panel.setLayout(new BorderLayout()); - - JPanel namePanel = createNamePanel(); - - // data tree panel must be created before the combo box - JPanel dataTreePanel = createDataTreePanel(); - ProjectData pd = project.getProjectData(); - treePanel.setProjectData(project.getName(), pd); - treePanel.selectRootDataFolder(); - - if (type == OPEN) { - JPanel comboPanel = createComboBoxPanel(); - - panel.add(comboPanel, BorderLayout.NORTH); - populateProjectModel(); - } - - panel.add(dataTreePanel, BorderLayout.CENTER); - panel.add(namePanel, BorderLayout.SOUTH); - - // can't add tree listeners until everything is built - addTreeListeners(); - return panel; - } - - @Override - protected void okCallback() { - cancelled = false; - - if (okActionListener == null) { - close(); - return; - } - okActionListener.actionPerformed(new ActionEvent(okButton, 0, okButton.getActionCommand())); - } - - public boolean wasCancelled() { - return cancelled; - } - - @Override - protected void cancelCallback() { - cancelled = true; - close(); - } - - /** - * Create the data tree panel. - */ - private JPanel createDataTreePanel() { - - JPanel panel = new JPanel(); - panel.setLayout(new BorderLayout()); - ProjectData pd = project.getProjectData(); - - treePanel = new ProjectDataTreePanel(project.getName(), true, // is for the active project - null, filter); - if (treeSelectionMode != null) { - treePanel.getTreeSelectionModel().setSelectionMode(treeSelectionMode); - } - treePanel.setProjectData(project.getName(), pd); - treePanel.addTreeSelectionListener(this); - treePanel.setPreferredTreePanelSize(new Dimension(150, 150)); - - // don't put the filter in the dialog when the user can/must type a name, as it's confusing - boolean userChoosesName = (type == SAVE) || (type == CREATE); - treePanel.setTreeFilterEnabled(!userChoosesName); - - panel.add(treePanel, BorderLayout.CENTER); - return panel; - } - - protected void addTreeListeners() { - if (type == OPEN) { - - treePanel.addTreeMouseListener(new GMouseListenerAdapter() { - @Override - public void doubleClickTriggered(MouseEvent e) { - if (okButton.isEnabled()) { - okCallback(); - } - } - }); - } - } - - /** - * Create the combo box panel that shows list of project names that - * are currently open, including the active project. - */ - private JPanel createComboBoxPanel() { - - JPanel panel = new JPanel(); - panel.setLayout(new BorderLayout()); - panel.setBorder(new TitledBorder("Current Projects")); - projectComboBox = new GComboBox<>(); - DefaultComboBoxModel model = new DefaultComboBoxModel<>(); - projectComboBox.setModel(model); - model.addElement("defaultProject"); - panel.add(projectComboBox, BorderLayout.CENTER); - projectComboBox.addActionListener(this); - - return panel; - } - - private JPanel createNamePanel() { - - JPanel outerPanel = new JPanel(); - outerPanel.setLayout(new BorderLayout(5, 0)); - - nameField = new JTextField(12); - nameField.getDocument().addDocumentListener(new DocumentListener() { - - @Override - public void removeUpdate(DocumentEvent e) { - update(); - } - - private void update() { - String text = nameField.getText(); - - switch (type) { - case OPEN: - // handled by valueChanged() - break; - case SAVE: - if (text == null || text.isEmpty()) { - DomainFile file = treePanel.getSelectedDomainFile(); - okButton.setEnabled(file != null); - } - break; - case CREATE: - if (text == null || text.isEmpty()) { - DomainFile file = treePanel.getSelectedDomainFile(); - okButton.setEnabled(file != null); - } - break; - case CHOOSE_FOLDER: - // handled by valueChanged() - break; - default: - throw new AssertException("Must handle new type!: " + type); - } - - setOkEnabled((text != null) && !text.isEmpty()); - } - - @Override - public void insertUpdate(DocumentEvent e) { - update(); - } - - @Override - public void changedUpdate(DocumentEvent e) { - update(); - } - }); - - boolean userChoosesName = (type == SAVE) || (type == CREATE); - nameField.setEditable(userChoosesName); - nameField.setEnabled(userChoosesName); - - JPanel namePanel = new JPanel(new PairLayout(2, 5, 100)); - - if (!userChoosesName) { - namePanel.setBorder(BorderFactory.createEmptyBorder(20, 5, 5, 5)); - } - namePanel.add(new GLabel("Folder Path:", SwingConstants.RIGHT)); - - folderNameLabel = new GDLabel(" "); - namePanel.add(folderNameLabel); - - namePanel.add( - new GLabel(type == CHOOSE_FOLDER ? "Folder Name:" : "Name:", SwingConstants.RIGHT)); - namePanel.add(nameField); - - outerPanel.add(namePanel, BorderLayout.CENTER); - - FieldKeyListener l = new FieldKeyListener(); - nameField.addKeyListener(l); - nameField.addActionListener(e -> okCallback()); - - return outerPanel; - } - - private void populateProjectModel() { - ProjectLocator[] views = project.getProjectViews(); - - projectLocators = new ProjectLocator[views.length + 1]; - // make the current project the first in the list - projectLocators[0] = project.getProjectLocator(); - for (int i = 0; i < views.length; i++) { - projectLocators[i + 1] = views[i]; - } - - // populate the combo box - DefaultComboBoxModel model = - (DefaultComboBoxModel) projectComboBox.getModel(); - model.removeAllElements(); - - Set map = new HashSet<>(); - for (ProjectLocator projectLocator : projectLocators) { - String name = projectLocator.getName(); - if (map.contains(name)) { - model.addElement(name + " (" + projectLocator.getLocation() + ")"); - } - else { - map.add(name); - model.addElement(name); - } - } - map = null; - } - - public void setSearchText(String s) { - if (searchString != null) { - treePanel.findAndSelect(s); - } - } - - private static DomainFileFilter getDefaultFilter(int type) { - if (type == CHOOSE_FOLDER || type == OPEN) { - // return filter which forces folder selection and allow navigation into linked-folders - return new DomainFileFilter() { - - @Override - public boolean accept(DomainFile df) { - return true; // show all files (legacy behavior) - } - }; - } - return null; - } - - private class FieldKeyListener extends KeyAdapter { - @Override - public void keyPressed(KeyEvent e) { - clearStatusText(); - } } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/DataTreeDialogType.java b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/DataTreeDialogType.java new file mode 100644 index 0000000000..5b65031cdf --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/DataTreeDialogType.java @@ -0,0 +1,38 @@ +/* ### + * 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.framework.main; + +/** + * Types of ways to use a DataTreeDialog. + */ +public enum DataTreeDialogType { + /** + * Dialog type for opening domain data files + */ + OPEN, + /** + * Dialog type for saving domain data files + */ + SAVE, + /** + * Dialog type for choosing a user folder + */ + CHOOSE_FOLDER, + /** + * Dialog type for creating domain data files + */ + CREATE +} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/OpenVersionedFileDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/OpenVersionedFileDialog.java index 11481f8cb8..247965f391 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/OpenVersionedFileDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/OpenVersionedFileDialog.java @@ -15,10 +15,11 @@ */ package ghidra.framework.main; +import static ghidra.framework.main.DataTreeDialogType.*; + import java.awt.*; import java.awt.event.MouseEvent; import java.io.IOException; -import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -40,7 +41,7 @@ import ghidra.util.Msg; * opened. * @param domain object class */ -public class OpenVersionedFileDialog extends DataTreeDialog { +public class OpenVersionedFileDialog extends AbstractDataTreeDialog { private static final String SHOW_HISTORY_PREFERENCES_KEY = "OPEN_PROGRAM_DIALOG.SHOW_HISTORY"; private static final String HEIGHT_PREFERENCES_KEY = "OPEN_PROGRAM_DIALOG.HEIGHT"; private static final String WIDTH_NO_HISTORY_PREFERENCES_KEY = @@ -76,12 +77,30 @@ public class OpenVersionedFileDialog extends DataTreeDia * @param domainObjectClass allowed domain object class which corresponds to {@code } */ public OpenVersionedFileDialog(PluginTool tool, String title, Class domainObjectClass) { - super(tool.getToolFrame(), title, DataTreeDialog.OPEN, f -> { + this(tool, title, domainObjectClass, null); + } + + /** + * Constructor + * @param tool tool where the file is being opened. + * @param title title to use + * @param domainObjectClass allowed domain object class which corresponds to {@code } + * @param openDomainObjects if non-null, will cause an additional tab showing the given + * list of open domain objects that the user can select from + */ + public OpenVersionedFileDialog(PluginTool tool, String title, Class domainObjectClass, + List openDomainObjects) { + super(tool.getToolFrame(), title, OPEN, f -> { return domainObjectClass.isAssignableFrom(f.getDomainObjectClass()); - }); + }, AppInfo.getActiveProject()); this.tool = tool; this.domainObjectClass = domainObjectClass; + this.openDomainObjects = openDomainObjects; + + addWorkPanel(buildMainPanel()); + initializeFocusedComponent(); + updateOkTooltip(); checkIfHistoryWasOpen(); } @@ -95,20 +114,6 @@ public class OpenVersionedFileDialog extends DataTreeDia } } - /** - * Set an optional list of already open domain objects of type {@code } which may be - * selected instead of a project domain file. The {@link #getDomainObject(Object, boolean)} - * method should be used when this optional list has been set. If this dialog is reused - * the list should be set null if previously set. This method must be invoked prior to - * showing the dialog. - * @param openDomainObjects list of open domain objects from which a selection may be made. - */ - public void setOpenObjectChoices(List openDomainObjects) { - this.openDomainObjects = (openDomainObjects != null && !openDomainObjects.isEmpty()) - ? new ArrayList<>(openDomainObjects) - : null; - } - /** * Get the selected domain object for read-only or immutable use. * If an existing open object is selected its original mode applies but consumer will @@ -173,7 +178,6 @@ public class OpenVersionedFileDialog extends DataTreeDia return super.getDomainFolder(); } - @Override protected JPanel buildMainPanel() { historyButton = new JButton("History>>"); historyButton.addActionListener(e -> showHistoryPanel(!historyIsShowing)); @@ -181,7 +185,7 @@ public class OpenVersionedFileDialog extends DataTreeDia rootPanel.setPreferredSize(getPreferredSizeForHistoryState()); mainPanel = new JPanel(new BorderLayout()); - mainPanel.add(super.buildMainPanel(), BorderLayout.CENTER); + mainPanel.add(buildDataTreePanel(), BorderLayout.CENTER); JPanel historyButtonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); historyButtonPanel.add(historyButton); mainPanel.add(historyButtonPanel, BorderLayout.SOUTH); @@ -201,7 +205,7 @@ public class OpenVersionedFileDialog extends DataTreeDia openObjectsTable = null; tabbedPane = null; - if (openDomainObjects == null) { + if (openDomainObjects == null || openDomainObjects.isEmpty()) { return projectFilePanel; // return Project File selection panel only } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterDialog.java index 07fc5ba591..a6115a91ab 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterDialog.java @@ -15,6 +15,8 @@ */ package ghidra.plugin.importer; +import static ghidra.framework.main.DataTreeDialogType.*; + import java.awt.*; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; @@ -571,7 +573,7 @@ public class ImporterDialog extends DialogComponentProvider { private void chooseProjectFolder() { DataTreeDialog dataTreeDialog = new DataTreeDialog(getComponent(), - "Choose a project folder", DataTreeDialog.CHOOSE_FOLDER); + "Choose a project folder", CHOOSE_FOLDER); dataTreeDialog.setSelectedFolder(destinationFolder); dataTreeDialog.showComponent(); DomainFolder folder = dataTreeDialog.getDomainFolder(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/plugins/importer/batch/BatchProjectDestinationPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/plugins/importer/batch/BatchProjectDestinationPanel.java index 116a831788..3aae03fecb 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/plugins/importer/batch/BatchProjectDestinationPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/plugins/importer/batch/BatchProjectDestinationPanel.java @@ -21,8 +21,7 @@ import javax.swing.*; import docking.widgets.button.BrowseButton; import docking.widgets.label.GDLabel; -import ghidra.framework.main.AppInfo; -import ghidra.framework.main.DataTreeDialog; +import ghidra.framework.main.*; import ghidra.framework.model.*; class BatchProjectDestinationPanel extends JPanel { @@ -96,7 +95,7 @@ class BatchProjectDestinationPanel extends JPanel { private void browseFolders() { DataTreeDialog dataTreeDialog = - new DataTreeDialog(parent, "Choose a project folder", DataTreeDialog.CHOOSE_FOLDER); + new DataTreeDialog(parent, "Choose a project folder", DataTreeDialogType.CHOOSE_FOLDER); dataTreeDialog.addOkActionListener(e -> { dataTreeDialog.close(); setFolder(dataTreeDialog.getDomainFolder()); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/framework/main/DataTreeDialogTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/framework/main/DataTreeDialogTest.java index 19201b68cc..479110de79 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/framework/main/DataTreeDialogTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/framework/main/DataTreeDialogTest.java @@ -15,6 +15,7 @@ */ package ghidra.framework.main; +import static ghidra.framework.main.DataTreeDialogType.*; import static org.junit.Assert.*; import java.util.*; @@ -110,7 +111,7 @@ public class DataTreeDialogTest extends AbstractGhidraHeadedIntegrationTest { @Test public void testOKButtonDisabled_Type_SAVE() { // no initial selection--button disabled - show(DataTreeDialog.SAVE); + show(SAVE); assertOK(false); // select a file--enabled; name field populated @@ -141,7 +142,7 @@ public class DataTreeDialogTest extends AbstractGhidraHeadedIntegrationTest { @Test public void testOKButtonDisabled_Type_CREATE() { // no initial selection--button disabled - show(DataTreeDialog.CREATE); + show(CREATE); assertOK(false); // select a file--enabled; name field populated @@ -172,7 +173,7 @@ public class DataTreeDialogTest extends AbstractGhidraHeadedIntegrationTest { @Test public void testOKButtonAlwaysEnabled_Type_CHOOSE_FOLDER() { // no initial selection--button disabled - show(DataTreeDialog.CHOOSE_FOLDER); + show(CHOOSE_FOLDER); assertOK(true); // select a file--enabled; name field populated @@ -199,7 +200,7 @@ public class DataTreeDialogTest extends AbstractGhidraHeadedIntegrationTest { @Test public void testOKButtonDisabled_Type_OPEN() { // no initial selection--button disabled - show(DataTreeDialog.OPEN); + show(OPEN); assertOK(false); // select a file--enabled; name field populated @@ -224,7 +225,7 @@ public class DataTreeDialogTest extends AbstractGhidraHeadedIntegrationTest { @Test public void testOKButtonEnabledWithInitialSelection_Type_OPEN() { // initial selection--button enabled - show(DataTreeDialog.OPEN, "x07"); + show(OPEN, "x07"); assertOK(true); // select a file--enabled; name field populated @@ -250,7 +251,7 @@ public class DataTreeDialogTest extends AbstractGhidraHeadedIntegrationTest { public void testSelectFiles() throws Exception { List createdFiles = createBlankProgramsInProject( List.of("/dir1/dir2/file1", "/dir1/dir2a/dir3a/file2", "/file3")); - show(DataTreeDialog.OPEN); + show(OPEN); Set selectedProjectElements = new HashSet<>(); ProjectDataTreePanel projectDataTreePanel = getProjectDataTreePanel(); @@ -280,7 +281,7 @@ public class DataTreeDialogTest extends AbstractGhidraHeadedIntegrationTest { public void testSelectFolder() throws Exception { List createdFiles = createBlankProgramsInProject( List.of("/dir1/dir2/file1", "/dir1/dir2a/dir3a/file2", "/file3")); - show(DataTreeDialog.OPEN); + show(OPEN); Set selectedProjectElements = new HashSet<>(); ProjectDataTreePanel projectDataTreePanel = getProjectDataTreePanel(); @@ -398,7 +399,7 @@ public class DataTreeDialogTest extends AbstractGhidraHeadedIntegrationTest { waitForTree(gTree); } - private void show(final int type) { + private void show(DataTreeDialogType type) { SwingUtilities.invokeLater(() -> { dialog = new DataTreeDialog(frontEndTool.getToolFrame(), "Test Data Tree Dialog", type); @@ -408,7 +409,7 @@ public class DataTreeDialogTest extends AbstractGhidraHeadedIntegrationTest { assertNotNull(dialog); } - private void show(final int type, final String name) { + private void show(DataTreeDialogType type, final String name) { SwingUtilities.invokeLater(() -> { dialog = new DataTreeDialog(frontEndTool.getToolFrame(), "Test Data Tree Dialog", type); @@ -424,7 +425,7 @@ public class DataTreeDialogTest extends AbstractGhidraHeadedIntegrationTest { private void showFiltered(final String startsWith) { SwingUtilities.invokeLater(() -> { dialog = new DataTreeDialog(frontEndTool.getToolFrame(), "Test Data Tree Dialog", - DataTreeDialog.OPEN, f -> f.getName().startsWith(startsWith)); + OPEN, f -> f.getName().startsWith(startsWith)); dialog.showComponent(); }); waitForSwing(); diff --git a/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/plugin/PopulateFidDialog.java b/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/plugin/PopulateFidDialog.java index cd5489fc68..a515c0de17 100644 --- a/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/plugin/PopulateFidDialog.java +++ b/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/plugin/PopulateFidDialog.java @@ -15,6 +15,8 @@ */ package ghidra.feature.fid.plugin; +import static ghidra.framework.main.DataTreeDialogType.*; + import java.awt.BorderLayout; import java.awt.Component; import java.io.File; @@ -225,7 +227,7 @@ public class PopulateFidDialog extends DialogComponentProvider { JButton browseButton = new BrowseButton(); browseButton.addActionListener(e -> { final DataTreeDialog dialog = new DataTreeDialog(tool.getToolFrame(), - "Choose Root Folder", DataTreeDialog.CHOOSE_FOLDER); + "Choose Root Folder", CHOOSE_FOLDER); tool.showDialog(dialog); DomainFolder domainFolder = dialog.getDomainFolder(); if (domainFolder != null) { diff --git a/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/ProgramDiffPlugin.java b/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/ProgramDiffPlugin.java index 84a4e146ef..d3370e2d74 100644 --- a/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/ProgramDiffPlugin.java +++ b/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/ProgramDiffPlugin.java @@ -150,6 +150,8 @@ public class ProgramDiffPlugin extends ProgramPlugin DiffApplySettingsOptionManager applySettingsMgr; private boolean isHighlightCursorLine; private Program activeProgram; + + // this is used for test injection only. In actual use, the dialog is not reused private OpenVersionedFileDialog openVersionedFileDialog; /** @@ -1141,10 +1143,9 @@ public class ProgramDiffPlugin extends ProgramPlugin return; } - final OpenVersionedFileDialog dialog = getOpenVersionedFileDialog(); - List openProgramList = getOpenProgramList(); - dialog.setOpenObjectChoices(openProgramList.isEmpty() ? null : openProgramList); + + OpenVersionedFileDialog dialog = getOpenVersionedFileDialog(openProgramList); dialog.addOkActionListener(e -> { tool.clearStatusInfo(); @@ -1186,14 +1187,17 @@ public class ProgramDiffPlugin extends ProgramPlugin return (rc != OptionDialog.OPTION_ONE); } - private OpenVersionedFileDialog getOpenVersionedFileDialog() { + private OpenVersionedFileDialog getOpenVersionedFileDialog( + List openPrograms) { + // This will always be null except during testing. if (openVersionedFileDialog != null) { return openVersionedFileDialog; } OpenVersionedFileDialog dialog = - new OpenVersionedFileDialog<>(tool, "Select Other Program", Program.class); + new OpenVersionedFileDialog<>(tool, "Select Other Program", Program.class, + openPrograms); dialog.setTreeSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); dialog.setHelpLocation(new HelpLocation("Diff", "Open_Close_Program_View")); return dialog; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/OpenVersionTrackingSessionAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/OpenVersionTrackingSessionAction.java index 35922e9320..57bdb334b8 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/OpenVersionTrackingSessionAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/OpenVersionTrackingSessionAction.java @@ -15,6 +15,8 @@ */ package ghidra.feature.vt.gui.actions; +import static ghidra.framework.main.DataTreeDialogType.*; + import docking.ActionContext; import docking.action.DockingAction; import docking.action.MenuData; @@ -45,8 +47,8 @@ public class OpenVersionTrackingSessionAction extends DockingAction { public void actionPerformed(ActionContext context) { PluginTool tool = controller.getTool(); DataTreeDialog dialog = - new DataTreeDialog(tool.getToolFrame(), "Open Version Tracking Session", - DataTreeDialog.OPEN, new VTDomainFileFilter()); + new DataTreeDialog(tool.getToolFrame(), "Open Version Tracking Session", OPEN, + new VTDomainFileFilter()); tool.showDialog(dialog); if (!dialog.wasCancelled()) { @@ -56,6 +58,7 @@ public class OpenVersionTrackingSessionAction extends DockingAction { } class VTDomainFileFilter implements DomainFileFilter { + @Override public boolean accept(DomainFile f) { Class c = f.getDomainObjectClass(); return VTSession.class.isAssignableFrom(c); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/NewSessionPanel.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/NewSessionPanel.java index 844433617e..e4b0894a35 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/NewSessionPanel.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/NewSessionPanel.java @@ -15,6 +15,8 @@ */ package ghidra.feature.vt.gui.wizard; +import static ghidra.framework.main.DataTreeDialogType.*; + import java.awt.*; import java.util.*; @@ -236,7 +238,7 @@ public class NewSessionPanel extends AbstractMageJPanel { */ private void browseDataTreeFolders() { final DataTreeDialog dataTreeDialog = - new DataTreeDialog(this, "Choose a project folder", DataTreeDialog.CHOOSE_FOLDER); + new DataTreeDialog(this, "Choose a project folder", CHOOSE_FOLDER); dataTreeDialog.addOkActionListener(e -> { dataTreeDialog.close(); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/VTWizardUtils.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/VTWizardUtils.java index d462548dd8..b87ddeefef 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/VTWizardUtils.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/VTWizardUtils.java @@ -15,6 +15,8 @@ */ package ghidra.feature.vt.gui.wizard; +import static ghidra.framework.main.DataTreeDialogType.*; + import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -55,8 +57,8 @@ public class VTWizardUtils { static DomainFile chooseDomainFile(Component parent, String domainIdentifier, DomainFileFilter filter, DomainFile fileToSelect) { final DataTreeDialog dataTreeDialog = filter == null - ? new DataTreeDialog(parent, "Choose " + domainIdentifier, DataTreeDialog.OPEN) - : new DataTreeDialog(parent, "Choose " + domainIdentifier, DataTreeDialog.OPEN, + ? new DataTreeDialog(parent, "Choose " + domainIdentifier, OPEN) + : new DataTreeDialog(parent, "Choose " + domainIdentifier, OPEN, filter); final DomainFileBox box = new DomainFileBox(); dataTreeDialog.addOkActionListener(new ActionListener() { diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ReferencesPluginScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ReferencesPluginScreenShots.java index 9ac8628190..44401db883 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ReferencesPluginScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ReferencesPluginScreenShots.java @@ -15,6 +15,8 @@ */ package help.screenshot; +import static ghidra.framework.main.DataTreeDialogType.*; + import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; @@ -61,7 +63,7 @@ public class ReferencesPluginScreenShots extends GhidraScreenShotGenerator { runSwing(() -> { DataTreeDialog dialog = new DataTreeDialog(tool.getToolFrame(), - "Choose External Program (" + "Kernel32.dll" + ")", DataTreeDialog.OPEN); + "Choose External Program (" + "Kernel32.dll" + ")", OPEN); tool.showDialog(dialog); }, false); captureDialog();