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 4b20b4498d..89735ad4bf 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 @@ -1190,12 +1190,7 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter { DomainFileFilter filter = df -> Program.class.isAssignableFrom(df.getDomainObjectClass()); - // TODO regarding the hack note below, I believe it's fixed, but not sure how to test - return new DataTreeDialog(null, "Map Module to Program", DataTreeDialog.OPEN, filter) { - { // TODO/HACK: I get an NPE setting the default selection if I don't fake this. - dialogShown(); - } - }; + return new DataTreeDialog(null, "Map Module to Program", DataTreeDialog.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 762771d1ed..6d02f696c3 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 @@ -430,12 +430,7 @@ public class DebuggerTraceManagerServicePlugin extends Plugin } }; - // TODO regarding the hack note below, I believe this issue ahs been fixed, but not sure how to test - return new DataTreeDialog(null, OpenTraceAction.NAME, DataTreeDialog.OPEN, filter) { - { // TODO/HACK: Why the NPE if I don't do this? - dialogShown(); - } - }; + return new DataTreeDialog(null, OpenTraceAction.NAME, DataTreeDialog.OPEN, filter); } public DomainFile askTrace(Trace trace) { 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 2755f84f72..45d1e23cb1 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 @@ -81,10 +81,7 @@ public class DataTreeDialog extends DialogComponentProvider private Component parent; private String searchString; - private boolean comboModelInitialized; private boolean cancelled = false; - private String pendingNameText; - private DomainFolder pendingDomainFolder; private ProjectDataExpandAction expandAction; private ProjectDataCollapseAction collapseAction; @@ -134,23 +131,31 @@ public class DataTreeDialog extends DialogComponentProvider 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; - initDataTreeDialog(type, filter); + this.type = type; + this.filter = filter; + + addWorkPanel(buildMainPanel()); + initializeButtons(); + rootPanel.setPreferredSize(new Dimension(WIDTH, HEIGHT)); + + initializeFocusedComponent(); + + createActions(); } - 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) - } - }; + private void initializeFocusedComponent() { + Component focusComponent = nameField; + if (!nameField.isEditable()) { + focusComponent = treePanel.getFilterField(); } - return null; + setFocusComponent(focusComponent); } public void setTreeSelectionMode(int mode) { @@ -160,34 +165,20 @@ public class DataTreeDialog extends DialogComponentProvider treeSelectionMode = mode; } - private void initDataTreeDialog(int newType, DomainFileFilter newFilter) { - - if (newType < 0 || newType > CREATE) { - throw new IllegalArgumentException("Invalid type specified: " + newType); - } - this.type = newType; - this.filter = newFilter; - - okButton = new JButton("OK"); - okButton.setMnemonic('K'); - okButton.addActionListener(ev -> okCallback()); - addButton(okButton); + private void initializeButtons() { + addOKButton(); addCancelButton(); - if (newType == SAVE) { + if (type == SAVE) { okButton.setText("Save"); okButton.setMnemonic('S'); } - else if (newType == CREATE) { + else if (type == CREATE) { okButton.setText("Create"); okButton.setMnemonic('C'); } + setOkEnabled(false); - rootPanel.setPreferredSize(new Dimension(WIDTH, HEIGHT)); - - setFocusComponent(nameField); - - createActions(); } private void createActions() { @@ -223,7 +214,6 @@ public class DataTreeDialog extends DialogComponentProvider } public void show() { - doSetup(); DockingWindowManager.showDialog(parent, this); } @@ -235,79 +225,13 @@ public class DataTreeDialog extends DialogComponentProvider show(); } - @Override - protected void dialogShown() { - if (!comboModelInitialized) { - doSetup(); - } - } - - private void doSetup() { - addWorkPanel(buildMainPanel()); - - comboModelInitialized = true; - // repopulate the tree - ProjectData pd = project.getProjectData(); - treePanel.setProjectData(project.getName(), pd); - - String nameFieldText = pendingNameText == null ? "" : pendingNameText; - pendingNameText = null; - initializeSelectedFolder(); - - setFocusComponent(nameField); - if (type == OPEN) { - domainFolder = null; - nameField.setText(nameFieldText); - nameField.selectAll(); - populateProjectModel(); - - // the name field is disabled; use the filter field - setFocusComponent(treePanel.getFilterField()); - } - else if (type == SAVE) { - nameField.setText(nameFieldText); - nameField.selectAll(); - initializeSelectedFolder(); - } - else if (type == CREATE) { - nameField.setText(nameFieldText); - nameField.selectAll(); - initializeSelectedFolder(); - } - else { // CHOOSE_FOLDER - setFocusComponent(treePanel.getFilterField()); - } - - setOkEnabled(!nameFieldText.isEmpty()); - - if (searchString != null) { - findAndSelect(searchString); - } - - clearStatusText(); - } - - private void initializeSelectedFolder() { - if (pendingDomainFolder != null) { - // set the explicitly requested folder to be selected - treePanel.selectDomainFolder(pendingDomainFolder); - pendingDomainFolder = null; - } - else { - // default case--make sure we have a folder selected - domainFolder = treePanel.getSelectedDomainFolder(); - if (domainFolder == null) { - treePanel.selectRootDataFolder(); - } - } - } - public String getNameText() { return nameField.getText(); } public void setNameText(String name) { - pendingNameText = name; + nameField.setText(name.trim()); + nameField.selectAll(); } /** @@ -316,7 +240,9 @@ public class DataTreeDialog extends DialogComponentProvider * @param folder {@link DomainFolder} to select when showing the dialog */ public void setSelectedFolder(DomainFolder folder) { - pendingDomainFolder = folder; + if (folder != null) { + treePanel.selectDomainFolder(folder); + } } /** @@ -474,7 +400,6 @@ public class DataTreeDialog extends DialogComponentProvider treePanel.dispose(); } treePanel = null; - comboModelInitialized = false; } protected JPanel buildMainPanel() { @@ -482,19 +407,26 @@ public class DataTreeDialog extends DialogComponentProvider 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); - JPanel namePanel = createNamePanel(); + panel.add(dataTreePanel, BorderLayout.CENTER); panel.add(namePanel, BorderLayout.SOUTH); + // can't add tree listeners until everything is built + addTreeListeners(); return panel; } @@ -537,7 +469,9 @@ public class DataTreeDialog extends DialogComponentProvider treePanel.addTreeSelectionListener(this); treePanel.setPreferredTreePanelSize(new Dimension(150, 150)); - addTreeListeners(); + // 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; @@ -633,9 +567,6 @@ public class DataTreeDialog extends DialogComponentProvider nameField.setEditable(userChoosesName); nameField.setEnabled(userChoosesName); - // don't put the filter in the dialog when the user can/must type a name, as it's confusing - treePanel.setTreeFilterEnabled(!userChoosesName); - JPanel namePanel = new JPanel(new PairLayout(2, 5, 100)); if (!userChoosesName) { @@ -688,12 +619,24 @@ public class DataTreeDialog extends DialogComponentProvider map = null; } - public void findAndSelect(String s) { - treePanel.findAndSelect(s); + public void setSearchText(String s) { + if (searchString != null) { + treePanel.findAndSelect(s); + } } - public void setSearchText(String string) { - searchString = string; + 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 { @@ -702,4 +645,5 @@ public class DataTreeDialog extends DialogComponentProvider clearStatusText(); } } + } 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 cef794835c..11481f8cb8 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 @@ -79,9 +79,20 @@ public class OpenVersionedFileDialog extends DataTreeDia super(tool.getToolFrame(), title, DataTreeDialog.OPEN, f -> { return domainObjectClass.isAssignableFrom(f.getDomainObjectClass()); }); + this.tool = tool; this.domainObjectClass = domainObjectClass; - init(); + updateOkTooltip(); + checkIfHistoryWasOpen(); + } + + private void checkIfHistoryWasOpen() { + String showHistory = + Preferences.getProperty(SHOW_HISTORY_PREFERENCES_KEY, Boolean.FALSE.toString(), true); + + if (Boolean.parseBoolean(showHistory)) { + showHistoryPanel(true); + } } /** @@ -164,6 +175,10 @@ public class OpenVersionedFileDialog extends DataTreeDia @Override protected JPanel buildMainPanel() { + historyButton = new JButton("History>>"); + historyButton.addActionListener(e -> showHistoryPanel(!historyIsShowing)); + + rootPanel.setPreferredSize(getPreferredSizeForHistoryState()); mainPanel = new JPanel(new BorderLayout()); mainPanel.add(super.buildMainPanel(), BorderLayout.CENTER); @@ -183,18 +198,9 @@ public class OpenVersionedFileDialog extends DataTreeDia JPanel projectFilePanel = new JPanel(new BorderLayout()); projectFilePanel.add(splitPane); - String showHistory = - Preferences.getProperty(SHOW_HISTORY_PREFERENCES_KEY, Boolean.FALSE.toString(), true); - - if (Boolean.parseBoolean(showHistory)) { - showHistoryPanel(true); - } - openObjectsTable = null; tabbedPane = null; - updateOkTooltip(); - if (openDomainObjects == null) { return projectFilePanel; // return Project File selection panel only } @@ -245,7 +251,7 @@ public class OpenVersionedFileDialog extends DataTreeDia openObjectsTable = new GFilterTable<>(new OpenObjectsTableModel()); GTable table = openObjectsTable.getTable(); table.getSelectionModel() - .setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + .setSelectionMode(ListSelectionModel.SINGLE_SELECTION); openObjectsTable.addSelectionListener(e -> { setOkEnabled(true); okButton.setToolTipText("Use the selected " + domainObjectClass.getSimpleName()); @@ -376,13 +382,6 @@ public class OpenVersionedFileDialog extends DataTreeDia return true; } - private void init() { - historyButton = new JButton("History>>"); - historyButton.addActionListener(e -> showHistoryPanel(!historyIsShowing)); - - rootPanel.setPreferredSize(getPreferredSizeForHistoryState()); - } - @Override protected void addTreeListeners() { super.addTreeListeners(); diff --git a/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffTestAdapter.java b/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffTestAdapter.java index ca438768f9..855186fda0 100644 --- a/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffTestAdapter.java +++ b/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffTestAdapter.java @@ -665,8 +665,12 @@ public class DiffTestAdapter extends AbstractGhidraHeadedIntegrationTest { void pickSecondProgram(final Program program2) { - OpenVersionedFileDialogTestFake dialog = new OpenVersionedFileDialogTestFake(program2); - diffPlugin.setDiffOpenVersionedFileDialog(dialog); + OpenVersionedFileDialogTestFake dialog = runSwing(() -> { + OpenVersionedFileDialogTestFake openDialog = + new OpenVersionedFileDialogTestFake(program2); + diffPlugin.setDiffOpenVersionedFileDialog(openDialog); + return openDialog; + }); launchDiffByAction();