mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
GP-628 - Dialogs - test of greatly simplified parenting code
This commit is contained in:
parent
d8166ff6ec
commit
b956870432
13 changed files with 242 additions and 174 deletions
|
@ -203,7 +203,7 @@ public abstract class AbstractToolSavingTest extends AbstractGhidraHeadedIntegra
|
|||
PluginTool[] tools = activeWorkspace.getTools();
|
||||
List<PluginTool> pluginToolList = new ArrayList<>(tools.length);
|
||||
for (PluginTool tool : tools) {
|
||||
pluginToolList.add((PluginTool) tool);
|
||||
pluginToolList.add(tool);
|
||||
}
|
||||
return pluginToolList;
|
||||
}
|
||||
|
@ -234,13 +234,9 @@ public abstract class AbstractToolSavingTest extends AbstractGhidraHeadedIntegra
|
|||
protected Map<String, Object> getOptionsMap(PluginTool tool) {
|
||||
Map<String, Object> map = new TreeMap<>();
|
||||
Options[] options = tool.getOptions();
|
||||
|
||||
for (Options option : options) {
|
||||
String optionsName = option.getName();
|
||||
|
||||
if (optionsName.equals("Key Bindings")) {
|
||||
Msg.debug(this, "break");
|
||||
}
|
||||
|
||||
List<String> optionNames = option.getOptionNames();
|
||||
for (String name : optionNames) {
|
||||
Object value = invokeInstanceMethod("getObject", option,
|
||||
|
@ -277,7 +273,12 @@ public abstract class AbstractToolSavingTest extends AbstractGhidraHeadedIntegra
|
|||
}
|
||||
|
||||
protected PluginTool launchTool(String toolName) {
|
||||
return testEnv.launchTool(toolName, null);
|
||||
PluginTool tool = testEnv.launchTool(toolName, null);
|
||||
|
||||
// There is some delayed options registration that causes sporadic test failures. Waiting
|
||||
// for swing here seems to fix that.
|
||||
waitForSwing();
|
||||
return tool;
|
||||
}
|
||||
|
||||
protected void dumpToolFile(String name) throws IOException {
|
||||
|
@ -341,27 +342,14 @@ public abstract class AbstractToolSavingTest extends AbstractGhidraHeadedIntegra
|
|||
|
||||
JFrame toolFrame = tool.getToolFrame();
|
||||
runSwing(() -> {
|
||||
Msg.debug(this, "setting tool location to: " + point + "\n\ton window: " +
|
||||
toolFrame.getTitle() + " (" + System.identityHashCode(toolFrame) + ")");
|
||||
toolFrame.setLocation(point);
|
||||
});
|
||||
waitForSwing();
|
||||
|
||||
waitForCondition(() -> {
|
||||
|
||||
Msg.debug(this,
|
||||
"\tattempt again - setting tool location to: " + point + "\n\ton window: " +
|
||||
toolFrame.getTitle() + " (" + System.identityHashCode(toolFrame) + ")");
|
||||
toolFrame.setLocation(point);
|
||||
|
||||
Msg.debug(this, "checking " + point + " against " + toolFrame.getLocation());
|
||||
return point.equals(toolFrame.getLocation());
|
||||
});
|
||||
|
||||
// debug
|
||||
runSwing(() -> {
|
||||
Msg.debug(this, "\ttool bounds now: " + toolFrame.getBounds());
|
||||
});
|
||||
}
|
||||
|
||||
protected void setToolSize(PluginTool tool, final Dimension dimension) {
|
||||
|
|
|
@ -190,7 +190,7 @@ public class ProgramDiffPlugin extends ProgramPlugin
|
|||
ProgramLocation p1Loc = p2Loc;
|
||||
if (p2LocationAddress.getAddressSpace().isOverlaySpace()) {
|
||||
ProgramLocation equivalentP1Loc = DiffUtility
|
||||
.getCompatibleProgramLocation(secondaryDiffProgram, p2Loc, primaryProgram);
|
||||
.getCompatibleProgramLocation(secondaryDiffProgram, p2Loc, primaryProgram);
|
||||
if (equivalentP1Loc != null) {
|
||||
AddressSpace p2Space = p2LocationAddress.getAddressSpace();
|
||||
AddressSpace p1Space = equivalentP1Loc.getAddress().getAddressSpace();
|
||||
|
@ -465,7 +465,7 @@ public class ProgramDiffPlugin extends ProgramPlugin
|
|||
diffControl.setLocation(previousP1Location.getAddress());
|
||||
}
|
||||
ProgramLocation previousP1LocationAsP2 = DiffUtility
|
||||
.getCompatibleProgramLocation(primaryProgram, location, secondaryDiffProgram);
|
||||
.getCompatibleProgramLocation(primaryProgram, location, secondaryDiffProgram);
|
||||
if (previousP1LocationAsP2 != null) {
|
||||
diffListingPanel.setCursorPosition(previousP1LocationAsP2);
|
||||
}
|
||||
|
@ -804,8 +804,8 @@ public class ProgramDiffPlugin extends ProgramPlugin
|
|||
AddressSet p2SelectionAsP1 =
|
||||
DiffUtility.getCompatibleAddressSet(p2Selection, primaryProgram);
|
||||
AddressSet p1ApplySet = p2SelectionAsP1.intersect(p1ViewAddrSet)
|
||||
.subtract(addressesOnlyInP1)
|
||||
.subtract(compatibleOnlyInP2);
|
||||
.subtract(addressesOnlyInP1)
|
||||
.subtract(compatibleOnlyInP2);
|
||||
if (p1ApplySet.isEmpty()) {
|
||||
Msg.showInfo(getClass(), tool.getToolFrame(), "Apply Differences",
|
||||
(p2Selection.isEmpty()) ? "No diff selection in the current view."
|
||||
|
@ -1882,7 +1882,7 @@ public class ProgramDiffPlugin extends ProgramPlugin
|
|||
}
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
// For now do nothing if user cancels, the Diff.
|
||||
// For now do nothing if user cancels
|
||||
}
|
||||
|
||||
monitor.setMessage("");
|
||||
|
|
|
@ -204,6 +204,7 @@ public class DualProgramTest extends DiffTestAdapter {
|
|||
TreeTestUtils.selectTreeNodeByText(tree, "OtherProgram");
|
||||
pressButton(win, "OK");
|
||||
waitForTasks();
|
||||
|
||||
win = waitForWindow("No Memory In Common");
|
||||
assertNotNull(win);
|
||||
MultiLineLabel mll = findComponent(win, MultiLineLabel.class);
|
||||
|
|
|
@ -52,11 +52,14 @@ public class DialogComponentProvider
|
|||
private static final String PROGRESS = "Progress";
|
||||
private static final String DEFAULT = "No Progress";
|
||||
|
||||
protected JPanel rootPanel;
|
||||
private static int idCounter;
|
||||
|
||||
private int id = ++idCounter;
|
||||
|
||||
private boolean modal;
|
||||
private String title;
|
||||
|
||||
protected JPanel rootPanel;
|
||||
private JPanel mainPanel;
|
||||
private JComponent workPanel;
|
||||
private JPanel buttonPanel;
|
||||
|
@ -189,6 +192,10 @@ public class DialogComponentProvider
|
|||
// may be overridden by subclasses
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public JComponent getComponent() {
|
||||
return rootPanel;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,9 @@ import ghidra.util.bean.GGlassPane;
|
|||
public class DockingDialog extends JDialog implements HelpDescriptor {
|
||||
private static Component focusComponent; // allow only one scheduled focus component. See above.
|
||||
|
||||
private static Map<String, BoundsInfo> dialogBoundsMap =
|
||||
LazyMap.lazyMap(new HashMap<>(), () -> new BoundsInfo());
|
||||
|
||||
private WindowListener windowAdapter;
|
||||
private DialogComponentProvider component;
|
||||
private boolean hasBeenFocused;
|
||||
|
@ -47,11 +50,7 @@ public class DockingDialog extends JDialog implements HelpDescriptor {
|
|||
hasBeenFocused = true;
|
||||
}
|
||||
};
|
||||
|
||||
private static Map<String, BoundsInfo> dialogBoundsMap =
|
||||
LazyMap.lazyMap(new HashMap<>(), () -> new BoundsInfo());
|
||||
private DockingWindowManager owningWindowManager;
|
||||
|
||||
private WindowAdapter modalFixWindowAdapter;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1664,7 +1664,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
* @param dialogComponent the DialogComponentProvider object to be shown in a dialog
|
||||
*/
|
||||
public static void showDialog(DialogComponentProvider dialogComponent) {
|
||||
showDialog(null, dialogComponent, (Component) null);
|
||||
doShowDialog(dialogComponent, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1680,41 +1680,10 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
ComponentProvider centeredOnProvider) {
|
||||
ComponentPlaceholder placeholder = getActivePlaceholder(centeredOnProvider);
|
||||
Component c = null;
|
||||
Window parent = null;
|
||||
if (placeholder != null) {
|
||||
parent = root.getWindow(placeholder);
|
||||
c = placeholder.getComponent();
|
||||
}
|
||||
showDialog(parent, dialogComponent, c);
|
||||
|
||||
}
|
||||
|
||||
private static void doShowDialog(DialogComponentProvider provider, Component parent,
|
||||
Component centeredOnComponent) {
|
||||
|
||||
Runnable r = () -> {
|
||||
if (provider.isVisible()) {
|
||||
provider.toFront();
|
||||
return;
|
||||
}
|
||||
|
||||
Window bestParent = getParentWindow(parent);
|
||||
Component bestCenter = getCenterOnComponent(bestParent, centeredOnComponent);
|
||||
|
||||
// Make sure the window we have chosen to center over is related to the given parent.
|
||||
// This prevents the oddness of a dialog that appears on the non-active screen.
|
||||
bestParent = ensureParentHierarchy(bestParent, bestCenter);
|
||||
|
||||
DockingDialog dialog = DockingDialog.createDialog(bestParent, provider, bestCenter);
|
||||
dialog.setVisible(true);
|
||||
};
|
||||
|
||||
if (provider.isModal()) {
|
||||
Swing.runNow(r);
|
||||
}
|
||||
else {
|
||||
Swing.runIfSwingOrRunLater(r);
|
||||
if (placeholder == null && centeredOnProvider != null) {
|
||||
c = centeredOnProvider.getComponent();
|
||||
}
|
||||
doShowDialog(dialogComponent, c);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1731,73 +1700,129 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
* @see #getParentWindow(Component) for parenting notes
|
||||
*/
|
||||
public static void showDialog(Component parent, DialogComponentProvider dialogComponent) {
|
||||
doShowDialog(dialogComponent, parent, null);
|
||||
doShowDialog(dialogComponent, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the dialog using the given parent window using the optional component for
|
||||
* positioning
|
||||
* positioning.
|
||||
*
|
||||
* <p>Warning: this method allows user to explicitly pass a parent window and component over
|
||||
* which to be centered. There is no reason to use this method in the standard workflow.
|
||||
* This method exists strictly to handle future unforeseen use cases. Use at your own
|
||||
* risk of incorrectly parenting dialogs.
|
||||
*
|
||||
* @param parent the component whose window over which the given dialog will be shown
|
||||
* @param parent the component whose window over which the given dialog will be shown; cannot
|
||||
* be null
|
||||
* @param dialogComponent the DialogComponentProvider object to be shown in a dialog
|
||||
* @param centeredOnComponent the component over which the dialog will be centered if not null
|
||||
* @param centeredOnComponent the component over which the dialog will be centered; cannot
|
||||
* be null
|
||||
*/
|
||||
public static void showDialog(Window parent, DialogComponentProvider dialogComponent,
|
||||
Component centeredOnComponent) {
|
||||
Objects.requireNonNull(parent);
|
||||
Objects.requireNonNull(centeredOnComponent);
|
||||
doShowDialog(dialogComponent, parent, centeredOnComponent);
|
||||
}
|
||||
|
||||
private static Window ensureParentHierarchy(Window parent, Component component) {
|
||||
if (CollectionUtils.isAllNull(parent, component)) {
|
||||
KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
|
||||
return kfm.getActiveWindow();
|
||||
}
|
||||
private static void doShowDialog(DialogComponentProvider provider,
|
||||
Component centeredOnComponent) {
|
||||
|
||||
if (SwingUtilities.isDescendingFrom(parent, component)) {
|
||||
return parent;
|
||||
}
|
||||
Runnable r = () -> {
|
||||
if (provider.isVisible()) {
|
||||
provider.toFront();
|
||||
return;
|
||||
}
|
||||
|
||||
return getParentWindow(component);
|
||||
Component bestCenter = getJavaActiveWindow();
|
||||
Window bestParent = getParentWindow(bestCenter);
|
||||
|
||||
if (!provider.isModal()) {
|
||||
bestParent = getBestNonModalParent(provider, bestParent);
|
||||
}
|
||||
|
||||
//
|
||||
// Note: prefer the active window; allow user's choice of center component when it is
|
||||
// in the active window
|
||||
//
|
||||
if (centeredOnComponent != null &&
|
||||
SwingUtilities.isDescendingFrom(centeredOnComponent, bestParent)) {
|
||||
bestCenter = centeredOnComponent;
|
||||
}
|
||||
|
||||
DockingDialog dialog = DockingDialog.createDialog(bestParent, provider, bestCenter);
|
||||
dialog.setVisible(true);
|
||||
};
|
||||
|
||||
if (provider.isModal()) {
|
||||
Swing.runNow(r);
|
||||
}
|
||||
else {
|
||||
Swing.runIfSwingOrRunLater(r);
|
||||
}
|
||||
}
|
||||
|
||||
private static Component getCenterOnComponent(Window parent, Component centeredOnComponent) {
|
||||
private static Window getBestNonModalParent(DialogComponentProvider newProvider,
|
||||
Window bestParent) {
|
||||
|
||||
/*
|
||||
This method seeks to accomplish 2 goals:
|
||||
1) find a suitable component over which to center, and
|
||||
2) ensure that the chosen component is in the parent hierarchy
|
||||
|
||||
*/
|
||||
if (SwingUtilities.isDescendingFrom(parent, centeredOnComponent)) {
|
||||
return centeredOnComponent;
|
||||
KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
|
||||
Window activeWindow = kfm.getActiveWindow();
|
||||
if (!(activeWindow instanceof DockingDialog)) {
|
||||
return bestParent;
|
||||
}
|
||||
|
||||
//
|
||||
// By default, prefer to center over the active window
|
||||
//
|
||||
Window activeWindow = getActiveNonTransientWindow();
|
||||
if (SwingUtilities.isDescendingFrom(parent, activeWindow)) {
|
||||
//
|
||||
// Have an active, visible, non-transient window, which may be another dialog.
|
||||
// We prefer this to be the parent.
|
||||
//
|
||||
return activeWindow;
|
||||
DockingDialog dialog = (DockingDialog) activeWindow;
|
||||
if (!dialog.isModal()) {
|
||||
|
||||
// Note: See issue 'E' described in getParentWindow()
|
||||
// If we parent to a non-modal progress dialog (which is odd), when it goes away, so
|
||||
// to do we. Assume that non-modal dialogs in general are long lived. We shall only
|
||||
// enforce parenting to modal dialogs as defined below in order to prevent blocking of
|
||||
// the non-modal dialog.
|
||||
|
||||
return bestParent; // not modal; assume no issues
|
||||
}
|
||||
|
||||
DialogComponentProvider activeProvider = dialog.getComponent();
|
||||
if (activeProvider == null) {
|
||||
return bestParent;
|
||||
}
|
||||
|
||||
int activeId = activeProvider.getId();
|
||||
int newId = newProvider.getId();
|
||||
if (newId < activeId) {
|
||||
// the new provider is actually older than the active window--do not parent the
|
||||
// new provider to that window
|
||||
return bestParent;
|
||||
}
|
||||
|
||||
//
|
||||
// The chosen component is not in the parent's hierarchy. See if there exists a
|
||||
// non-transient parent window for that component.
|
||||
//
|
||||
Window newWindow = getParentWindow(centeredOnComponent);
|
||||
if (newWindow != null) {
|
||||
// the component is safe to use; the caller of this method will validate the component
|
||||
// we return, updating the parent as needed
|
||||
return centeredOnComponent;
|
||||
}
|
||||
// The active window is modal. We must make it the non-modal dialog's parent to
|
||||
// prevent blocking the non-modal.
|
||||
//
|
||||
return dialog;
|
||||
}
|
||||
|
||||
// We were unable to find a suitable parent for the 'best' component. Just return the
|
||||
// parent as the thing over which to center.
|
||||
return parent;
|
||||
private static void doShowDialog(DialogComponentProvider provider, Window parent,
|
||||
Component centeredOnComponent) {
|
||||
|
||||
Runnable r = () -> {
|
||||
if (provider.isVisible()) {
|
||||
provider.toFront();
|
||||
return;
|
||||
}
|
||||
|
||||
DockingDialog dialog =
|
||||
DockingDialog.createDialog(parent, provider, centeredOnComponent);
|
||||
dialog.setVisible(true);
|
||||
};
|
||||
|
||||
if (provider.isModal()) {
|
||||
Swing.runNow(r);
|
||||
}
|
||||
else {
|
||||
Swing.runIfSwingOrRunLater(r);
|
||||
}
|
||||
}
|
||||
|
||||
private static Window getParentWindow(Component parent) {
|
||||
|
@ -1841,6 +1866,9 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
dialog is shown. If the non-modal dialog is parented to the modal input dialog,
|
||||
then the script progress dialog appears on top (which we do not want) and the
|
||||
progress dialog goes away when the input dialog is closed.
|
||||
E -A long-running API shows a non-modal progress dialog. This API then shows a
|
||||
results dialog which is also non-modal. We do not want to parent the new dialog
|
||||
to the original dialog, since it is a progress dialog that will go away.
|
||||
|
||||
|
||||
For now, the easiest mental model to use is to always prefer the active non-transient
|
||||
|
@ -1849,17 +1877,8 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
|
||||
*/
|
||||
|
||||
//
|
||||
// Due to Use Case 'C' above, prefer dialogs as parents, so that child non-modal dialogs
|
||||
// do not get blocked by modal dialogs.
|
||||
//
|
||||
if (isNonTransientWindow(parent)) {
|
||||
return (Window) parent;
|
||||
}
|
||||
|
||||
DockingWindowManager dwm = getActiveInstance();
|
||||
Window defaultWindow = dwm != null ? dwm.getRootFrame() : null;
|
||||
|
||||
if (parent == null) {
|
||||
Window w = getActiveNonTransientWindow();
|
||||
return w == null ? defaultWindow : w;
|
||||
|
@ -1871,7 +1890,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
// parent of 'c' if it itself is parented to a Frame. The issue is that
|
||||
// Use Case 'C' above may not work correctly. If we find that to be the case,
|
||||
// then we can try changing 'Frame' to 'Window' here.
|
||||
if (c instanceof Frame && isNonTransientWindow(c)) {
|
||||
if (c instanceof Window && isNonTransientWindow(c)) {
|
||||
return (Window) c;
|
||||
}
|
||||
c = c.getParent();
|
||||
|
@ -1896,12 +1915,21 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
return false; // we have seen this in testing
|
||||
}
|
||||
|
||||
return !provider.isTransient();
|
||||
return !provider.isModal() && !provider.isTransient();
|
||||
}
|
||||
|
||||
if (c instanceof Dialog) {
|
||||
return !((Dialog) c).isModal();
|
||||
}
|
||||
|
||||
return (c instanceof Window);
|
||||
}
|
||||
|
||||
private static Window getJavaActiveWindow() {
|
||||
KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
|
||||
return kfm.getActiveWindow();
|
||||
}
|
||||
|
||||
private static Window getActiveNonTransientWindow() {
|
||||
|
||||
KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
|
||||
|
|
|
@ -199,14 +199,14 @@ public class GTableFilterPanel<ROW_OBJECT> extends JPanel {
|
|||
String filterLabel) {
|
||||
this.table = table;
|
||||
|
||||
buildPanel(filterLabel);
|
||||
|
||||
uniquePreferenceKey = createUniqueFilterPreferenceKey(table);
|
||||
|
||||
transformer = new DefaultRowFilterTransformer<>(tableModel, table.getColumnModel());
|
||||
|
||||
textFilterModel = installTableModel(tableModel);
|
||||
|
||||
buildPanel(filterLabel);
|
||||
|
||||
TableColumnModel columnModel = table.getColumnModel();
|
||||
columnModel.addColumnModelListener(columnModelListener);
|
||||
|
||||
|
@ -478,10 +478,11 @@ public class GTableFilterPanel<ROW_OBJECT> extends JPanel {
|
|||
columnFilterDialog = new ColumnFilterDialog<>(this, table, tableModel);
|
||||
}
|
||||
else {
|
||||
Msg.showError(this, this, "Column Filter Error", "This table contains no filterable columns!");
|
||||
Msg.showError(this, this, "Column Filter Error",
|
||||
"This table contains no filterable columns!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
columnFilterDialog.setCloseCallback(() -> {
|
||||
|
|
|
@ -96,6 +96,7 @@ class BasicTaskMonitor implements TaskMonitor {
|
|||
public void initialize(long maxValue) {
|
||||
setMaximum(maxValue);
|
||||
setProgress(0);
|
||||
setIndeterminate(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -55,13 +55,47 @@ public class TaskDialog extends DialogComponentProvider implements TaskMonitor {
|
|||
|
||||
public final static int DEFAULT_WIDTH = 275;
|
||||
|
||||
/*
|
||||
* Note: all paths of finishing should end up calling this runnable.
|
||||
*
|
||||
* Workflow:
|
||||
*
|
||||
* Dialog Close Button Pressed:
|
||||
* -calls cancelCallback()
|
||||
* -calls verifyCancel runnable
|
||||
* -calls iternalCancel()
|
||||
* -triggers taskProcessed()
|
||||
* -calls closeDialog runnable
|
||||
*
|
||||
* Cancel Button Pressed:
|
||||
* -(same as Dialog Close Button Pressed)
|
||||
*
|
||||
* Task Monitor Stop Button Pressed:
|
||||
* -triggers taskProcessed()
|
||||
* -calls closeDialog runnable
|
||||
*
|
||||
* Public API dispose() is Called:
|
||||
* -calls iternalCancel()
|
||||
* -triggers taskProcessed()
|
||||
* -calls closeDialog runnable
|
||||
*
|
||||
* Task Monitor Cancelled by API:
|
||||
* -triggers taskProcessed()
|
||||
* -calls closeDialog runnable
|
||||
*
|
||||
* Task Finishes Normally:
|
||||
* -triggers taskProcessed()
|
||||
* -calls closeDialog runnable
|
||||
*
|
||||
*
|
||||
*/
|
||||
private Runnable closeDialog = () -> {
|
||||
close();
|
||||
dispose();
|
||||
cleanup();
|
||||
};
|
||||
private Runnable verifyCancel = () -> {
|
||||
if (promptToVerifyCancel()) {
|
||||
cancel();
|
||||
internalCancel();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -196,6 +230,7 @@ public class TaskDialog extends DialogComponentProvider implements TaskMonitor {
|
|||
|
||||
@Override
|
||||
protected void cancelCallback() {
|
||||
// note: this is called from the cancel button and when the dialog close button is pressed
|
||||
Swing.runLater(verifyCancel);
|
||||
}
|
||||
|
||||
|
@ -211,11 +246,10 @@ public class TaskDialog extends DialogComponentProvider implements TaskMonitor {
|
|||
}
|
||||
|
||||
/**
|
||||
* Called after the task has been executed
|
||||
* Called after the task has been executed or when the task is cancelled
|
||||
*/
|
||||
public void taskProcessed() {
|
||||
finished.countDown();
|
||||
monitorComponent.notifyChangeListeners();
|
||||
Swing.runLater(closeDialog);
|
||||
}
|
||||
|
||||
|
@ -305,8 +339,14 @@ public class TaskDialog extends DialogComponentProvider implements TaskMonitor {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the task and closes this dialog
|
||||
*/
|
||||
public void dispose() {
|
||||
cancel();
|
||||
internalCancel();
|
||||
}
|
||||
|
||||
private void cleanup() {
|
||||
showTimer.cancel();
|
||||
messageUpdater.dispose();
|
||||
}
|
||||
|
@ -339,17 +379,21 @@ public class TaskDialog extends DialogComponentProvider implements TaskMonitor {
|
|||
@Override
|
||||
public void initialize(long max) {
|
||||
|
||||
monitorComponent.initialize(max);
|
||||
|
||||
if (!supportsProgress) {
|
||||
if (max <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!monitorComponent.isShowing()) {
|
||||
// Note: it is not clear why we only wish to show progress if the monitor is not
|
||||
// visible. This seems wrong. If someone knows, please update this code.
|
||||
installProgressMonitor();
|
||||
monitorComponent.initialize(max);
|
||||
if (!supportsProgress) {
|
||||
supportsProgress = true;
|
||||
setIndeterminate(false);
|
||||
}
|
||||
|
||||
// Note: it is not clear why we only wish to show progress if the monitor is not
|
||||
// visible. This seems wrong. If someone knows, please update this code.
|
||||
//if (!monitorComponent.isShowing()) {
|
||||
installProgressMonitor();
|
||||
//}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -391,11 +435,15 @@ public class TaskDialog extends DialogComponentProvider implements TaskMonitor {
|
|||
|
||||
@Override
|
||||
public synchronized void cancel() {
|
||||
internalCancel();
|
||||
}
|
||||
|
||||
private void internalCancel() {
|
||||
if (monitorComponent.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
// Mark as cancelled, must be detected by task which should terminate
|
||||
// and invoke setCompleted which will dismiss dialog.
|
||||
|
||||
// mark as cancelled; the task will terminate and the callback will dismiss this dialog
|
||||
monitorComponent.cancel();
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ import javax.swing.*;
|
|||
import docking.widgets.EmptyBorderButton;
|
||||
import docking.widgets.OptionDialog;
|
||||
import docking.widgets.label.GDHtmlLabel;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.util.Swing;
|
||||
import ghidra.util.datastruct.WeakDataStructureFactory;
|
||||
import ghidra.util.datastruct.WeakSet;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
|
@ -208,7 +208,7 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor {
|
|||
// a task dialog for fast background tasks.
|
||||
//
|
||||
isIndeterminate.set(indeterminate);
|
||||
SystemUtilities.runIfSwingOrPostSwingLater(() -> {
|
||||
Swing.runIfSwingOrRunLater(() -> {
|
||||
boolean newValue = isIndeterminate.get();
|
||||
progressBar.setIndeterminate(newValue);
|
||||
progressBar.setStringPainted(!newValue);
|
||||
|
@ -219,7 +219,7 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor {
|
|||
public synchronized void setCancelEnabled(boolean enable) {
|
||||
if (cancelEnabled != enable) {
|
||||
cancelEnabled = enable;
|
||||
SystemUtilities.runSwingLater(updateCancelButtonRunnable);
|
||||
Swing.runLater(updateCancelButtonRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,7 +237,7 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor {
|
|||
isCancelled = true;
|
||||
}
|
||||
|
||||
notifyChangeListeners();
|
||||
notifyCancelListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -286,7 +286,7 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor {
|
|||
public synchronized void showProgress(boolean show) {
|
||||
if (show != showingProgress) {
|
||||
showingProgress = show;
|
||||
SystemUtilities.runSwingLater(updateProgressPanelRunnable);
|
||||
Swing.runLater(updateProgressPanelRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -298,7 +298,7 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor {
|
|||
*/
|
||||
public void setTaskName(String name) {
|
||||
taskName = name;
|
||||
SystemUtilities.runSwingLater(updateToolTipRunnable);
|
||||
Swing.runLater(updateToolTipRunnable);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -342,16 +342,16 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor {
|
|||
showingIcon = visible;
|
||||
};
|
||||
|
||||
SystemUtilities.runSwingNow(r);
|
||||
Swing.runNow(r);
|
||||
}
|
||||
|
||||
protected void notifyChangeListeners() {
|
||||
protected void notifyCancelListeners() {
|
||||
Runnable r = () -> {
|
||||
for (CancelledListener mcl : listeners) {
|
||||
mcl.cancelled();
|
||||
}
|
||||
};
|
||||
SwingUtilities.invokeLater(r);
|
||||
Swing.runLater(r);
|
||||
}
|
||||
|
||||
private synchronized void startUpdateTimer() {
|
||||
|
@ -493,7 +493,7 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor {
|
|||
|
||||
cancelButton.setName("CANCEL_TASK");
|
||||
cancelButton.setPreferredSize(new Dimension(icon.getIconWidth(), icon.getIconHeight()));
|
||||
cancelButton.addActionListener(e -> SwingUtilities.invokeLater(shouldCancelRunnable));
|
||||
cancelButton.addActionListener(e -> Swing.runLater(shouldCancelRunnable));
|
||||
cancelButton.setFocusable(false);
|
||||
cancelButton.setRolloverEnabled(true);
|
||||
|
||||
|
|
|
@ -68,8 +68,14 @@ public class WrappingTaskMonitor implements TaskMonitor {
|
|||
delegate.removeCancelledListener(l);
|
||||
}
|
||||
|
||||
newDelegate.setIndeterminate(delegate.isIndeterminate());
|
||||
newDelegate.initialize(delegate.getMaximum());
|
||||
if (delegate.isIndeterminate()) {
|
||||
newDelegate.setIndeterminate(true);
|
||||
}
|
||||
else {
|
||||
newDelegate.setIndeterminate(false);
|
||||
newDelegate.initialize(delegate.getMaximum());
|
||||
}
|
||||
|
||||
newDelegate.setProgress(delegate.getProgress());
|
||||
newDelegate.setMessage(delegate.getMessage());
|
||||
newDelegate.setCancelEnabled(delegate.isCancelEnabled());
|
||||
|
|
|
@ -1446,7 +1446,7 @@ public abstract class PluginTool extends AbstractDockingTool {
|
|||
* @param centeredOnComponent the component on which to center the dialog.
|
||||
*/
|
||||
public void showDialog(DialogComponentProvider dialogComponent, Component centeredOnComponent) {
|
||||
DockingWindowManager.showDialog(getToolFrame(), dialogComponent, centeredOnComponent);
|
||||
DockingWindowManager.showDialog(centeredOnComponent, dialogComponent);
|
||||
}
|
||||
|
||||
public Window getActiveWindow() {
|
||||
|
|
|
@ -40,12 +40,12 @@ import ghidra.program.model.util.StringPropertyMap;
|
|||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||
import ghidra.test.TestEnv;
|
||||
import ghidra.util.InvalidNameException;
|
||||
import ghidra.util.task.TaskMonitorAdapter;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import utilities.util.FileUtilities;
|
||||
|
||||
public class ProjectInfoFilesystemTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
|
||||
private static final String PROJECT_NAME = "TestProject";
|
||||
private static final String TEST_PROJECT_NAME = "TestProject";
|
||||
|
||||
private TestEnv env;
|
||||
|
||||
|
@ -64,11 +64,11 @@ public class ProjectInfoFilesystemTest extends AbstractGhidraHeadedIntegrationTe
|
|||
|
||||
env = new TestEnv();
|
||||
|
||||
projectLocator = new ProjectLocator(getTestDirectoryPath(), PROJECT_NAME);
|
||||
projectLocator = new ProjectLocator(getTestDirectoryPath(), TEST_PROJECT_NAME);
|
||||
projectLocator.getMarkerFile().delete();
|
||||
|
||||
File projectDir = new File(getTestDirectoryPath(),
|
||||
PROJECT_NAME + ProjectLocator.getProjectDirExtension());
|
||||
TEST_PROJECT_NAME + ProjectLocator.getProjectDirExtension());
|
||||
if (projectDir.isDirectory()) {
|
||||
if (!FileUtilities.deleteDir(projectDir)) {
|
||||
Assert.fail("Cleanup of old test project failed");
|
||||
|
@ -78,7 +78,7 @@ public class ProjectInfoFilesystemTest extends AbstractGhidraHeadedIntegrationTe
|
|||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
closeAllWindowsAndFrames();
|
||||
closeAllWindows();
|
||||
env.dispose();
|
||||
|
||||
if (project != null) {
|
||||
|
@ -114,11 +114,6 @@ public class ProjectInfoFilesystemTest extends AbstractGhidraHeadedIntegrationTe
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create project
|
||||
* @param filesystemVersion -1: mangled, 0... indexed version
|
||||
* @throws Exception
|
||||
*/
|
||||
private void createProject(int filesystemVersion) throws Exception {
|
||||
|
||||
if (filesystemVersion < 0) {
|
||||
|
@ -164,11 +159,6 @@ public class ProjectInfoFilesystemTest extends AbstractGhidraHeadedIntegrationTe
|
|||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and open project in front-end and popup Project Info dialog
|
||||
* @param filesystemVersion -1: mangled, 0... indexed version
|
||||
* @throws Exception
|
||||
*/
|
||||
private void openProjectAndInfo(int filesystemVersion) throws Exception {
|
||||
|
||||
frontEndTool = env.getFrontEndTool();
|
||||
|
@ -197,8 +187,7 @@ public class ProjectInfoFilesystemTest extends AbstractGhidraHeadedIntegrationTe
|
|||
assertNotNull(action);
|
||||
performAction(action, true);
|
||||
|
||||
dialog = waitForDialogComponent(frontEndTool.getToolFrame(), ProjectInfoDialog.class, 2000);
|
||||
assertNotNull(dialog);
|
||||
dialog = waitForDialogComponent(ProjectInfoDialog.class);
|
||||
}
|
||||
|
||||
private DomainFolder getFolder(String folderPath, boolean create) throws IOException {
|
||||
|
@ -239,13 +228,13 @@ public class ProjectInfoFilesystemTest extends AbstractGhidraHeadedIntegrationTe
|
|||
programUserData.endTransaction(txId);
|
||||
}
|
||||
|
||||
df = getFolder(folderPath, true).createFile(name, p, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
df = getFolder(folderPath, true).createFile(name, p, TaskMonitor.DUMMY);
|
||||
}
|
||||
finally {
|
||||
p.release(this);
|
||||
}
|
||||
|
||||
df.addToVersionControl("Initial", true, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
df.addToVersionControl("Initial", true, TaskMonitor.DUMMY);
|
||||
return df;
|
||||
}
|
||||
|
||||
|
@ -266,7 +255,7 @@ public class ProjectInfoFilesystemTest extends AbstractGhidraHeadedIntegrationTe
|
|||
assertEquals("Initial", versionHistory[0].getComment());
|
||||
|
||||
Program p =
|
||||
(Program) df.getDomainObject(this, false, false, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
(Program) df.getDomainObject(this, false, false, TaskMonitor.DUMMY);
|
||||
try {
|
||||
AddressFactory addressFactory = p.getAddressFactory();
|
||||
ProgramUserData programUserData = p.getProgramUserData();
|
||||
|
@ -303,7 +292,7 @@ public class ProjectInfoFilesystemTest extends AbstractGhidraHeadedIntegrationTe
|
|||
|
||||
JLabel nameLabel = (JLabel) findComponentByName(dialog.getComponent(), "Project Name");
|
||||
assertNotNull(nameLabel);
|
||||
assertEquals(PROJECT_NAME, nameLabel.getText());
|
||||
assertEquals(TEST_PROJECT_NAME, nameLabel.getText());
|
||||
}
|
||||
|
||||
private void doStorageConvert(String buttonText) {
|
||||
|
@ -314,7 +303,7 @@ public class ProjectInfoFilesystemTest extends AbstractGhidraHeadedIntegrationTe
|
|||
pressButton(button, false);
|
||||
|
||||
JDialog confirmDialog =
|
||||
waitForJDialog(null, "Confirm Convert/Upgrade Project Storage", 2000);
|
||||
waitForJDialog("Confirm Convert/Upgrade Project Storage");
|
||||
assertNotNull("Expected convert confirm dialog", confirmDialog);
|
||||
|
||||
JButton confirmButton = findButtonByText(confirmDialog, "Convert");
|
||||
|
@ -322,7 +311,7 @@ public class ProjectInfoFilesystemTest extends AbstractGhidraHeadedIntegrationTe
|
|||
|
||||
waitForPostedSwingRunnables();
|
||||
|
||||
dialog = waitForDialogComponent(frontEndTool.getToolFrame(), ProjectInfoDialog.class, 5000);
|
||||
dialog = waitForDialogComponent(ProjectInfoDialog.class);
|
||||
assertNotNull("Expected to find Project Info dialog after conversion completed", dialog);
|
||||
|
||||
ProjectManager projectManager = env.getProjectManager();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue