mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
GP-4545 fixing focus issues for data tree dialog in windows OS.
This commit is contained in:
parent
9abfa3da86
commit
330f7fe87c
5 changed files with 84 additions and 147 deletions
|
@ -1184,12 +1184,7 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
|
||||||
|
|
||||||
DomainFileFilter filter = df -> Program.class.isAssignableFrom(df.getDomainObjectClass());
|
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);
|
||||||
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();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DomainFile askProgram(Program program) {
|
public DomainFile askProgram(Program program) {
|
||||||
|
|
|
@ -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);
|
||||||
return new DataTreeDialog(null, OpenTraceAction.NAME, DataTreeDialog.OPEN, filter) {
|
|
||||||
{ // TODO/HACK: Why the NPE if I don't do this?
|
|
||||||
dialogShown();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DomainFile askTrace(Trace trace) {
|
public DomainFile askTrace(Trace trace) {
|
||||||
|
|
|
@ -81,10 +81,7 @@ public class DataTreeDialog extends DialogComponentProvider
|
||||||
private Component parent;
|
private Component parent;
|
||||||
|
|
||||||
private String searchString;
|
private String searchString;
|
||||||
private boolean comboModelInitialized;
|
|
||||||
private boolean cancelled = false;
|
private boolean cancelled = false;
|
||||||
private String pendingNameText;
|
|
||||||
private DomainFolder pendingDomainFolder;
|
|
||||||
|
|
||||||
private ProjectDataExpandAction<DialogProjectTreeContext> expandAction;
|
private ProjectDataExpandAction<DialogProjectTreeContext> expandAction;
|
||||||
private ProjectDataCollapseAction<DialogProjectTreeContext> collapseAction;
|
private ProjectDataCollapseAction<DialogProjectTreeContext> collapseAction;
|
||||||
|
@ -134,23 +131,31 @@ public class DataTreeDialog extends DialogComponentProvider
|
||||||
public DataTreeDialog(Component parent, String title, int type, DomainFileFilter filter,
|
public DataTreeDialog(Component parent, String title, int type, DomainFileFilter filter,
|
||||||
Project project) {
|
Project project) {
|
||||||
super(title, true, true, true, false);
|
super(title, true, true, true, false);
|
||||||
|
|
||||||
|
if (type < 0 || type > CREATE) {
|
||||||
|
throw new IllegalArgumentException("Invalid type specified: " + type);
|
||||||
|
}
|
||||||
|
|
||||||
this.project = project;
|
this.project = project;
|
||||||
this.parent = parent;
|
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) {
|
private void initializeFocusedComponent() {
|
||||||
if (type == CHOOSE_FOLDER || type == OPEN) {
|
Component focusComponent = nameField;
|
||||||
// return filter which forces folder selection and allow navigation into linked-folders
|
if (!nameField.isEditable()) {
|
||||||
return new DomainFileFilter() {
|
focusComponent = treePanel.getFilterField();
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean accept(DomainFile df) {
|
|
||||||
return true; // show all files (legacy behavior)
|
|
||||||
}
|
}
|
||||||
};
|
setFocusComponent(focusComponent);
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTreeSelectionMode(int mode) {
|
public void setTreeSelectionMode(int mode) {
|
||||||
|
@ -160,34 +165,20 @@ public class DataTreeDialog extends DialogComponentProvider
|
||||||
treeSelectionMode = mode;
|
treeSelectionMode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initDataTreeDialog(int newType, DomainFileFilter newFilter) {
|
private void initializeButtons() {
|
||||||
|
addOKButton();
|
||||||
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);
|
|
||||||
addCancelButton();
|
addCancelButton();
|
||||||
|
|
||||||
if (newType == SAVE) {
|
if (type == SAVE) {
|
||||||
okButton.setText("Save");
|
okButton.setText("Save");
|
||||||
okButton.setMnemonic('S');
|
okButton.setMnemonic('S');
|
||||||
}
|
}
|
||||||
else if (newType == CREATE) {
|
else if (type == CREATE) {
|
||||||
okButton.setText("Create");
|
okButton.setText("Create");
|
||||||
okButton.setMnemonic('C');
|
okButton.setMnemonic('C');
|
||||||
}
|
}
|
||||||
|
setOkEnabled(false);
|
||||||
|
|
||||||
rootPanel.setPreferredSize(new Dimension(WIDTH, HEIGHT));
|
|
||||||
|
|
||||||
setFocusComponent(nameField);
|
|
||||||
|
|
||||||
createActions();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createActions() {
|
private void createActions() {
|
||||||
|
@ -223,7 +214,6 @@ public class DataTreeDialog extends DialogComponentProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
public void show() {
|
public void show() {
|
||||||
doSetup();
|
|
||||||
DockingWindowManager.showDialog(parent, this);
|
DockingWindowManager.showDialog(parent, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,79 +225,13 @@ public class DataTreeDialog extends DialogComponentProvider
|
||||||
show();
|
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() {
|
public String getNameText() {
|
||||||
return nameField.getText();
|
return nameField.getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNameText(String name) {
|
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
|
* @param folder {@link DomainFolder} to select when showing the dialog
|
||||||
*/
|
*/
|
||||||
public void setSelectedFolder(DomainFolder folder) {
|
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.dispose();
|
||||||
}
|
}
|
||||||
treePanel = null;
|
treePanel = null;
|
||||||
comboModelInitialized = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected JPanel buildMainPanel() {
|
protected JPanel buildMainPanel() {
|
||||||
|
@ -482,19 +407,26 @@ public class DataTreeDialog extends DialogComponentProvider
|
||||||
JPanel panel = new JPanel();
|
JPanel panel = new JPanel();
|
||||||
panel.setLayout(new BorderLayout());
|
panel.setLayout(new BorderLayout());
|
||||||
|
|
||||||
|
JPanel namePanel = createNamePanel();
|
||||||
|
|
||||||
// data tree panel must be created before the combo box
|
// data tree panel must be created before the combo box
|
||||||
JPanel dataTreePanel = createDataTreePanel();
|
JPanel dataTreePanel = createDataTreePanel();
|
||||||
|
ProjectData pd = project.getProjectData();
|
||||||
|
treePanel.setProjectData(project.getName(), pd);
|
||||||
|
treePanel.selectRootDataFolder();
|
||||||
|
|
||||||
if (type == OPEN) {
|
if (type == OPEN) {
|
||||||
JPanel comboPanel = createComboBoxPanel();
|
JPanel comboPanel = createComboBoxPanel();
|
||||||
|
|
||||||
panel.add(comboPanel, BorderLayout.NORTH);
|
panel.add(comboPanel, BorderLayout.NORTH);
|
||||||
|
populateProjectModel();
|
||||||
}
|
}
|
||||||
panel.add(dataTreePanel, BorderLayout.CENTER);
|
|
||||||
|
|
||||||
JPanel namePanel = createNamePanel();
|
panel.add(dataTreePanel, BorderLayout.CENTER);
|
||||||
panel.add(namePanel, BorderLayout.SOUTH);
|
panel.add(namePanel, BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
// can't add tree listeners until everything is built
|
||||||
|
addTreeListeners();
|
||||||
return panel;
|
return panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -537,7 +469,9 @@ public class DataTreeDialog extends DialogComponentProvider
|
||||||
treePanel.addTreeSelectionListener(this);
|
treePanel.addTreeSelectionListener(this);
|
||||||
treePanel.setPreferredTreePanelSize(new Dimension(150, 150));
|
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);
|
panel.add(treePanel, BorderLayout.CENTER);
|
||||||
return panel;
|
return panel;
|
||||||
|
@ -633,9 +567,6 @@ public class DataTreeDialog extends DialogComponentProvider
|
||||||
nameField.setEditable(userChoosesName);
|
nameField.setEditable(userChoosesName);
|
||||||
nameField.setEnabled(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));
|
JPanel namePanel = new JPanel(new PairLayout(2, 5, 100));
|
||||||
|
|
||||||
if (!userChoosesName) {
|
if (!userChoosesName) {
|
||||||
|
@ -688,12 +619,24 @@ public class DataTreeDialog extends DialogComponentProvider
|
||||||
map = null;
|
map = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void findAndSelect(String s) {
|
public void setSearchText(String s) {
|
||||||
|
if (searchString != null) {
|
||||||
treePanel.findAndSelect(s);
|
treePanel.findAndSelect(s);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setSearchText(String string) {
|
private static DomainFileFilter getDefaultFilter(int type) {
|
||||||
searchString = string;
|
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 {
|
private class FieldKeyListener extends KeyAdapter {
|
||||||
|
@ -702,4 +645,5 @@ public class DataTreeDialog extends DialogComponentProvider
|
||||||
clearStatusText();
|
clearStatusText();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,9 +79,20 @@ public class OpenVersionedFileDialog<T extends DomainObject> extends DataTreeDia
|
||||||
super(tool.getToolFrame(), title, DataTreeDialog.OPEN, f -> {
|
super(tool.getToolFrame(), title, DataTreeDialog.OPEN, f -> {
|
||||||
return domainObjectClass.isAssignableFrom(f.getDomainObjectClass());
|
return domainObjectClass.isAssignableFrom(f.getDomainObjectClass());
|
||||||
});
|
});
|
||||||
|
|
||||||
this.tool = tool;
|
this.tool = tool;
|
||||||
this.domainObjectClass = domainObjectClass;
|
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<T extends DomainObject> extends DataTreeDia
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected JPanel buildMainPanel() {
|
protected JPanel buildMainPanel() {
|
||||||
|
historyButton = new JButton("History>>");
|
||||||
|
historyButton.addActionListener(e -> showHistoryPanel(!historyIsShowing));
|
||||||
|
|
||||||
|
rootPanel.setPreferredSize(getPreferredSizeForHistoryState());
|
||||||
|
|
||||||
mainPanel = new JPanel(new BorderLayout());
|
mainPanel = new JPanel(new BorderLayout());
|
||||||
mainPanel.add(super.buildMainPanel(), BorderLayout.CENTER);
|
mainPanel.add(super.buildMainPanel(), BorderLayout.CENTER);
|
||||||
|
@ -183,18 +198,9 @@ public class OpenVersionedFileDialog<T extends DomainObject> extends DataTreeDia
|
||||||
JPanel projectFilePanel = new JPanel(new BorderLayout());
|
JPanel projectFilePanel = new JPanel(new BorderLayout());
|
||||||
projectFilePanel.add(splitPane);
|
projectFilePanel.add(splitPane);
|
||||||
|
|
||||||
String showHistory =
|
|
||||||
Preferences.getProperty(SHOW_HISTORY_PREFERENCES_KEY, Boolean.FALSE.toString(), true);
|
|
||||||
|
|
||||||
if (Boolean.parseBoolean(showHistory)) {
|
|
||||||
showHistoryPanel(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
openObjectsTable = null;
|
openObjectsTable = null;
|
||||||
tabbedPane = null;
|
tabbedPane = null;
|
||||||
|
|
||||||
updateOkTooltip();
|
|
||||||
|
|
||||||
if (openDomainObjects == null) {
|
if (openDomainObjects == null) {
|
||||||
return projectFilePanel; // return Project File selection panel only
|
return projectFilePanel; // return Project File selection panel only
|
||||||
}
|
}
|
||||||
|
@ -376,13 +382,6 @@ public class OpenVersionedFileDialog<T extends DomainObject> extends DataTreeDia
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init() {
|
|
||||||
historyButton = new JButton("History>>");
|
|
||||||
historyButton.addActionListener(e -> showHistoryPanel(!historyIsShowing));
|
|
||||||
|
|
||||||
rootPanel.setPreferredSize(getPreferredSizeForHistoryState());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void addTreeListeners() {
|
protected void addTreeListeners() {
|
||||||
super.addTreeListeners();
|
super.addTreeListeners();
|
||||||
|
|
|
@ -665,8 +665,12 @@ public class DiffTestAdapter extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
void pickSecondProgram(final Program program2) {
|
void pickSecondProgram(final Program program2) {
|
||||||
|
|
||||||
OpenVersionedFileDialogTestFake dialog = new OpenVersionedFileDialogTestFake(program2);
|
OpenVersionedFileDialogTestFake dialog = runSwing(() -> {
|
||||||
diffPlugin.setDiffOpenVersionedFileDialog(dialog);
|
OpenVersionedFileDialogTestFake openDialog =
|
||||||
|
new OpenVersionedFileDialogTestFake(program2);
|
||||||
|
diffPlugin.setDiffOpenVersionedFileDialog(openDialog);
|
||||||
|
return openDialog;
|
||||||
|
});
|
||||||
|
|
||||||
launchDiffByAction();
|
launchDiffByAction();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue