Merge remote-tracking branch 'origin/GT-2891-dragonmacher-optiondialog-to-swing'

This commit is contained in:
Ryan Kurtz 2019-06-03 08:12:11 -04:00
commit f3a7cb0490
16 changed files with 380 additions and 313 deletions

View file

@ -1,41 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.merge;
import java.awt.Component;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import docking.widgets.OptionDialog;
public class CancelMergeDialog extends OptionDialog {
public CancelMergeDialog(Icon icon) {
super("Confirm Cancel Merge",
"Warning! Cancel causes the entire merge process to be canceled.\n" +
"Do you want to cancel the Merge Process?",
"Yes", null, OptionDialog.PLAIN_MESSAGE, icon, true, "No");
setFocusComponent(cancelButton);
}
public static int showYesNoDialog(Component parent, ImageIcon icon) {
CancelMergeDialog dialog = new CancelMergeDialog(icon);
dialog.show(parent);
return dialog.getResult();
}
}

View file

@ -16,7 +16,7 @@
package ghidra.app.merge;
import java.awt.*;
import java.awt.event.*;
import java.awt.event.MouseEvent;
import javax.swing.*;
@ -35,7 +35,6 @@ import ghidra.framework.plugintool.ComponentProviderAdapter;
import ghidra.framework.project.tool.ToolIconURL;
import ghidra.program.util.ProgramLocation;
import ghidra.util.HelpLocation;
import ghidra.util.UniversalIdGenerator;
import ghidra.util.layout.VerticalLayout;
import resources.ResourceManager;
@ -60,14 +59,9 @@ class MergeManagerProvider extends ComponentProviderAdapter {
private JButton cancelButton;
private boolean wasCanceled;
private ImageIcon WARNING_ICON = ResourceManager.loadImage("images/warning.png");
private ImageIcon MERGE_ICON = ResourceManager.loadImage("images/Merge.png");
private long instanceID = UniversalIdGenerator.nextID().getValue();
private JPanel mainPanel;
/**
* Constructor
*/
public MergeManagerProvider(MergeManagerPlugin plugin, String title) {
super(plugin.getTool(), "Merge Manager", plugin.getName());
this.plugin = plugin;
@ -157,7 +151,7 @@ class MergeManagerProvider extends ComponentProviderAdapter {
/**
* Sets the merge description at the top of the merge tool.
* @param description
* @param description the description
*/
void updateMergeDescription(String description) {
nameLabel.setText(description);
@ -186,12 +180,18 @@ class MergeManagerProvider extends ComponentProviderAdapter {
setApplyEnabled(false);
}
/* (non-Javadoc)
* @see ghidra.util.bean.GhidraDialog#cancelCallback()
*/
void cancelCallback(boolean force) {
if (force ||
CancelMergeDialog.showYesNoDialog(mainPanel, WARNING_ICON) == OptionDialog.OPTION_ONE) {
boolean cancel = force;
if (!force) {
int choice =
OptionDialog.showYesNoDialogWithNoAsDefaultButton(null, "Confirm Cancel Merge",
"Warning! Cancel causes the entire merge process to be canceled.\n" +
"Do you want to cancel the Merge Process?");
cancel = choice == OptionDialog.OPTION_ONE;
}
if (cancel) {
wasCanceled = true;
MergeManager mergeManager = plugin.getMergeManager();
if (mergeManager != null) {
@ -231,22 +231,12 @@ class MergeManagerProvider extends ComponentProviderAdapter {
private JPanel createButtonPanel() {
applyButton = new JButton("Apply");
applyButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
applyCallback();
}
});
applyButton.addActionListener(e -> applyCallback());
applyButton.setEnabled(false);
applyButton.setToolTipText("Apply conflict resolution");
cancelButton = new JButton("Cancel");
cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
cancelCallback(false);
}
});
cancelButton.addActionListener(e -> cancelCallback(false));
JPanel panel = ButtonPanelFactory.createButtonPanel(
new JButton[] { applyButton, cancelButton }, ButtonPanelFactory.X_AXIS);

View file

@ -16,7 +16,6 @@
package ghidra.app.plugin.core.analysis;
import java.awt.BorderLayout;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
@ -37,7 +36,7 @@ import ghidra.program.model.lang.LanguageID;
import ghidra.program.model.listing.Program;
import ghidra.program.util.GhidraProgramUtilities;
import ghidra.util.HTMLUtilities;
import ghidra.util.Msg;
import ghidra.util.Swing;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.*;
@ -171,30 +170,17 @@ class AnalyzeAllOpenProgramsTask extends Task {
}
private boolean setOptions(final Program program, AutoAnalysisManager mgr) {
final AtomicBoolean analyze = new AtomicBoolean();
AtomicBoolean analyze = new AtomicBoolean();
int id = program.startTransaction("analysis");
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
AnalysisOptionsDialog dialog =
new AnalysisOptionsDialog(getValidProgramsByArchitecture());
tool.showDialog(dialog);
boolean shouldAnalyze = dialog.wasAnalyzeButtonSelected();
analyze.set(shouldAnalyze);
}
Swing.runNow(() -> {
AnalysisOptionsDialog dialog =
new AnalysisOptionsDialog(getValidProgramsByArchitecture());
tool.showDialog(dialog);
boolean shouldAnalyze = dialog.wasAnalyzeButtonSelected();
analyze.set(shouldAnalyze);
});
}
catch (InterruptedException e) {
// shouldn't happen
Msg.debug(this, "Unexpected exception", e);
return false;
}
catch (InvocationTargetException e) {
// shouldn't happen
Msg.debug(this, "Unexpected exception", e);
return false;
}
finally {
program.endTransaction(id, true);
}
@ -338,10 +324,10 @@ class AnalyzeAllOpenProgramsTask extends Task {
buffy.append("</TABLE>");
OptionDialog dialog = new ScrollingOptionDialog("Found Differing Architectures--Continue?",
buffy.toString(), "Continue", OptionDialog.WARNING_MESSAGE);
dialog.show(null);
return dialog.getResult() == OptionDialog.OPTION_ONE;
return Swing.runNow(() -> {
ScrollingOptionDialog dialog = new ScrollingOptionDialog(buffy.toString());
return dialog.shouldContinue();
});
}
//==================================================================================================
@ -495,9 +481,16 @@ class AnalyzeAllOpenProgramsTask extends Task {
private class ScrollingOptionDialog extends OptionDialog {
public ScrollingOptionDialog(String title, String message, String option1,
int messageType) {
super(title, message, option1, messageType, null);
public ScrollingOptionDialog(String message) {
super("Found Differing Architectures", message, "Continue",
OptionDialog.WARNING_MESSAGE, null);
}
boolean shouldContinue() {
return Swing.runNow(() -> {
show(null);
return getResult() == OptionDialog.OPTION_ONE;
});
}
@Override

View file

@ -28,7 +28,6 @@ import ghidra.program.model.address.Address;
import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.Reference;
import ghidra.util.HelpLocation;
import ghidra.util.SystemUtilities;
/**
* <CODE>SetStackDepthChangeAction</CODE> allows the user to set a stack depth change value
@ -172,14 +171,8 @@ class SetStackDepthChangeAction extends ListingContextAction {
currentAddress.toString() + ".";
// @formatter:on
final OptionDialog dialog = new OptionDialog("Stack Depth Change or Function Purge?",
message, "Local", "Global", OptionDialog.QUESTION_MESSAGE,
OptionDialog.getIconForMessageType(OptionDialog.QUESTION_MESSAGE), true);
dialog.setHelpLocation(new HelpLocation(funcPlugin.getName(), "Set_Stack_Depth_Change"));
Runnable r = () -> tool.showDialog(dialog);
SystemUtilities.runSwingNow(r);
StackChangeOptionDialog dialog = new StackChangeOptionDialog(message);
dialog.show();
return dialog.getResult();
}
@ -198,4 +191,13 @@ class SetStackDepthChangeAction extends ListingContextAction {
return true;
}
private class StackChangeOptionDialog extends OptionDialog {
StackChangeOptionDialog(String message) {
super("Stack Depth Change or Function Purge?", message, "Local", "Global",
OptionDialog.QUESTION_MESSAGE, null, true);
setHelpLocation(new HelpLocation(funcPlugin.getName(), "Set_Stack_Depth_Change"));
}
}
}

View file

@ -20,6 +20,8 @@ import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.*;
import javax.swing.JComponent;
import org.jdom.Element;
import docking.ComponentProvider;
@ -820,14 +822,11 @@ public class ReferencesPlugin extends Plugin {
curType = "Memory reference(s)";
}
OptionDialog confirmDlg = new OptionDialog("Reference Removal Confirmation",
JComponent parent = editRefDialog.getComponent();
int choice = OptionDialog.showOptionDialog(parent, "Reference Removal Confirmation",
"Warning! existing " + curType + " will be removed.", "Continue",
OptionDialog.WARNING_MESSAGE,
OptionDialog.getIconForMessageType(OptionDialog.WARNING_MESSAGE));
confirmDlg.setRememberLocation(false);
confirmDlg.setRememberSize(false);
tool.showDialog(confirmDlg, editRefDialog.getComponent());
return (confirmDlg.getResult() != OptionDialog.CANCEL_OPTION);
OptionDialog.WARNING_MESSAGE);
return (choice != OptionDialog.CANCEL_OPTION);
}
@Override

View file

@ -18,7 +18,6 @@ package ghidra.app.util.task;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import docking.widgets.OptionDialog;
import ghidra.app.util.dialog.CheckoutDialog;
@ -259,16 +258,10 @@ public class OpenProgramTask extends Task {
private boolean askRecoverFile(final String filename) {
final AtomicBoolean result = new AtomicBoolean();
SystemUtilities.runSwingNow(() -> {
int option = OptionDialog.showYesNoDialog(null, "Crash Recovery Data Found",
"<html>" + HTMLUtilities.escapeHTML(filename) + " has crash data.<br>" +
"Would you like to recover unsaved changes?");
result.set(option == OptionDialog.OPTION_ONE);
});
return result.get();
int option = OptionDialog.showYesNoDialog(null, "Crash Recovery Data Found",
"<html>" + HTMLUtilities.escapeHTML(filename) + " has crash data.<br>" +
"Would you like to recover unsaved changes?");
return option == OptionDialog.OPTION_ONE;
}
private void performOptionalCheckout(DomainFile domainFile) {

View file

@ -19,6 +19,7 @@ import java.awt.Component;
import java.awt.Window;
import java.io.*;
import docking.widgets.OkDialog;
import docking.widgets.OptionDialog;
import ghidra.util.*;
import ghidra.util.exception.MultipleCauses;
@ -97,7 +98,7 @@ public class DockingErrorDisplay implements ErrorDisplay {
dialog = createErrorDialog(title, message, throwable, messageString);
}
else {
dialog = new OptionDialog(title, messageString, dialogType, null);
dialog = new OkDialog(title, messageString, dialogType);
}
DockingWindowManager.showDialog(parent, dialog);
}

View file

@ -32,7 +32,6 @@ public class DialogRememberOption {
* Constructs a new DialogRememberOption for use in an OptionDialog for adding an
* "Apply to all", "Remember my decision", etc. checkBox.
* @param description the checkBox text (e.g. "Apply to all")
* @param defaultState the default state of the checkBox. (This almost always false.)
*/
public DialogRememberOption(String description) {
this.description = description;
@ -57,8 +56,8 @@ public class DialogRememberOption {
/**
* Returns true if a previous call to the dialog was remembered (The user selected the
* checkBox.)
* @return
* checkBox)
* @return true if a previous call to the dialog was remembered
*/
public boolean hasRememberedResult() {
return hasRememberedResult;
@ -72,12 +71,10 @@ public class DialogRememberOption {
* "shown", if there is a saved result, it will be returned
* instead of actually showing the dialog.
*
* @param choice the boolean state of the checkBox.
* @param rememberedResult the users result from the OptionDialog.
* @param choice the user's choice from the OptionDialog
*/
public void rememberResult(int rememberedResult) {
public void rememberResult(int choice) {
this.hasRememberedResult = true;
this.rememberedResult = rememberedResult;
this.rememberedResult = choice;
}
}

View file

@ -0,0 +1,93 @@
/* ###
* 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 docking.widgets;
import javax.swing.Icon;
import ghidra.util.Swing;
/**
* A dialog with an OK button. The client can specify the message type in the constructor.
*/
public class OkDialog extends OptionDialog {
/**
* Show a {@link OptionDialog#PLAIN_MESSAGE plain} {@link OkDialog} with the given title and message
* @param title the title
* @param message the message
*/
public static void show(String title, String message) {
Swing.runNow(() -> {
new OkDialog(title, message, OptionDialog.PLAIN_MESSAGE).show();
});
}
/**
* Show a {@link OptionDialog#INFORMATION_MESSAGE plain} {@link OkDialog} with the given
* title and message
*
* @param title the title
* @param message the message
*/
public static void showInfo(String title, String message) {
Swing.runNow(() -> {
new OkDialog(title, message, OptionDialog.INFORMATION_MESSAGE).show();
});
}
/**
* Show a {@link OptionDialog#ERROR_MESSAGE plain} {@link OkDialog} with the given
* title and message
*
* @param title the title
* @param message the message
*/
public static void showError(String title, String message) {
Swing.runNow(() -> {
new OkDialog(title, message, OptionDialog.ERROR_MESSAGE).show();
});
}
/**
* Construct a simple informational dialog with a single OK button
*
* @param title The String to be placed in the dialogs title area
* @param message The information message to be displayed in the dialog
* @param messageType used to specify a default icon
* <ul>
* <li>ERROR_MESSAGE</li>
* <li>INFORMATION_MESSAGE</li>
* <li>WARNING_MESSAGE</li>
* <li>QUESTION_MESSAGE</li>
* <li>PLAIN_MESSAGE</li>
* </ul>
*/
public OkDialog(String title, String message, int messageType) {
super(title, message, messageType, null);
}
/**
* Construct a simple informational dialog with a single OK button
*
* @param title The String to be placed in the dialogs title area
* @param message The information message to be displayed in the dialog
* @param icon allows the user to specify the icon to be used
* If non-null, this will override the messageType
*/
public OkDialog(String title, String message, Icon icon) {
super(title, message, PLAIN_MESSAGE, icon);
}
}

View file

@ -28,8 +28,7 @@ import docking.widgets.checkbox.GCheckBox;
import docking.widgets.dialogs.*;
import docking.widgets.label.GHtmlLabel;
import docking.widgets.label.GIconLabel;
import ghidra.util.HTMLUtilities;
import ghidra.util.Msg;
import ghidra.util.*;
import ghidra.util.exception.AssertException;
/**
@ -37,6 +36,7 @@ import ghidra.util.exception.AssertException;
*
*
* <h3>Option Dialogs</h3><br>
* <blockquote>
* <p>
* The primary type of
* dialog provided herein is the basic option dialog that allows the user to specify the buttons
@ -50,39 +50,53 @@ import ghidra.util.exception.AssertException;
* Each of the option dialog methods will return a result, which is a number indicating the
* choice made by the user. See each method for more details.
* </p>
* </blockquote>
*
*
* <h3>Data Input and Choice Dialogs</h3><br>
* <p>
* The methods listed here allow the user to either enter data from the keyboard or to choose
* from a pre-populated list of data.
* </p>
* <blockquote>
* {@link #showInputChoiceDialog(Component, String, String, String[], String, int)}<br>
* {@link #showInputMultilineDialog(Component, String, String, String)}<br>
* {@link #showInputSingleLineDialog(Component, String, String, String)}
* <p>
* The methods listed here allow the user to either enter data from the keyboard or to choose
* from a pre-populated list of data.
* </p>
* <blockquote>
* {@link #showInputChoiceDialog(Component, String, String, String[], String, int)}<br>
* {@link #showInputMultilineDialog(Component, String, String, String)}<br>
* {@link #showInputSingleLineDialog(Component, String, String, String)}
* </blockquote>
* </blockquote>
*
*
* <h3>Yes/No Dialogs</h3><br>
* <blockquote>
* <p>
* Finally, there are a series of methods that present <tt>Yes</tt> and <tt>No</tt> buttons in
* a dialog. There are versions that do and do not have a <tt>Cancel</tt> button.
* </p>
* </blockquote>
*
*
* <h3>Basic Message / Warning / Error Dialogs</h3><br>
* <blockquote>
* <p>
* If you would like to display a simple message to the user, but do not require input from the
* user, then you should use the various methods of {@link Msg}, such as
* {@link Msg#showInfo(Object, Component, String, Object)}.
* </p>
*
* <p>
* Note, the user will be unable to select any text shown in the message area of the dialog.
* </p>
* </blockquote>
*
* <h3>"Apply to All" / "Don't Show Again"</h3><br>
* <blockquote>
* <p>For more advanced input dialog usage, to include allowing the user to tell the dialog
* to remember a particular decision, or to apply a given choice to all future request, see
* {@link OptionDialogBuilder}.
* </blockquote>
*
* @see Msg
* @see OptionDialogBuilder
*/
public class OptionDialog extends DialogComponentProvider {
private static final String MESSAGE_COMPONENT_NAME = "MESSAGE-COMPONENT";
@ -141,7 +155,7 @@ public class OptionDialog extends DialogComponentProvider {
* @param icon allows the user to specify the icon to be used.
* If non-null, this will override the messageType.
*/
public OptionDialog(String title, String message, int messageType, Icon icon) {
protected OptionDialog(String title, String message, int messageType, Icon icon) {
this(title, message, null, null, messageType, icon, false, null);
}
@ -157,7 +171,7 @@ public class OptionDialog extends DialogComponentProvider {
* this will override the messageType.
* @param addCancel true means add a Cancel button
*/
public OptionDialog(String title, String message, String option1, String option2,
protected OptionDialog(String title, String message, String option1, String option2,
int messageType, Icon icon, boolean addCancel) {
super(title, true, false, true, false);
buildMainPanel(message, messageType, icon, null);
@ -175,12 +189,9 @@ public class OptionDialog extends DialogComponentProvider {
* @param icon allows the user to specify the icon to be used. If non-null,
* this will override the messageType.
* @param addCancel true means add a Cancel button
* @param int The index of the button that should be the default button (the one that is
* executed when the user presses the Enter key):<br>
* 1 for button 1; 2 for button 2 and 3 for button 3 (if applicable)
* @param defaultButtonName The default button name
*/
public OptionDialog(String title, String message, String option1, String option2,
protected OptionDialog(String title, String message, String option1, String option2,
int messageType, Icon icon, boolean addCancel, String defaultButtonName) {
super(title, true, false, true, false);
buildMainPanel(message, messageType, icon, null);
@ -197,7 +208,8 @@ public class OptionDialog extends DialogComponentProvider {
* @param icon allows the user to specify the icon to be used. If non-null,
* this will override the messageType.
*/
public OptionDialog(String title, String message, String option1, int messageType, Icon icon) {
protected OptionDialog(String title, String message, String option1, int messageType,
Icon icon) {
this(title, message, option1, null, messageType, icon, true, null);
}
@ -212,14 +224,12 @@ public class OptionDialog extends DialogComponentProvider {
* this will override the messageType.
* @param defaultButtonName the name of the button to be made the default.
*/
public OptionDialog(String title, String message, String option1, int messageType, Icon icon,
protected OptionDialog(String title, String message, String option1, int messageType, Icon icon,
String defaultButtonName) {
this(title, message, option1, null, messageType, icon, true, defaultButtonName);
}
////////////////////////////////////////////////////////////////////////////
/** Special 3 button constructor */
/* Special 3 button constructor */
protected OptionDialog(String title, String message, String option1, String option2,
String option3, int messageType, Icon icon, boolean addCancel) {
super(title, true, false, true, false);
@ -287,8 +297,6 @@ public class OptionDialog extends DialogComponentProvider {
return panel;
}
////////////////////////////////////////////////////////////////////////////
private void buildButtons(List<String> options, boolean addCancel, String defaultButtonName) {
List<JButton> buttons = new ArrayList<>();
@ -340,7 +348,7 @@ public class OptionDialog extends DialogComponentProvider {
"No button exists to make default for name: " + defaultButtonName);
}
JButton createOptionButton(String optionName, final int callbackValue) {
private JButton createOptionButton(String optionName, final int callbackValue) {
int ampLoc = optionName.indexOf('&');
char mnemonicKey = '\0';
if (ampLoc >= 0 && ampLoc < optionName.length() - 1) {
@ -375,6 +383,10 @@ public class OptionDialog extends DialogComponentProvider {
return label;
}
/**
* Returns the dialog's message to the user
* @return the message
*/
public String getMessage() {
return dialogMessage;
}
@ -395,6 +407,13 @@ public class OptionDialog extends DialogComponentProvider {
//==================================================================================================
// Show Option Dialog Methods
//==================================================================================================
/**
* A convenience method to create a {@link OptionDialogBuilder}
* @param title the dialog title
* @param message the dialog message
* @return the builder
*/
public static OptionDialogBuilder createBuilder(String title, String message) {
return new OptionDialogBuilder(title, message);
}
@ -439,9 +458,12 @@ public class OptionDialog extends DialogComponentProvider {
*/
public static int showOptionDialogWithCancelAsDefaultButton(Component parent, String title,
String message, String option1) {
OptionDialog info =
new OptionDialog(title, message, option1, QUESTION_MESSAGE, null, "Cancel");
return info.show(parent);
return Swing.runNow(() -> {
OptionDialog info =
new OptionDialog(title, message, option1, QUESTION_MESSAGE, null, "Cancel");
return info.show(parent);
});
}
/**
@ -466,10 +488,14 @@ public class OptionDialog extends DialogComponentProvider {
*/
public static int showOptionDialogWithCancelAsDefaultButton(Component parent, String title,
String message, String option1, int messageType) {
String defaultButton = option1.equals("Yes") ? "No" : "Cancel";
OptionDialog info =
new OptionDialog(title, message, option1, messageType, null, defaultButton);
return info.show(parent);
return Swing.runNow(() -> {
OptionDialog info =
new OptionDialog(title, message, option1, messageType, null, defaultButton);
return info.show(parent);
});
}
/**
@ -491,8 +517,11 @@ public class OptionDialog extends DialogComponentProvider {
*/
public static int showOptionDialog(Component parent, String title, String message,
String option1, int messageType) {
OptionDialog info = new OptionDialog(title, message, option1, messageType, null);
return info.show(parent);
return Swing.runNow(() -> {
OptionDialog info = new OptionDialog(title, message, option1, messageType, null);
return info.show(parent);
});
}
/**
@ -516,9 +545,12 @@ public class OptionDialog extends DialogComponentProvider {
*/
public static int showOptionDialog(Component parent, String title, String message,
String option1, int messageType, String defaultButtonName) {
OptionDialog info =
new OptionDialog(title, message, option1, messageType, null, defaultButtonName);
return info.show(parent);
return Swing.runNow(() -> {
OptionDialog info =
new OptionDialog(title, message, option1, messageType, null, defaultButtonName);
return info.show(parent);
});
}
/**
@ -540,8 +572,11 @@ public class OptionDialog extends DialogComponentProvider {
*/
public static int showOptionDialog(Component parent, String title, String message,
String option1, Icon icon) {
OptionDialog info = new OptionDialog(title, message, option1, PLAIN_MESSAGE, icon);
return info.show(parent);
return Swing.runNow(() -> {
OptionDialog info = new OptionDialog(title, message, option1, PLAIN_MESSAGE, icon);
return info.show(parent);
});
}
/**
@ -563,9 +598,12 @@ public class OptionDialog extends DialogComponentProvider {
*/
public static int showOptionDialog(Component parent, String title, String message,
String option1, String option2, String option3, int messageType) {
OptionDialog dialog =
new OptionDialog(title, message, option1, option2, option3, messageType, null, true);
return dialog.show(parent);
return Swing.runNow(() -> {
OptionDialog dialog = new OptionDialog(title, message, option1, option2, option3,
messageType, null, true);
return dialog.show(parent);
});
}
/**
@ -609,9 +647,12 @@ public class OptionDialog extends DialogComponentProvider {
*/
public static int showOptionDialog(Component parent, String title, String message,
String option1, String option2, int messageType) {
OptionDialog info =
new OptionDialog(title, message, option1, option2, messageType, null, true);
return info.show(parent);
return Swing.runNow(() -> {
OptionDialog info =
new OptionDialog(title, message, option1, option2, messageType, null, true);
return info.show(parent);
});
}
/**
@ -634,9 +675,12 @@ public class OptionDialog extends DialogComponentProvider {
*/
public static int showOptionDialog(Component parent, String title, String message,
String option1, String option2, Icon icon) {
OptionDialog info =
new OptionDialog(title, message, option1, option2, PLAIN_MESSAGE, icon, true);
return info.show(parent);
return Swing.runNow(() -> {
OptionDialog info =
new OptionDialog(title, message, option1, option2, PLAIN_MESSAGE, icon, true);
return info.show(parent);
});
}
/**
@ -659,9 +703,12 @@ public class OptionDialog extends DialogComponentProvider {
*/
public static int showOptionNoCancelDialog(Component parent, String title, String message,
String option1, String option2, int messageType) {
OptionDialog info =
new OptionDialog(title, message, option1, option2, messageType, null, false);
return info.show(parent);
return Swing.runNow(() -> {
OptionDialog info =
new OptionDialog(title, message, option1, option2, messageType, null, false);
return info.show(parent);
});
}
/**
@ -685,9 +732,11 @@ public class OptionDialog extends DialogComponentProvider {
public static int showOptionNoCancelDialog(Component parent, String title, String message,
String option1, String option2, Icon icon) {
OptionDialog info =
new OptionDialog(title, message, option1, option2, PLAIN_MESSAGE, icon, false);
return info.show();
return Swing.runNow(() -> {
OptionDialog info =
new OptionDialog(title, message, option1, option2, PLAIN_MESSAGE, icon, false);
return info.show();
});
}
/**
@ -713,9 +762,11 @@ public class OptionDialog extends DialogComponentProvider {
public static int showOptionNoCancelDialog(Component parent, String title, String message,
String option1, String option2, String option3, int messageType) {
OptionDialog info =
new OptionDialog(title, message, option1, option2, option3, messageType, null, false);
return info.show();
return Swing.runNow(() -> {
OptionDialog info = new OptionDialog(title, message, option1, option2, option3,
messageType, null, false);
return info.show();
});
}
/**
@ -725,9 +776,11 @@ public class OptionDialog extends DialogComponentProvider {
* @param title The String to be placed in the dialogs title area.
* @param message The information message to be displayed in the dialog.
* @return The options selected by the user:
* <pre>
* 0 is returned if the operation is cancelled
* 1 for <b>Yes</b>
* 2 for <b>No</b>
* </pre>
*/
public static int showYesNoDialog(Component parent, String title, String message) {
return showOptionNoCancelDialog(parent, title, message, "&Yes", "&No", QUESTION_MESSAGE);
@ -747,14 +800,19 @@ public class OptionDialog extends DialogComponentProvider {
* @param title The String to be placed in the dialogs title area.
* @param message The information message to be displayed in the dialog.
* @return The options selected by the user:
* <pre>
* 1 for <b>Yes</b>
* 2 for <b>No</b>
* </pre>
*/
public static int showYesNoDialogWithNoAsDefaultButton(Component parent, String title,
String message) {
OptionDialog info =
new OptionDialog(title, message, "&Yes", "&No", QUESTION_MESSAGE, null, false, "No");
return info.show(parent);
return Swing.runNow(() -> {
OptionDialog info = new OptionDialog(title, message, "&Yes", "&No", QUESTION_MESSAGE,
null, false, "No");
return info.show(parent);
});
}
/**
@ -768,9 +826,11 @@ public class OptionDialog extends DialogComponentProvider {
* @param title The String to be placed in the dialogs title area.
* @param message The information message to be displayed in the dialog.
* @return The options selected by the user:
* <pre>
* 0 is returned if the operation is cancelled
* 1 for the first option
* 2 for the second option
* </pre>
*/
public static int showYesNoCancelDialog(Component parent, String title, String message) {
return showOptionDialog(parent, title, message, "&Yes", "&No", QUESTION_MESSAGE);
@ -787,18 +847,22 @@ public class OptionDialog extends DialogComponentProvider {
*/
public static String showInputSingleLineDialog(Component parent, String title, String label,
String initialValue) {
InputDialog dialog = new InputDialog(title, label, initialValue, true);
// Apply similar settings to that of the OptionDialog, for consistency
dialog.setRememberLocation(false);
dialog.setRememberSize(false);
return Swing.runNow(() -> {
DockingWindowManager.showDialog(parent, dialog);
InputDialog dialog = new InputDialog(title, label, initialValue, true);
if (dialog.isCanceled()) {
return null;
}
return dialog.getValue();
// Apply similar settings to that of the OptionDialog, for consistency
dialog.setRememberLocation(false);
dialog.setRememberSize(false);
DockingWindowManager.showDialog(parent, dialog);
if (dialog.isCanceled()) {
return null;
}
return dialog.getValue();
});
}
/**
@ -812,14 +876,19 @@ public class OptionDialog extends DialogComponentProvider {
*/
public static String showInputMultilineDialog(Component parent, String title, String label,
String initialValue) {
Icon icon = getIconForMessageType(QUESTION_MESSAGE);
MultiLineInputDialog dialog = new MultiLineInputDialog(title, label, initialValue, icon);
DockingWindowManager.showDialog(parent, dialog);
if (dialog.isCanceled()) {
return null;
}
return dialog.getValue();
return Swing.runNow(() -> {
Icon icon = getIconForMessageType(QUESTION_MESSAGE);
MultiLineInputDialog dialog =
new MultiLineInputDialog(title, label, initialValue, icon);
DockingWindowManager.showDialog(parent, dialog);
if (dialog.isCanceled()) {
return null;
}
return dialog.getValue();
});
}
/**
@ -839,16 +908,19 @@ public class OptionDialog extends DialogComponentProvider {
public static String showInputChoiceDialog(Component parent, String title, String label,
String[] selectableValues, String initialValue, int messageType) {
Icon icon = getIconForMessageType(messageType);
return Swing.runNow(() -> {
InputWithChoicesDialog dialog =
new InputWithChoicesDialog(title, label, selectableValues, initialValue, icon);
DockingWindowManager.showDialog(parent, dialog);
Icon icon = getIconForMessageType(messageType);
if (dialog.isCanceled()) {
return null;
}
return dialog.getValue();
InputWithChoicesDialog dialog =
new InputWithChoicesDialog(title, label, selectableValues, initialValue, icon);
DockingWindowManager.showDialog(parent, dialog);
if (dialog.isCanceled()) {
return null;
}
return dialog.getValue();
});
}
/**
@ -871,14 +943,17 @@ public class OptionDialog extends DialogComponentProvider {
Icon icon = getIconForMessageType(messageType);
InputWithChoicesDialog dialog =
new InputWithChoicesDialog(title, label, selectableValues, initialValue, true, icon);
DockingWindowManager.showDialog(parent, dialog);
return Swing.runNow(() -> {
InputWithChoicesDialog dialog = new InputWithChoicesDialog(title, label,
selectableValues, initialValue, true, icon);
DockingWindowManager.showDialog(parent, dialog);
if (dialog.isCanceled()) {
return null;
}
return dialog.getValue();
if (dialog.isCanceled()) {
return null;
}
return dialog.getValue();
});
}
/**

View file

@ -21,6 +21,8 @@ import java.util.List;
import javax.swing.Icon;
import ghidra.util.Swing;
/**
* Class for creating OptionDialogs using the builder pattern.
*
@ -45,8 +47,8 @@ import javax.swing.Icon;
* "no" as the defaultOption.
*
* <P>You can also add a Cancel button, which will return a result of 0 if pressed. Note that this
* is different than adding an option named "Cancel" which would return a result > 0, depending
* on where in the order it was added.
* is different than adding an option named "Cancel" which would return a result greater than
* <code>0</code>, depending on where in the order it was added.
*
* <P><a name="RememberOption"></a>A "Remember Option" can be added to OptionDialog to
* present the user with a choice for remembering a dialog result and automatically
@ -82,9 +84,6 @@ public class OptionDialogBuilder {
* this constructor is used, then both {@link #setTitle(String)} and the
* {@link #setMessage(String)} methods must be called
* or else the dialog will have no title or message.
*
* @param title the title of the dialog.
* @param message the main message to be displayed in the dialog.
*/
public OptionDialogBuilder() {
this(null, null);
@ -95,8 +94,7 @@ public class OptionDialogBuilder {
* this constructor is used, then the {@link #setMessage(String)} method must be called
* or else the dialog will be blank.
*
* @param title the title of the dialog.
* @param message the main message to be displayed in the dialog.
* @param title the title of the dialog
*/
public OptionDialogBuilder(String title) {
this(title, null);
@ -243,8 +241,10 @@ public class OptionDialogBuilder {
* @return an OptionDialog built based on the values set in this builder.
*/
public OptionDialog build() {
return new OptionDialog(title, message, messageType, icon, addCancelButton,
rememberOption, options, defaultOption);
return Swing.runNow(() -> {
return new OptionDialog(title, message, messageType, icon, addCancelButton,
rememberOption, options, defaultOption);
});
}
/**
@ -266,6 +266,7 @@ public class OptionDialogBuilder {
if (rememberOption != null && rememberOption.hasRememberedResult()) {
return rememberOption.getRememberedResult();
}
OptionDialog dialog = build();
dialog.show(parent);
return dialog.getResult();

View file

@ -85,19 +85,8 @@ public class DefaultClientAuthenticator extends PopupKeyStorePasswordProvider
@Override
public boolean promptForReconnect(final Component parent, final String message) {
final boolean[] retVal = new boolean[] { false };
Runnable r = () -> {
String msg = message;
if (msg != null) {
msg = msg + "\n";
}
msg = msg + "Do you want to reconnect to the server now?";
retVal[0] = OptionDialog.showYesNoDialog(parent, "Lost Connection to Server",
message) == OptionDialog.OPTION_ONE;
};
SystemUtilities.runSwingNow(r);
return retVal[0];
return OptionDialog.showYesNoDialog(parent, "Lost Connection to Server",
message) == OptionDialog.OPTION_ONE;
}
@Override

View file

@ -31,6 +31,7 @@ import org.jdom.output.XMLOutputter;
import docking.*;
import docking.action.DockingAction;
import docking.action.MenuData;
import docking.widgets.OkDialog;
import docking.widgets.OptionDialog;
import docking.widgets.dialogs.InputDialog;
import docking.widgets.filechooser.GhidraFileChooser;
@ -369,23 +370,23 @@ public class FrontEndPlugin extends Plugin
"\nserver may be forced to close as a result.";
// @formatter:on
OptionDialog info = new OptionDialog("Ghidra Server Error", message,
OptionDialog.PLAIN_MESSAGE, DISCONNECTED_ICON);
OkDialog info = new OkDialog("Ghidra Server Error", message, DISCONNECTED_ICON);
info.show(tool.getToolFrame());
}
/**
* Set the project manager; try to reopen the last project that was
* opened.
* @param pm
* @param pm the project manager
*/
void setProjectManager(ProjectManager pm) {
this.projectManager = pm;
}
/**
* sets the handle to the activeProject, as well as updating the
* Sets the handle to the activeProject, as well as updating the
* active data tree to show the new active project's data
* @param project the active project
*/
void setActiveProject(Project project) {

View file

@ -17,7 +17,6 @@ package ghidra.util;
import java.awt.Component;
import docking.DockingWindowManager;
import docking.widgets.OptionDialog;
import ghidra.framework.model.DomainFile;
import ghidra.util.exception.VersionException;
@ -57,16 +56,14 @@ public class VersionExceptionHandler {
private static void showNeedExclusiveCheckoutDialog(final Component parent, String filename,
String contentType, String actionName) {
final OptionDialog dialog = new OptionDialog(actionName + " Failed!",
Msg.showError(VersionExceptionHandler.class, parent, actionName + " Failed!",
"Unable to " + actionName + " " + contentType + ": " + filename + "\n \n" +
"An upgrade of the " + contentType +
" data is required, however, you must have an exclusive checkout\n" +
"to upgrade a shared file!\n \n" +
"NOTE: If you are unable to obtain an exclusive checkout, you may be able to " +
actionName + "\nthe file with an older version of Ghidra.",
OptionDialog.ERROR_MESSAGE,
OptionDialog.getIconForMessageType(OptionDialog.ERROR_MESSAGE));
DockingWindowManager.showDialog(parent, dialog);
actionName + "\nthe file with an older version of Ghidra.");
}
private static int showUpgradeDialog(final Component parent, VersionException ve,
@ -74,28 +71,23 @@ public class VersionExceptionHandler {
final String detailMessage =
ve.getDetailMessage() == null ? "" : "\n" + ve.getDetailMessage();
OptionDialog dialog = new OptionDialog("Upgrade " + contentType + " Data? " + filename,
"The " + contentType + " file you are attempting to " + actionName +
" is an older version." + detailMessage + "\n \n" +
"Would you like to Upgrade it now?",
"Upgrade", "Cancel", OptionDialog.QUESTION_MESSAGE,
OptionDialog.getIconForMessageType(OptionDialog.QUESTION_MESSAGE), false);
DockingWindowManager.showDialog(parent, dialog);
return dialog.getResult();
String title = "Upgrade " + contentType + " Data? " + filename;
String message = "The " + contentType + " file you are attempting to " + actionName +
" is an older version." + detailMessage + "\n \n" + "Would you like to Upgrade it now?";
return OptionDialog.showOptionDialog(parent, title, message, "Upgrade",
OptionDialog.QUESTION_MESSAGE);
}
private static int showWarningDialog(final Component parent, String filename,
String contentType, String actionName) {
final OptionDialog dialog = new OptionDialog(
"Upgrade Shared " + contentType + " Data? " + filename,
"This " + contentType +
" file is shared with other users. If you upgrade this file,\n" +
"other users will not be able to read the new version until they upgrade to \n" +
"the same version of Ghidra. Do you want to continue?",
"Upgrade", "Cancel", OptionDialog.WARNING_MESSAGE,
OptionDialog.getIconForMessageType(OptionDialog.WARNING_MESSAGE), false);
DockingWindowManager.showDialog(parent, dialog);
return dialog.getResult();
String title = "Upgrade Shared " + contentType + " Data? " + filename;
String message = "This " + contentType +
" file is shared with other users. If you upgrade this file,\n" +
"other users will not be able to read the new version until they upgrade to \n" +
"the same version of Ghidra. Do you want to continue?";
return OptionDialog.showOptionDialog(parent, title, message, "Upgrade",
OptionDialog.WARNING_MESSAGE);
}
public static void showVersionError(final Component parent, final String filename,

View file

@ -28,8 +28,7 @@ import org.junit.Test;
import docking.DialogComponentProvider;
import docking.DockingDialog;
import docking.widgets.OptionDialog;
import docking.widgets.PasswordChangeDialog;
import docking.widgets.*;
import docking.widgets.filechooser.GhidraFileChooser;
import docking.widgets.table.GTable;
import docking.wizard.WizardManager;
@ -120,8 +119,7 @@ public class FrontEndPluginScreenShots extends GhidraScreenShotGenerator {
new PasswordChangeDialog("Change Password", "Repository Server", "server1", "user-1");
runSwing(() -> tool.showDialog(pcd), false);
PasswordChangeDialog dialog =
waitForDialogComponent(null, PasswordChangeDialog.class, DEFAULT_WINDOW_TIMEOUT);
PasswordChangeDialog dialog = waitForDialogComponent(PasswordChangeDialog.class);
captureDialog(dialog);
}
@ -353,11 +351,8 @@ public class FrontEndPluginScreenShots extends GhidraScreenShotGenerator {
@Test
public void testProjectExists() {
final OptionDialog dialog = new OptionDialog("Project Exists",
"Cannot restore project because project named " + "TestPrj" + " already exists.",
OptionDialog.PLAIN_MESSAGE, null);
runSwing(() -> tool.showDialog(dialog), false);
OkDialog.show("Project Exists",
"Cannot restore project because project named TestPrj already exists.");
captureDialog();
}
@ -689,7 +684,7 @@ public class FrontEndPluginScreenShots extends GhidraScreenShotGenerator {
}
private void waitForVMMemoryInitialilzed() {
Window w = waitForWindow("VM Memory Usage", 2000);
Window w = waitForWindow("VM Memory Usage");
DialogComponentProvider dc = ((DockingDialog) w).getDialogComponent();
Boolean initialized = (Boolean) invokeInstanceMethod("isInitialized", dc);

View file

@ -21,13 +21,13 @@ import org.junit.Test;
import docking.DockingWindowManager;
import docking.ErrLogDialog;
import docking.widgets.OptionDialog;
import docking.widgets.OkDialog;
import ghidra.framework.model.Project;
import ghidra.framework.model.ProjectData;
import ghidra.util.InvalidNameException;
import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitorAdapter;
import ghidra.util.task.TaskMonitor;
public class IntroScreenShots extends GhidraScreenShotGenerator {
@ -45,55 +45,42 @@ public class IntroScreenShots extends GhidraScreenShotGenerator {
// don't need to load a program
}
@Test
public void testEmpty_ghidra() {
@Test
public void testEmpty_ghidra() {
performAction("Close Project", "FrontEndPlugin", true);
Msg.info("RecoverySnapshotMgrPlugin", "Recovery snapshot timer set to 5 minute(s)");
captureToolWindow(600, 500);
}
@Test
public void testErr_Dialog() {
runSwing(new Runnable() {
@Override
public void run() {
ErrLogDialog dialog =
ErrLogDialog.createLogMessageDialog("Unexpected Error",
"Oops, this is really bad!", "");
DockingWindowManager.showDialog(null, dialog);
}
@Test
public void testErr_Dialog() {
runSwing(() -> {
ErrLogDialog dialog = ErrLogDialog.createLogMessageDialog("Unexpected Error",
"Oops, this is really bad!", "");
DockingWindowManager.showDialog(null, dialog);
}, false);
waitForSwing();
captureDialog();
}
@Test
public void testOpen_ghidra() throws InvalidNameException, CancelledException, IOException {
@Test
public void testOpen_ghidra() throws InvalidNameException, CancelledException, IOException {
program = env.getProgram("WinHelloCPP.exe");
Project project = env.getProject();
ProjectData projectData = project.getProjectData();
projectData.getRootFolder().createFile("WinHelloCpp.exe", program,
TaskMonitorAdapter.DUMMY_MONITOR);
projectData.getRootFolder().createFile("AnotherProgram.exe", program,
TaskMonitorAdapter.DUMMY_MONITOR);
projectData.getRootFolder().createFile("WinHelloCpp.exe", program, TaskMonitor.DUMMY);
projectData.getRootFolder().createFile("AnotherProgram.exe", program, TaskMonitor.DUMMY);
waitForSwing();
Msg.info("ProjectImpl", "Opening project: " + tool.getProject().getName());
captureToolWindow(600, 500);
}
@Test
public void testSimple_err_dialog() {
runSwing(new Runnable() {
@Override
public void run() {
OptionDialog dialog =
new OptionDialog("Some Resonable Error",
"Your operation did not complete because... (i.e File Not Found)",
OptionDialog.ERROR_MESSAGE, null);
DockingWindowManager.showDialog(null, dialog);
}
}, false);
@Test
public void testSimple_err_dialog() {
OkDialog.showError("Some Resonable Error",
"Your operation did not complete because... (i.e File Not Found)");
captureDialog();
}