mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-28 15:45:32 +08:00
GP-1699 - Updated script 'ask' methods to place widget building on the Swing thread
This commit is contained in:
@@ -17,14 +17,10 @@ package ghidra.app.script;
|
|||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.rmi.ConnectException;
|
import java.rmi.ConnectException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import javax.swing.SwingUtilities;
|
|
||||||
|
|
||||||
import docking.DockingWindowManager;
|
|
||||||
import docking.widgets.OptionDialog;
|
import docking.widgets.OptionDialog;
|
||||||
import docking.widgets.dialogs.MultiLineMessageDialog;
|
import docking.widgets.dialogs.MultiLineMessageDialog;
|
||||||
import docking.widgets.filechooser.GhidraFileChooser;
|
import docking.widgets.filechooser.GhidraFileChooser;
|
||||||
@@ -87,12 +83,12 @@ import ghidra.util.task.TaskMonitor;
|
|||||||
* When you create a new script using the script manager,
|
* When you create a new script using the script manager,
|
||||||
* you will automatically receive a source code stub (as shown below).
|
* you will automatically receive a source code stub (as shown below).
|
||||||
* <pre>
|
* <pre>
|
||||||
* //TODO write a description for this script
|
* // TODO write a description for this script
|
||||||
*
|
*
|
||||||
* public class NewScript extends GhidraScript {
|
* public class NewScript extends GhidraScript {
|
||||||
*
|
*
|
||||||
* public void run() throws Exception {
|
* public void run() throws Exception {
|
||||||
* //TODO Add User Code Here
|
* // TODO Add User Code Here
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
@@ -565,7 +561,7 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||||||
// only change client authenticator in headless mode
|
// only change client authenticator in headless mode
|
||||||
try {
|
try {
|
||||||
HeadlessClientAuthenticator
|
HeadlessClientAuthenticator
|
||||||
.installHeadlessClientAuthenticator(ClientUtil.getUserName(), null, false);
|
.installHeadlessClientAuthenticator(ClientUtil.getUserName(), null, false);
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
throw new RuntimeException("Unexpected Exception", e);
|
throw new RuntimeException("Unexpected Exception", e);
|
||||||
@@ -1340,10 +1336,9 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||||||
Msg.error(this, errorBuffer.toString());
|
Msg.error(this, errorBuffer.toString());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
MultiLineMessageDialog dialog = new MultiLineMessageDialog("Analysis Options",
|
MultiLineMessageDialog.showMessageDialog(null, "Analysis Options",
|
||||||
"Ghidra encountered error(s) when attempting to set analysis options.",
|
"Ghidra encountered error(s) when attempting to set analysis options.",
|
||||||
errorBuffer.toString(), MultiLineMessageDialog.WARNING_MESSAGE, false);
|
errorBuffer.toString(), MultiLineMessageDialog.WARNING_MESSAGE);
|
||||||
DockingWindowManager.showDialog(null, dialog);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1366,10 +1361,9 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||||||
Msg.error(this, errorMsg);
|
Msg.error(this, errorMsg);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
MultiLineMessageDialog dialog = new MultiLineMessageDialog("Analysis Options",
|
MultiLineMessageDialog.showMessageDialog(null, "Analysis Options",
|
||||||
"Ghidra encountered error(s) when attempting to set analysis options.",
|
"Ghidra encountered error(s) when attempting to set analysis options.",
|
||||||
errorMsg, MultiLineMessageDialog.WARNING_MESSAGE, false);
|
errorMsg, MultiLineMessageDialog.WARNING_MESSAGE);
|
||||||
DockingWindowManager.showDialog(null, dialog);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1796,23 +1790,8 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||||||
Msg.info(this, message);
|
Msg.info(this, message);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
String name = getClass().getName();
|
||||||
final String name = getClass().getName();
|
Msg.showInfo(getClass(), null, name, message);
|
||||||
if (SwingUtilities.isEventDispatchThread()) {
|
|
||||||
Msg.showInfo(getClass(), null, name, message);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
try {
|
|
||||||
SwingUtilities
|
|
||||||
.invokeAndWait(() -> Msg.showInfo(getClass(), null, name, message));
|
|
||||||
}
|
|
||||||
catch (InterruptedException e) {
|
|
||||||
// shouldn't happen
|
|
||||||
}
|
|
||||||
catch (InvocationTargetException e) {
|
|
||||||
// shouldn't happen
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1981,7 +1960,7 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||||||
|
|
||||||
T lastValue = (mappedValue != null) ? mappedValue : defaultValue;
|
T lastValue = (mappedValue != null) ? mappedValue : defaultValue;
|
||||||
|
|
||||||
T newValue = asker.apply(lastValue); // may be cancelled
|
T newValue = swing(asker, lastValue); // may be cancelled
|
||||||
|
|
||||||
map.put(clazz, newValue);
|
map.put(clazz, newValue);
|
||||||
return newValue;
|
return newValue;
|
||||||
@@ -2039,22 +2018,17 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||||||
File choice = doAsk(File.class, title, approveButtonText, existingValue, lastValue -> {
|
File choice = doAsk(File.class, title, approveButtonText, existingValue, lastValue -> {
|
||||||
|
|
||||||
GhidraFileChooser chooser = new GhidraFileChooser(null);
|
GhidraFileChooser chooser = new GhidraFileChooser(null);
|
||||||
AtomicReference<File> ref = new AtomicReference<>();
|
chooser.setSelectedFile(lastValue);
|
||||||
|
chooser.setTitle(title);
|
||||||
Runnable r = () -> {
|
chooser.setApproveButtonText(approveButtonText);
|
||||||
chooser.setSelectedFile(lastValue);
|
chooser.setFileSelectionMode(GhidraFileChooserMode.FILES_ONLY);
|
||||||
chooser.setTitle(title);
|
File file = chooser.getSelectedFile();
|
||||||
chooser.setApproveButtonText(approveButtonText);
|
|
||||||
chooser.setFileSelectionMode(GhidraFileChooserMode.FILES_ONLY);
|
|
||||||
ref.set(chooser.getSelectedFile());
|
|
||||||
};
|
|
||||||
Swing.runNow(r);
|
|
||||||
|
|
||||||
if (chooser.wasCancelled()) {
|
if (chooser.wasCancelled()) {
|
||||||
throw new CancelledException();
|
throw new CancelledException();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ref.get();
|
return file;
|
||||||
});
|
});
|
||||||
|
|
||||||
return choice;
|
return choice;
|
||||||
@@ -2121,22 +2095,17 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||||||
File choice = doAsk(DIRECTORY.class, title, approveButtonText, existingValue, lastValue -> {
|
File choice = doAsk(DIRECTORY.class, title, approveButtonText, existingValue, lastValue -> {
|
||||||
|
|
||||||
GhidraFileChooser chooser = new GhidraFileChooser(null);
|
GhidraFileChooser chooser = new GhidraFileChooser(null);
|
||||||
AtomicReference<File> ref = new AtomicReference<>();
|
chooser.setSelectedFile(lastValue);
|
||||||
|
chooser.setTitle(title);
|
||||||
Runnable r = () -> {
|
chooser.setApproveButtonText(approveButtonText);
|
||||||
chooser.setSelectedFile(lastValue);
|
chooser.setFileSelectionMode(GhidraFileChooserMode.DIRECTORIES_ONLY);
|
||||||
chooser.setTitle(title);
|
File file = chooser.getSelectedFile();
|
||||||
chooser.setApproveButtonText(approveButtonText);
|
|
||||||
chooser.setFileSelectionMode(GhidraFileChooserMode.DIRECTORIES_ONLY);
|
|
||||||
ref.set(chooser.getSelectedFile());
|
|
||||||
};
|
|
||||||
Swing.runNow(r);
|
|
||||||
|
|
||||||
if (chooser.wasCancelled()) {
|
if (chooser.wasCancelled()) {
|
||||||
throw new CancelledException();
|
throw new CancelledException();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ref.get();
|
return file;
|
||||||
});
|
});
|
||||||
|
|
||||||
return choice;
|
return choice;
|
||||||
@@ -2230,19 +2199,13 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||||||
doAsk(clazz, title, approveButtonText, existingValue, lastValue -> {
|
doAsk(clazz, title, approveButtonText, existingValue, lastValue -> {
|
||||||
|
|
||||||
SelectLanguageDialog dialog = new SelectLanguageDialog(title, approveButtonText);
|
SelectLanguageDialog dialog = new SelectLanguageDialog(title, approveButtonText);
|
||||||
AtomicReference<LanguageCompilerSpecPair> ref = new AtomicReference<>();
|
dialog.setSelectedLanguage(lastValue);
|
||||||
|
dialog.show();
|
||||||
Runnable r = () -> {
|
|
||||||
dialog.setSelectedLanguage(lastValue);
|
|
||||||
ref.set(dialog.getSelectedLanguage());
|
|
||||||
};
|
|
||||||
Swing.runNow(r);
|
|
||||||
|
|
||||||
if (dialog.wasCancelled()) {
|
if (dialog.wasCancelled()) {
|
||||||
throw new CancelledException();
|
throw new CancelledException();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ref.get();
|
return dialog.getSelectedLanguage();
|
||||||
});
|
});
|
||||||
|
|
||||||
return choice;
|
return choice;
|
||||||
@@ -2309,21 +2272,12 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||||||
DomainFolder choice = doAsk(Program.class, title, "", existingValue, lastValue -> {
|
DomainFolder choice = doAsk(Program.class, title, "", existingValue, lastValue -> {
|
||||||
|
|
||||||
DataTreeDialog dtd = new DataTreeDialog(null, title, DataTreeDialog.CHOOSE_FOLDER);
|
DataTreeDialog dtd = new DataTreeDialog(null, title, DataTreeDialog.CHOOSE_FOLDER);
|
||||||
AtomicReference<DomainFolder> ref = new AtomicReference<>();
|
dtd.show();
|
||||||
|
|
||||||
dtd.addOkActionListener(e -> {
|
|
||||||
ref.set(dtd.getDomainFolder());
|
|
||||||
dtd.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
Runnable r = () -> dtd.showComponent();
|
|
||||||
Swing.runNow(r);
|
|
||||||
|
|
||||||
if (dtd.wasCancelled()) {
|
if (dtd.wasCancelled()) {
|
||||||
throw new CancelledException();
|
throw new CancelledException();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ref.get();
|
return dtd.getDomainFolder();
|
||||||
});
|
});
|
||||||
|
|
||||||
return choice;
|
return choice;
|
||||||
@@ -2676,21 +2630,12 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||||||
DomainFile choice = doAsk(Program.class, title, "", existingValue, lastValue -> {
|
DomainFile choice = doAsk(Program.class, title, "", existingValue, lastValue -> {
|
||||||
|
|
||||||
DataTreeDialog dtd = new DataTreeDialog(null, title, DataTreeDialog.OPEN);
|
DataTreeDialog dtd = new DataTreeDialog(null, title, DataTreeDialog.OPEN);
|
||||||
AtomicReference<DomainFile> ref = new AtomicReference<>();
|
dtd.show();
|
||||||
|
|
||||||
dtd.addOkActionListener(e -> {
|
|
||||||
ref.set(dtd.getDomainFile());
|
|
||||||
dtd.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
Runnable r = () -> dtd.showComponent();
|
|
||||||
Swing.runNow(r);
|
|
||||||
|
|
||||||
if (dtd.wasCancelled()) {
|
if (dtd.wasCancelled()) {
|
||||||
throw new CancelledException();
|
throw new CancelledException();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ref.get();
|
return dtd.getDomainFile();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (choice == null) {
|
if (choice == null) {
|
||||||
@@ -2768,21 +2713,12 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||||||
DomainFile choice = doAsk(DomainFile.class, title, message, existingValue, lastValue -> {
|
DomainFile choice = doAsk(DomainFile.class, title, message, existingValue, lastValue -> {
|
||||||
|
|
||||||
DataTreeDialog dtd = new DataTreeDialog(null, title, DataTreeDialog.OPEN);
|
DataTreeDialog dtd = new DataTreeDialog(null, title, DataTreeDialog.OPEN);
|
||||||
AtomicReference<DomainFile> ref = new AtomicReference<>();
|
dtd.show();
|
||||||
|
|
||||||
dtd.addOkActionListener(e -> {
|
|
||||||
ref.set(dtd.getDomainFile());
|
|
||||||
dtd.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
Runnable r = () -> dtd.showComponent();
|
|
||||||
Swing.runNow(r);
|
|
||||||
|
|
||||||
if (dtd.wasCancelled()) {
|
if (dtd.wasCancelled()) {
|
||||||
throw new CancelledException();
|
throw new CancelledException();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ref.get();
|
return dtd.getDomainFile();
|
||||||
});
|
});
|
||||||
|
|
||||||
return choice;
|
return choice;
|
||||||
@@ -3170,18 +3106,14 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||||||
Class<?> clazz = choices.get(0).getClass();
|
Class<?> clazz = choices.get(0).getClass();
|
||||||
List<T> choice = doAsk(clazz, title, message, existingValue, lastValue -> {
|
List<T> choice = doAsk(clazz, title, message, existingValue, lastValue -> {
|
||||||
|
|
||||||
AtomicReference<List<T>> reference = new AtomicReference<>();
|
|
||||||
MultipleOptionsDialog<T> dialog =
|
MultipleOptionsDialog<T> dialog =
|
||||||
new MultipleOptionsDialog<>(title, message, choices, true);
|
new MultipleOptionsDialog<>(title, message, choices, true);
|
||||||
|
dialog.show();
|
||||||
Runnable r = () -> reference.set(dialog.getUserChoices());
|
|
||||||
Swing.runNow(r);
|
|
||||||
|
|
||||||
if (dialog.isCanceled()) {
|
if (dialog.isCanceled()) {
|
||||||
throw new CancelledException();
|
throw new CancelledException();
|
||||||
}
|
}
|
||||||
|
|
||||||
return reference.get();
|
return dialog.getUserChoices();
|
||||||
});
|
});
|
||||||
|
|
||||||
return choice;
|
return choice;
|
||||||
@@ -3247,18 +3179,14 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||||||
Class<?> clazz = choices.get(0).getClass();
|
Class<?> clazz = choices.get(0).getClass();
|
||||||
List<T> choice = doAsk(clazz, title, message, existingValue, lastValue -> {
|
List<T> choice = doAsk(clazz, title, message, existingValue, lastValue -> {
|
||||||
|
|
||||||
AtomicReference<List<T>> reference = new AtomicReference<>();
|
|
||||||
MultipleOptionsDialog<T> dialog =
|
MultipleOptionsDialog<T> dialog =
|
||||||
new MultipleOptionsDialog<>(title, message, choices, choiceLabels, true);
|
new MultipleOptionsDialog<>(title, message, choices, choiceLabels, true);
|
||||||
|
dialog.show();
|
||||||
Runnable r = () -> reference.set(dialog.getUserChoices());
|
|
||||||
Swing.runNow(r);
|
|
||||||
|
|
||||||
if (dialog.isCanceled()) {
|
if (dialog.isCanceled()) {
|
||||||
throw new CancelledException();
|
throw new CancelledException();
|
||||||
}
|
}
|
||||||
|
|
||||||
return reference.get();
|
return dialog.getUserChoices();
|
||||||
});
|
});
|
||||||
|
|
||||||
return choice;
|
return choice;
|
||||||
@@ -3742,22 +3670,20 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||||||
Swing.runLater(runnable);
|
Swing.runLater(runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void show(final String title, final TableService table,
|
private void show(String title, TableService table, AddressSetView addresses) {
|
||||||
final AddressSetView addresses) {
|
|
||||||
PluginTool tool = state.getTool();
|
PluginTool tool = state.getTool();
|
||||||
if (tool == null) {
|
if (tool == null) {
|
||||||
println("Couldn't show table!");
|
println("Couldn't show table!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Runnable runnable = () -> {
|
Swing.runLater(() -> {
|
||||||
AddressSetTableModel model =
|
AddressSetTableModel model =
|
||||||
new AddressSetTableModel(title, state.getTool(), currentProgram, addresses, null);
|
new AddressSetTableModel(title, state.getTool(), currentProgram, addresses, null);
|
||||||
TableComponentProvider<Address> tableProvider = table.showTableWithMarkers(title,
|
TableComponentProvider<Address> tableProvider = table.showTableWithMarkers(title,
|
||||||
"GhidraScript", model, Color.GREEN, null, "Script Results", null);
|
"GhidraScript", model, Color.GREEN, null, "Script Results", null);
|
||||||
tableProvider.installRemoveItemsAction();
|
tableProvider.installRemoveItemsAction();
|
||||||
};
|
});
|
||||||
Swing.runLater(runnable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<Class<?>, Object> getScriptMap(String title, String message) {
|
private Map<Class<?>, Object> getScriptMap(String title, String message) {
|
||||||
@@ -3780,4 +3706,26 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
|||||||
}
|
}
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static <T> T swing(CancellableFunction<T, T> f, T t) throws CancelledException {
|
||||||
|
|
||||||
|
AtomicBoolean wasCancelled = new AtomicBoolean();
|
||||||
|
T result = Swing.runNow(() -> {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return f.apply(t);
|
||||||
|
}
|
||||||
|
catch (CancelledException e) {
|
||||||
|
wasCancelled.set(true);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (wasCancelled.get()) {
|
||||||
|
throw new CancelledException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import docking.DialogComponentProvider;
|
|||||||
import docking.DockingWindowManager;
|
import docking.DockingWindowManager;
|
||||||
import docking.widgets.checkbox.GCheckBox;
|
import docking.widgets.checkbox.GCheckBox;
|
||||||
import docking.widgets.label.GLabel;
|
import docking.widgets.label.GLabel;
|
||||||
import ghidra.util.Msg;
|
|
||||||
|
|
||||||
public class MultipleOptionsDialog<T> extends DialogComponentProvider {
|
public class MultipleOptionsDialog<T> extends DialogComponentProvider {
|
||||||
|
|
||||||
@@ -104,21 +103,10 @@ public class MultipleOptionsDialog<T> extends DialogComponentProvider {
|
|||||||
addWorkPanel(panel);
|
addWorkPanel(panel);
|
||||||
addOKButton();
|
addOKButton();
|
||||||
addCancelButton();
|
addCancelButton();
|
||||||
|
}
|
||||||
|
|
||||||
if (SwingUtilities.isEventDispatchThread()) {
|
public void show() {
|
||||||
DockingWindowManager.showDialog(null, this);
|
DockingWindowManager.showDialog(null, this);
|
||||||
}
|
|
||||||
else {
|
|
||||||
try {
|
|
||||||
SwingUtilities.invokeAndWait(
|
|
||||||
() -> DockingWindowManager.showDialog(null, MultipleOptionsDialog.this));
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
Msg.error(this, "Unable to get choices from the user; error showing dialog - " +
|
|
||||||
e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -19,12 +19,11 @@ import docking.DialogComponentProvider;
|
|||||||
import docking.DockingWindowManager;
|
import docking.DockingWindowManager;
|
||||||
import ghidra.plugin.importer.NewLanguagePanel;
|
import ghidra.plugin.importer.NewLanguagePanel;
|
||||||
import ghidra.program.model.lang.LanguageCompilerSpecPair;
|
import ghidra.program.model.lang.LanguageCompilerSpecPair;
|
||||||
import ghidra.util.SystemUtilities;
|
import ghidra.util.Swing;
|
||||||
|
|
||||||
public class SelectLanguageDialog extends DialogComponentProvider {
|
public class SelectLanguageDialog extends DialogComponentProvider {
|
||||||
|
|
||||||
private NewLanguagePanel languagePanel;
|
private NewLanguagePanel languagePanel;
|
||||||
private boolean actionComplete = false;
|
|
||||||
private LanguageCompilerSpecPair selectedLcsPair;
|
private LanguageCompilerSpecPair selectedLcsPair;
|
||||||
private boolean wasCancelled = false;
|
private boolean wasCancelled = false;
|
||||||
|
|
||||||
@@ -47,7 +46,6 @@ public class SelectLanguageDialog extends DialogComponentProvider {
|
|||||||
@Override
|
@Override
|
||||||
protected void okCallback() {
|
protected void okCallback() {
|
||||||
if (checkInput()) {
|
if (checkInput()) {
|
||||||
actionComplete = true;
|
|
||||||
selectedLcsPair = languagePanel.getSelectedLcsPair();
|
selectedLcsPair = languagePanel.getSelectedLcsPair();
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
@@ -74,18 +72,14 @@ public class SelectLanguageDialog extends DialogComponentProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setSelectedLanguage(LanguageCompilerSpecPair language) {
|
void setSelectedLanguage(LanguageCompilerSpecPair language) {
|
||||||
SystemUtilities.runSwingNow(() -> languagePanel.setSelectedLcsPair(language));
|
Swing.runNow(() -> languagePanel.setSelectedLcsPair(language));
|
||||||
}
|
}
|
||||||
|
|
||||||
public LanguageCompilerSpecPair getSelectedLanguage() {
|
public LanguageCompilerSpecPair getSelectedLanguage() {
|
||||||
|
|
||||||
SystemUtilities.runSwingNow(() -> showDialog());
|
|
||||||
return selectedLcsPair;
|
return selectedLcsPair;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showDialog() {
|
public void show() {
|
||||||
selectedLcsPair = null;
|
|
||||||
actionComplete = false;
|
|
||||||
DockingWindowManager.showDialog(null, this);
|
DockingWindowManager.showDialog(null, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,10 +32,12 @@ import docking.widgets.label.GDLabel;
|
|||||||
import docking.widgets.label.GLabel;
|
import docking.widgets.label.GLabel;
|
||||||
import docking.widgets.tree.support.GTreeSelectionEvent;
|
import docking.widgets.tree.support.GTreeSelectionEvent;
|
||||||
import docking.widgets.tree.support.GTreeSelectionListener;
|
import docking.widgets.tree.support.GTreeSelectionListener;
|
||||||
|
import ghidra.framework.main.datatree.DialogProjectTreeContext;
|
||||||
import ghidra.framework.main.datatree.ProjectDataTreePanel;
|
import ghidra.framework.main.datatree.ProjectDataTreePanel;
|
||||||
import ghidra.framework.main.projectdata.actions.*;
|
import ghidra.framework.main.projectdata.actions.*;
|
||||||
import ghidra.framework.model.*;
|
import ghidra.framework.model.*;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
import ghidra.util.Swing;
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
import ghidra.util.layout.PairLayout;
|
import ghidra.util.layout.PairLayout;
|
||||||
|
|
||||||
@@ -56,8 +58,7 @@ public class DataTreeDialog extends DialogComponentProvider
|
|||||||
/**
|
/**
|
||||||
* Dialog type for choosing a user folder.
|
* Dialog type for choosing a user folder.
|
||||||
*/
|
*/
|
||||||
public final static int CHOOSE_FOLDER = 2; // choose only a
|
public final static int CHOOSE_FOLDER = 2;
|
||||||
// folder owned by the user
|
|
||||||
/**
|
/**
|
||||||
* Dialog type for creating domain data files.
|
* Dialog type for creating domain data files.
|
||||||
*/
|
*/
|
||||||
@@ -85,9 +86,9 @@ public class DataTreeDialog extends DialogComponentProvider
|
|||||||
private String pendingNameText;
|
private String pendingNameText;
|
||||||
private DomainFolder pendingDomainFolder;
|
private DomainFolder pendingDomainFolder;
|
||||||
|
|
||||||
private ProjectDataExpandAction expandAction;
|
private ProjectDataExpandAction<DialogProjectTreeContext> expandAction;
|
||||||
private ProjectDataCollapseAction collapseAction;
|
private ProjectDataCollapseAction<DialogProjectTreeContext> collapseAction;
|
||||||
private ProjectDataNewFolderAction newFolderAction;
|
private ProjectDataNewFolderAction<DialogProjectTreeContext> newFolderAction;
|
||||||
|
|
||||||
private Integer treeSelectionMode;
|
private Integer treeSelectionMode;
|
||||||
|
|
||||||
@@ -188,15 +189,22 @@ public class DataTreeDialog extends DialogComponentProvider
|
|||||||
return treePanel.getActionContext(null, event);
|
return treePanel.getActionContext(null, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showComponent() {
|
public void show() {
|
||||||
doSetup();
|
doSetup();
|
||||||
DockingWindowManager.showDialog(parent, this);
|
DockingWindowManager.showDialog(parent, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows this dialog. The preferred show method is {@link #show()}, as it is the preferred
|
||||||
|
* nomenclature.
|
||||||
|
*/
|
||||||
|
public void showComponent() {
|
||||||
|
show();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void dialogShown() {
|
protected void dialogShown() {
|
||||||
if (!comboModelInitialized) {
|
if (!comboModelInitialized) {
|
||||||
// make sure the combo box model has been populated
|
|
||||||
doSetup();
|
doSetup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -255,9 +263,6 @@ public class DataTreeDialog extends DialogComponentProvider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the name from the name field.
|
|
||||||
*/
|
|
||||||
public String getNameText() {
|
public String getNameText() {
|
||||||
return nameField.getText();
|
return nameField.getText();
|
||||||
}
|
}
|
||||||
@@ -275,7 +280,16 @@ public class DataTreeDialog extends DialogComponentProvider
|
|||||||
* @return null if there was no domain file selected
|
* @return null if there was no domain file selected
|
||||||
*/
|
*/
|
||||||
public DomainFile getDomainFile() {
|
public DomainFile getDomainFile() {
|
||||||
if (domainFile == null && !cancelled) {
|
|
||||||
|
if (domainFile != null) {
|
||||||
|
return domainFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancelled) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (treePanel != null) {
|
||||||
domainFile = treePanel.getSelectedDomainFile();
|
domainFile = treePanel.getSelectedDomainFile();
|
||||||
}
|
}
|
||||||
return domainFile;
|
return domainFile;
|
||||||
@@ -293,8 +307,7 @@ public class DataTreeDialog extends DialogComponentProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TreeSelectionListener method that is called whenever the value of the
|
* TreeSelectionListener method that is called whenever the value of the selection changes.
|
||||||
* selection changes.
|
|
||||||
* @param e the event that characterizes the change.
|
* @param e the event that characterizes the change.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -364,31 +377,23 @@ public class DataTreeDialog extends DialogComponentProvider
|
|||||||
setOkEnabled((text != null) && !text.isEmpty());
|
setOkEnabled((text != null) && !text.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Action listener for the project combo box.
|
|
||||||
* @param e event generated when a selection is made in the combo box
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent event) {
|
||||||
int index = projectComboBox.getSelectedIndex();
|
int index = projectComboBox.getSelectedIndex();
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Project project = AppInfo.getActiveProject();
|
|
||||||
try {
|
|
||||||
ProjectData pd = project.getProjectData(projectLocators[index]);
|
|
||||||
|
|
||||||
if (pd == null) {
|
Project project = AppInfo.getActiveProject();
|
||||||
Msg.showError(getClass(), getComponent(), "Error Getting Project Data",
|
ProjectLocator projectLocator = projectLocators[index];
|
||||||
"Could not get project data for " + projectLocators[index].getName());
|
ProjectData pd = project.getProjectData(projectLocator);
|
||||||
}
|
String projectName = projectLocator.getName();
|
||||||
else {
|
if (pd == null) {
|
||||||
treePanel.setProjectData(projectLocators[index].getName(), pd);
|
Msg.showError(this, getComponent(), "Error Getting Project Data",
|
||||||
}
|
"Could not get project data for " + projectName);
|
||||||
}
|
}
|
||||||
catch (Exception exc) {
|
else {
|
||||||
Msg.showError(getClass(), getComponent(), "Error Getting Project Data", exc.toString(),
|
treePanel.setProjectData(projectName, pd);
|
||||||
exc);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,19 +401,17 @@ public class DataTreeDialog extends DialogComponentProvider
|
|||||||
* Select the root folder in the tree.
|
* Select the root folder in the tree.
|
||||||
*/
|
*/
|
||||||
public void selectRootDataFolder() {
|
public void selectRootDataFolder() {
|
||||||
SwingUtilities.invokeLater(() -> treePanel.selectRootDataFolder());
|
Swing.runLater(() -> treePanel.selectRootDataFolder());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select the node that corresponds to the given domain file.
|
* Select the node that corresponds to the given domain file.
|
||||||
|
* @param file the file
|
||||||
*/
|
*/
|
||||||
public void selectDomainFile(final DomainFile file) {
|
public void selectDomainFile(DomainFile file) {
|
||||||
SwingUtilities.invokeLater(() -> treePanel.selectDomainFile(file));
|
Swing.runLater(() -> treePanel.selectDomainFile(file));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see docking.DialogComponentProvider#close()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
super.close();
|
super.close();
|
||||||
@@ -420,10 +423,6 @@ public class DataTreeDialog extends DialogComponentProvider
|
|||||||
comboModelInitialized = false;
|
comboModelInitialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Define the Main panel for the dialog here.
|
|
||||||
* @return JPanel the completed <CODE>Main Panel</CODE>
|
|
||||||
*/
|
|
||||||
protected JPanel buildMainPanel() {
|
protected JPanel buildMainPanel() {
|
||||||
|
|
||||||
JPanel panel = new JPanel();
|
JPanel panel = new JPanel();
|
||||||
@@ -445,9 +444,6 @@ public class DataTreeDialog extends DialogComponentProvider
|
|||||||
return panel;
|
return panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets called when the user clicks on the OK Action for the dialog.
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
protected void okCallback() {
|
protected void okCallback() {
|
||||||
cancelled = false;
|
cancelled = false;
|
||||||
@@ -463,17 +459,12 @@ public class DataTreeDialog extends DialogComponentProvider
|
|||||||
return cancelled;
|
return cancelled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when user hits the cancel button.
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
protected void cancelCallback() {
|
protected void cancelCallback() {
|
||||||
cancelled = true;
|
cancelled = true;
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the data tree panel.
|
* Create the data tree panel.
|
||||||
*/
|
*/
|
||||||
@@ -653,13 +644,10 @@ public class DataTreeDialog extends DialogComponentProvider
|
|||||||
searchString = string;
|
searchString = string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
|
||||||
private class FieldKeyListener extends KeyAdapter {
|
private class FieldKeyListener extends KeyAdapter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void keyPressed(KeyEvent e) {
|
public void keyPressed(KeyEvent e) {
|
||||||
clearStatusText();
|
clearStatusText();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-12
@@ -98,12 +98,10 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
|||||||
// if we get here, then no exception happened--good!
|
// if we get here, then no exception happened--good!
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Test that askBytes method auto-populates dialog with value in .properties file.
|
* Test that askBytes method auto-populates dialog with value in .properties file.
|
||||||
*
|
*
|
||||||
* Also test that subsequent calls to the dialog show the last-used value.
|
* Also test that subsequent calls to the dialog show the last-used value.
|
||||||
*
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testAskBytes() throws Exception {
|
public void testAskBytes() throws Exception {
|
||||||
@@ -309,12 +307,10 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
|||||||
assertEquals(anotherTempFile, myFile[0]);
|
assertEquals(anotherTempFile, myFile[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Test that askDirectory method auto-populates dialog with value in .properties file.
|
* Test that askDirectory method auto-populates dialog with value in .properties file.
|
||||||
*
|
*
|
||||||
* Also test that subsequent calls to the dialog show the last-used value.
|
* Also test that subsequent calls to the dialog show the last-used value.
|
||||||
*
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testAskDirectory() throws Exception {
|
public void testAskDirectory() throws Exception {
|
||||||
@@ -416,12 +412,10 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
|||||||
FileUtilities.deleteDir(anotherTempSubDir);
|
FileUtilities.deleteDir(anotherTempSubDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Test that askLanguage method auto-populates dialog with value in .properties file.
|
* Test that askLanguage method auto-populates dialog with value in .properties file.
|
||||||
*
|
*
|
||||||
* Also test that subsequent calls to the dialog show the last-used value.
|
* Also test that subsequent calls to the dialog show the last-used value.
|
||||||
*
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testAskLanguage() throws Exception {
|
public void testAskLanguage() throws Exception {
|
||||||
@@ -662,11 +656,9 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
|||||||
assertEquals(choice_eenie, chosen);
|
assertEquals(choice_eenie, chosen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Test that askChoice method auto-populates dialog with user-supplied default value (in the
|
* Test that askChoice method auto-populates dialog with user-supplied default value (in the
|
||||||
* absence of a .properties file).
|
* absence of a .properties file).
|
||||||
*
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testAskChoiceDefaultValue() throws Exception {
|
public void testAskChoiceDefaultValue() throws Exception {
|
||||||
|
|||||||
+1
@@ -171,6 +171,7 @@ public class PopulateFidDialog extends DialogComponentProvider {
|
|||||||
browseButton.addActionListener(e -> {
|
browseButton.addActionListener(e -> {
|
||||||
SelectLanguageDialog selectLanguageDialog =
|
SelectLanguageDialog selectLanguageDialog =
|
||||||
new SelectLanguageDialog("Select Language", "Ok");
|
new SelectLanguageDialog("Select Language", "Ok");
|
||||||
|
selectLanguageDialog.show();
|
||||||
LanguageCompilerSpecPair selectedLanguage = selectLanguageDialog.getSelectedLanguage();
|
LanguageCompilerSpecPair selectedLanguage = selectLanguageDialog.getSelectedLanguage();
|
||||||
if (selectedLanguage != null) {
|
if (selectedLanguage != null) {
|
||||||
languageIdField.setText(selectedLanguage.languageID.toString());
|
languageIdField.setText(selectedLanguage.languageID.toString());
|
||||||
|
|||||||
+12
-6
@@ -28,6 +28,7 @@ import docking.widgets.OptionDialog;
|
|||||||
import docking.widgets.label.GIconLabel;
|
import docking.widgets.label.GIconLabel;
|
||||||
import docking.widgets.label.GLabel;
|
import docking.widgets.label.GLabel;
|
||||||
import ghidra.util.HTMLUtilities;
|
import ghidra.util.HTMLUtilities;
|
||||||
|
import ghidra.util.Swing;
|
||||||
|
|
||||||
public class MultiLineMessageDialog extends DialogComponentProvider {
|
public class MultiLineMessageDialog extends DialogComponentProvider {
|
||||||
/** Used for error messages. */
|
/** Used for error messages. */
|
||||||
@@ -61,16 +62,21 @@ public class MultiLineMessageDialog extends DialogComponentProvider {
|
|||||||
*/
|
*/
|
||||||
public static void showModalMessageDialog(Component parent, String title, String shortMessage,
|
public static void showModalMessageDialog(Component parent, String title, String shortMessage,
|
||||||
String detailedMessage, int messageType) {
|
String detailedMessage, int messageType) {
|
||||||
MultiLineMessageDialog mlmd =
|
Swing.runNow(() -> {
|
||||||
new MultiLineMessageDialog(title, shortMessage, detailedMessage, messageType, true);
|
MultiLineMessageDialog dialog =
|
||||||
DockingWindowManager.showDialog(parent, mlmd);
|
new MultiLineMessageDialog(title, shortMessage, detailedMessage, messageType, true);
|
||||||
|
DockingWindowManager.showDialog(parent, dialog);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void showMessageDialog(Component parent, String title, String shortMessage,
|
public static void showMessageDialog(Component parent, String title, String shortMessage,
|
||||||
String detailedMessage, int messageType) {
|
String detailedMessage, int messageType) {
|
||||||
MultiLineMessageDialog mlmd =
|
Swing.runNow(() -> {
|
||||||
new MultiLineMessageDialog(title, shortMessage, detailedMessage, messageType, false);
|
MultiLineMessageDialog dialog =
|
||||||
DockingWindowManager.showDialog(parent, mlmd);
|
new MultiLineMessageDialog(title, shortMessage, detailedMessage, messageType,
|
||||||
|
false);
|
||||||
|
DockingWindowManager.showDialog(parent, dialog);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user