mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-224 - Modal Dialogs - fixed modal dialogs not being parented to
active window in default case
This commit is contained in:
parent
2b08598dba
commit
9dd458e9e1
24 changed files with 182 additions and 217 deletions
|
@ -35,10 +35,10 @@ import ghidra.framework.project.DefaultProjectManager;
|
|||
import ghidra.framework.remote.InetNameLookup;
|
||||
import ghidra.framework.store.LockException;
|
||||
import ghidra.program.database.ProgramDB;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.exception.UsrException;
|
||||
import ghidra.util.task.*;
|
||||
import ghidra.util.task.TaskLauncher;
|
||||
import ghidra.util.task.TaskMonitorAdapter;
|
||||
|
||||
/**
|
||||
* Main Ghidra application class. Creates
|
||||
|
@ -64,7 +64,6 @@ import ghidra.util.task.*;
|
|||
* @see ghidra.GhidraLauncher
|
||||
*/
|
||||
public class GhidraRun implements GhidraLaunchable {
|
||||
private final String MASTER_HELP_SET_HS = "Base_HelpSet.hs";
|
||||
|
||||
private Logger log; // intentionally load later, after initialization
|
||||
|
||||
|
@ -179,14 +178,12 @@ public class GhidraRun implements GhidraLaunchable {
|
|||
}
|
||||
}
|
||||
|
||||
private void openProject(final FrontEndTool tool, final ProjectLocator projectLocator,
|
||||
final boolean reopen) {
|
||||
private void openProject(FrontEndTool tool, ProjectLocator projectLocator, boolean reopen) {
|
||||
SplashScreen.updateSplashScreenStatus(
|
||||
(reopen ? "Reopening" : "Opening") + " project: " + projectLocator.getName());
|
||||
final Runnable r = () -> doOpenProject(tool, projectLocator, reopen);
|
||||
|
||||
InvokeInSwingTask task = new InvokeInSwingTask("Opening Project", r);
|
||||
new TaskLauncher(task, tool.getToolFrame(), 0);
|
||||
Runnable r = () -> doOpenProject(tool, projectLocator, reopen);
|
||||
TaskLauncher.launchModal("Opening Project", () -> Swing.runNow(r));
|
||||
}
|
||||
|
||||
private void doOpenProject(FrontEndTool tool, ProjectLocator projectLocator, boolean reopen) {
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
package ghidra.app.plugin.core.compositeeditor;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Window;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import docking.ActionContext;
|
||||
import docking.DockingWindowManager;
|
||||
|
@ -59,9 +56,7 @@ public class AddBitFieldAction extends CompositeEditorTableAction {
|
|||
new BitFieldEditorDialog(editorModel.viewComposite, provider.dtmService,
|
||||
-(rowIndex + 1), ordinal -> refreshTableAndSelection(editorModel, ordinal));
|
||||
Component c = provider.getComponent();
|
||||
Window w = SwingUtilities.windowForComponent(c);
|
||||
DockingWindowManager.showDialog(w, dlg, c);
|
||||
|
||||
DockingWindowManager.showDialog(c, dlg);
|
||||
requestTableFocus();
|
||||
}
|
||||
|
||||
|
|
|
@ -165,8 +165,7 @@ public abstract class CompositeEditorPanel extends JPanel
|
|||
model.notifyCompositeChanged();
|
||||
});
|
||||
Component c = provider.getComponent();
|
||||
Window w = SwingUtilities.windowForComponent(c);
|
||||
DockingWindowManager.showDialog(w, dlg, c);
|
||||
DockingWindowManager.showDialog(c, dlg);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,10 +16,8 @@
|
|||
package ghidra.app.plugin.core.compositeeditor;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Window;
|
||||
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import docking.ActionContext;
|
||||
import docking.DockingWindowManager;
|
||||
|
@ -77,8 +75,7 @@ public class EditBitFieldAction extends CompositeEditorTableAction {
|
|||
provider.dtmService, dtComponent.getOrdinal(),
|
||||
ordinal -> refreshTableAndSelection(editorModel, ordinal));
|
||||
Component c = provider.getComponent();
|
||||
Window w = SwingUtilities.windowForComponent(c);
|
||||
DockingWindowManager.showDialog(w, dlg, c);
|
||||
DockingWindowManager.showDialog(c, dlg);
|
||||
requestTableFocus();
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.datamgr.actions;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.*;
|
||||
|
@ -138,7 +137,7 @@ public class ExportToHeaderAction extends DockingAction {
|
|||
if (!list.isEmpty()) {
|
||||
list.add(0, new DefaultAnnotationHandler());
|
||||
AnnotationHandlerDialog dlg = new AnnotationHandlerDialog(list);
|
||||
plugin.getTool().showDialog(dlg, (Component) null);
|
||||
plugin.getTool().showDialog(dlg);
|
||||
if (!dlg.wasSuccessful()) {
|
||||
return;
|
||||
}
|
||||
|
@ -210,8 +209,7 @@ public class ExportToHeaderAction extends DockingAction {
|
|||
finally {
|
||||
writer.close();
|
||||
}
|
||||
plugin.getTool()
|
||||
.setStatusInfo(
|
||||
plugin.getTool().setStatusInfo(
|
||||
"Successfully exported data type(s) to " + file.getAbsolutePath());
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
|
|
|
@ -35,7 +35,7 @@ import ghidra.app.plugin.PluginCategoryNames;
|
|||
import ghidra.app.util.HelpTopics;
|
||||
import ghidra.framework.main.FrontEndable;
|
||||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.util.*;
|
||||
import ghidra.framework.plugintool.util.PluginStatus;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.util.DefaultLanguageService;
|
||||
import ghidra.util.HelpLocation;
|
||||
|
@ -102,7 +102,7 @@ public class ProcessorListPlugin extends Plugin implements FrontEndable {
|
|||
if (dialogProvider == null) {
|
||||
dialogProvider = new ProcessorListDialogProvider();
|
||||
}
|
||||
tool.showDialog(dialogProvider, tool.getToolFrame());
|
||||
tool.showDialog(dialogProvider);
|
||||
}
|
||||
|
||||
private void copy(boolean asHtml) {
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.register;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.event.*;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
|
@ -290,7 +289,7 @@ public class RegisterPlugin extends ProgramPlugin {
|
|||
SetRegisterValueDialog dialog =
|
||||
new SetRegisterValueDialog(context.getProgram(), registers, register, addrSet, false);
|
||||
|
||||
tool.showDialog(dialog, (Component) null);
|
||||
tool.showDialog(dialog);
|
||||
|
||||
Register selectedRegister = dialog.getSelectRegister();
|
||||
if (selectedRegister != null) {
|
||||
|
@ -304,7 +303,7 @@ public class RegisterPlugin extends ProgramPlugin {
|
|||
SetRegisterValueDialog dialog =
|
||||
new SetRegisterValueDialog(context.getProgram(), registers, register, addrSet, true);
|
||||
|
||||
tool.showDialog(dialog, (Component) null);
|
||||
tool.showDialog(dialog);
|
||||
|
||||
BigInteger value = dialog.getRegisterValue();
|
||||
Register selectedRegister = dialog.getSelectRegister();
|
||||
|
|
|
@ -24,7 +24,8 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
import javax.swing.*;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
|
||||
import docking.*;
|
||||
import docking.ActionContext;
|
||||
import docking.DialogComponentProvider;
|
||||
import docking.action.DockingAction;
|
||||
import docking.widgets.table.*;
|
||||
import docking.widgets.table.threaded.ThreadedTableModel;
|
||||
|
@ -181,8 +182,7 @@ public class TableChooserDialog extends DialogComponentProvider
|
|||
}
|
||||
|
||||
public void show() {
|
||||
DockingWindowManager manager = DockingWindowManager.getActiveInstance();
|
||||
tool.showDialog(this, manager.getMainWindow());
|
||||
tool.showDialog(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -358,7 +358,7 @@ public class SetEquateDialog extends DialogComponentProvider {
|
|||
result = CANCELED;
|
||||
overwriteExistingEquates.setVisible(true);
|
||||
setTitle("Set Equate");
|
||||
tool.showDialog(this, (Component) null);
|
||||
tool.showDialog(this);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -374,7 +374,7 @@ public class SetEquateDialog extends DialogComponentProvider {
|
|||
overwriteExistingEquates.setVisible(false);
|
||||
overwriteExistingEquates.setEnabled(false);
|
||||
setTitle("Rename Equate");
|
||||
tool.showDialog(this, (Component) null);
|
||||
tool.showDialog(this);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ public class TutorialScreenShotGenerator extends AbstractScreenShotGenerator {
|
|||
@Deprecated
|
||||
public void showImage() {
|
||||
ImageDialogProvider dialog = new ImageDialogProvider(null, null, image);
|
||||
tool.showDialog(dialog, tool.getToolFrame());
|
||||
tool.showDialog(dialog);
|
||||
}
|
||||
|
||||
protected void saveToFile(String absolutePathToImage) {
|
||||
|
|
|
@ -332,8 +332,7 @@ public class FGController implements ProgramLocationListener, ProgramSelectionLi
|
|||
}
|
||||
|
||||
private boolean shouldSaveVertexChanges() {
|
||||
return functionGraphOptions
|
||||
.getNavigationHistoryChoice() == NavigationHistoryChoices.VERTEX_CHANGES;
|
||||
return functionGraphOptions.getNavigationHistoryChoice() == NavigationHistoryChoices.VERTEX_CHANGES;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -694,14 +693,16 @@ public class FGController implements ProgramLocationListener, ProgramSelectionLi
|
|||
vertex = view.getEntryPointVertex();
|
||||
}
|
||||
|
||||
PluginTool tool = plugin.getTool();
|
||||
SetFormatDialogComponentProvider setFormatDialog =
|
||||
new SetFormatDialogComponentProvider(getDefaultFormatManager(), minimalFormatManager,
|
||||
plugin.getTool(), provider.getProgram(), vertex.getAddresses());
|
||||
plugin.getTool().showDialogOnActiveWindow(setFormatDialog);
|
||||
tool, provider.getProgram(), vertex.getAddresses());
|
||||
tool.showDialog(setFormatDialog);
|
||||
FormatManager newFormatManager = setFormatDialog.getNewFormatManager();
|
||||
if (newFormatManager == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
SaveState saveState = new SaveState();
|
||||
newFormatManager.saveState(saveState);
|
||||
minimalFormatManager.readState(saveState);
|
||||
|
|
|
@ -32,7 +32,7 @@ public class DiffApply2Test extends DiffApplyTestAdapter {
|
|||
@Test
|
||||
public void testApplyDiffsNextActionFirst() throws Exception {
|
||||
openDiff(diffTestP1, diffTestP2);
|
||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Memory Differs", 2000);
|
||||
JDialog dialog = waitForJDialog("Memory Differs");
|
||||
pressButtonByText(dialog, "OK");
|
||||
waitForPostedSwingRunnables();
|
||||
showApplySettings();
|
||||
|
@ -55,7 +55,7 @@ public class DiffApply2Test extends DiffApplyTestAdapter {
|
|||
@Test
|
||||
public void testApplyDiffsNextActionMiddle() throws Exception {
|
||||
openDiff(diffTestP1, diffTestP2);
|
||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Memory Differs", 2000);
|
||||
JDialog dialog = waitForJDialog("Memory Differs");
|
||||
pressButtonByText(dialog, "OK");
|
||||
waitForPostedSwingRunnables();
|
||||
showApplySettings();
|
||||
|
@ -79,7 +79,7 @@ public class DiffApply2Test extends DiffApplyTestAdapter {
|
|||
@Test
|
||||
public void testApplyDiffsNextActionLast() throws Exception {
|
||||
openDiff(diffTestP1, diffTestP2);
|
||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Memory Differs", 2000);
|
||||
JDialog dialog = waitForJDialog("Memory Differs");
|
||||
pressButtonByText(dialog, "OK");
|
||||
waitForPostedSwingRunnables();
|
||||
showApplySettings();
|
||||
|
@ -93,7 +93,7 @@ public class DiffApply2Test extends DiffApplyTestAdapter {
|
|||
@Test
|
||||
public void testIgnoreEntireBlock() throws Exception {
|
||||
openDiff(diffTestP1, diffTestP2);
|
||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Memory Differs", 2000);
|
||||
JDialog dialog = waitForJDialog("Memory Differs");
|
||||
pressButtonByText(dialog, "OK");
|
||||
waitForPostedSwingRunnables();
|
||||
showApplySettings();
|
||||
|
@ -136,7 +136,7 @@ public class DiffApply2Test extends DiffApplyTestAdapter {
|
|||
@Test
|
||||
public void testIgnorePartialBlock() throws Exception {
|
||||
openDiff(diffTestP1, diffTestP2);
|
||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Memory Differs", 2000);
|
||||
JDialog dialog = waitForJDialog("Memory Differs");
|
||||
pressButtonByText(dialog, "OK");
|
||||
waitForPostedSwingRunnables();
|
||||
showApplySettings();
|
||||
|
@ -163,7 +163,7 @@ public class DiffApply2Test extends DiffApplyTestAdapter {
|
|||
@Test
|
||||
public void testUndoRedo() throws Exception {
|
||||
openDiff(diffTestP1, diffTestP2);
|
||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Memory Differs", 2000);
|
||||
JDialog dialog = waitForJDialog("Memory Differs");
|
||||
pressButtonByText(dialog, "OK");
|
||||
waitForPostedSwingRunnables();
|
||||
showApplySettings();
|
||||
|
|
|
@ -361,6 +361,17 @@ class DetachedWindowNode extends WindowNode {
|
|||
}
|
||||
});
|
||||
|
||||
adjustBounds();
|
||||
|
||||
window.setBounds(bounds);
|
||||
window.setVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the bounds of this window have a valid location and size
|
||||
*/
|
||||
private void adjustBounds() {
|
||||
|
||||
if (bounds.height == 0 || bounds.width == 0) {
|
||||
window.pack();
|
||||
Dimension d = window.getSize();
|
||||
|
@ -368,9 +379,14 @@ class DetachedWindowNode extends WindowNode {
|
|||
bounds.width = d.width;
|
||||
}
|
||||
|
||||
WindowUtilities.ensureOnScreen(winMgr.getRootFrame(), bounds);
|
||||
window.setBounds(bounds);
|
||||
window.setVisible(true);
|
||||
Window activeWindow = winMgr.getActiveWindow();
|
||||
Point p = bounds.getLocation();
|
||||
if (p.x == 0 && p.y == 0) {
|
||||
p = WindowUtilities.centerOnScreen(activeWindow, bounds.getSize());
|
||||
bounds.setLocation(p);
|
||||
}
|
||||
|
||||
WindowUtilities.ensureOnScreen(activeWindow, bounds);
|
||||
}
|
||||
|
||||
private JFrame createFrame() {
|
||||
|
@ -455,10 +471,6 @@ class DetachedWindowNode extends WindowNode {
|
|||
((RootNode) parent).notifyWindowChanged(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases all resources and makes this node unusable.
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
void dispose() {
|
||||
if (dropTargetHandler != null) {
|
||||
|
@ -516,10 +528,8 @@ class DetachedWindowNode extends WindowNode {
|
|||
if (window != null) {
|
||||
bounds = window.getBounds();
|
||||
}
|
||||
|
||||
Element root = new Element("WINDOW_NODE");
|
||||
// if (title != null) {
|
||||
// root.setAttribute("TITLE", title);
|
||||
// }
|
||||
root.setAttribute("X_POS", "" + bounds.x);
|
||||
root.setAttribute("Y_POS", "" + bounds.y);
|
||||
root.setAttribute("WIDTH", "" + bounds.width);
|
||||
|
@ -539,7 +549,7 @@ class DetachedWindowNode extends WindowNode {
|
|||
|
||||
/**
|
||||
* Set the status text
|
||||
* @param text
|
||||
* @param text the text
|
||||
*/
|
||||
public void setStatusText(String text) {
|
||||
if (statusBar != null) {
|
||||
|
|
|
@ -20,25 +20,38 @@ import javax.swing.JFrame;
|
|||
import ghidra.util.bean.GGlassPane;
|
||||
|
||||
/**
|
||||
* Base JFrame to be used by the root window and detached windows if they are using frames
|
||||
*
|
||||
* Also fixed:
|
||||
* <ol>
|
||||
* <li>Swing problem of setting bounds before the frame is visible causes slow paints
|
||||
* if the bounds position is not on the primary display, </li>
|
||||
* </ol>
|
||||
* Base frame used by the root window and detached windows
|
||||
*/
|
||||
public class DockingFrame extends JFrame {
|
||||
|
||||
private boolean isTransient;
|
||||
|
||||
public DockingFrame(String name) {
|
||||
super(name);
|
||||
|
||||
GGlassPane ghidraGlassPane = new GGlassPane();
|
||||
setGlassPane(ghidraGlassPane);
|
||||
ghidraGlassPane.setVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks this frame as transient. A transient frame is one that is show temporarily.
|
||||
*/
|
||||
public void setTransient() {
|
||||
this.isTransient = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* REturns whether this frame is transient. A transient frame is one that is show temporarily.
|
||||
* @return true if transient
|
||||
*/
|
||||
public boolean isTransient() {
|
||||
return isTransient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getTitle();
|
||||
return getTitle() + (isTransient ? " - transient" : "") + " (" +
|
||||
System.identityHashCode(this) + ")";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,8 +131,8 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
* @param hasStatusBar if true a status bar will be created for the main window
|
||||
* @param factory the drop target factory
|
||||
*/
|
||||
public DockingWindowManager(Tool tool, List<Image> images, boolean modal,
|
||||
boolean isDocking, boolean hasStatusBar, DropTargetFactory factory) {
|
||||
public DockingWindowManager(Tool tool, List<Image> images, boolean modal, boolean isDocking,
|
||||
boolean hasStatusBar, DropTargetFactory factory) {
|
||||
|
||||
KeyBindingOverrideKeyEventDispatcher.install();
|
||||
|
||||
|
@ -1189,8 +1189,8 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
for (ComponentPlaceholder placeholder : placeholders) {
|
||||
ComponentProvider provider = placeholder.getProvider();
|
||||
boolean isTransient = provider.isTransient();
|
||||
actionList.add(
|
||||
new ShowComponentAction(this, placeholder, subMenuName, isTransient));
|
||||
actionList
|
||||
.add(new ShowComponentAction(this, placeholder, subMenuName, isTransient));
|
||||
}
|
||||
|
||||
if (subMenuName != null) {
|
||||
|
@ -1649,44 +1649,13 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the dialog using the tool's currently active window as a parent
|
||||
*
|
||||
* @param dialogComponent the DialogComponentProvider object to be shown in a dialog
|
||||
*/
|
||||
public static void showDialogOnActiveWindow(DialogComponentProvider dialogComponent) {
|
||||
showDialog(null, dialogComponent, (Component) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the dialog using the tool's currently active window as a parent
|
||||
*
|
||||
* @param dialogComponent the DialogComponentProvider object to be shown in a dialog
|
||||
*/
|
||||
public static void showDialog(DialogComponentProvider dialogComponent) {
|
||||
showDialogOnActiveWindow(dialogComponent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the dialog using the given component's parent frame, centering the dialog
|
||||
* on the given component
|
||||
*
|
||||
* @param dialogComponent the DialogComponentProvider object to be shown in a dialog.
|
||||
* @param centeredOnComponent the component on which to center the dialog.
|
||||
*/
|
||||
public static void showDialog(DialogComponentProvider dialogComponent,
|
||||
Component centeredOnComponent) {
|
||||
Window parent = null;
|
||||
Component c = centeredOnComponent;
|
||||
while (c != null) {
|
||||
if ((c instanceof Frame) || (c instanceof Dialog)) {
|
||||
parent = (Window) c;
|
||||
break;
|
||||
}
|
||||
c = c.getParent();
|
||||
}
|
||||
|
||||
showDialog(parent, dialogComponent, centeredOnComponent);
|
||||
showDialog(null, dialogComponent, (Component) null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1720,10 +1689,14 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
return;
|
||||
}
|
||||
|
||||
Window updatedParent = getParentWindow(parent);
|
||||
Component updatedCenter = getCenterOnComponent(centeredOnComponent);
|
||||
DockingDialog dialog =
|
||||
DockingDialog.createDialog(updatedParent, provider, updatedCenter);
|
||||
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);
|
||||
};
|
||||
|
||||
|
@ -1735,17 +1708,6 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
}
|
||||
}
|
||||
|
||||
private static Component getCenterOnComponent(Component centeredOnComponent) {
|
||||
|
||||
if (centeredOnComponent != null) {
|
||||
return centeredOnComponent;
|
||||
}
|
||||
|
||||
// by default, prefer to center over the active window
|
||||
Window activeWindow = getActiveNonTransientWindow();
|
||||
return activeWindow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the dialog using the given parent component to find a parent window and to
|
||||
* position the dialog. If a Window can be found containing the given component, it
|
||||
|
@ -1773,10 +1735,53 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
*/
|
||||
public static void showDialog(Window parent, DialogComponentProvider dialogComponent,
|
||||
Component centeredOnComponent) {
|
||||
|
||||
doShowDialog(dialogComponent, parent, centeredOnComponent);
|
||||
}
|
||||
|
||||
private static Window ensureParentHierarchy(Window parent, Component component) {
|
||||
if (SwingUtilities.isDescendingFrom(parent, component)) {
|
||||
return parent;
|
||||
}
|
||||
|
||||
return getParentWindow(component);
|
||||
}
|
||||
|
||||
private static Component getCenterOnComponent(Window parent, Component centeredOnComponent) {
|
||||
|
||||
/*
|
||||
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
|
||||
|
||||
*/
|
||||
Component bestComponent = centeredOnComponent;
|
||||
if (SwingUtilities.isDescendingFrom(parent, bestComponent)) {
|
||||
return bestComponent;
|
||||
}
|
||||
|
||||
// by default, prefer to center over the active window
|
||||
KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
|
||||
Window activeWindow = kfm.getActiveWindow();
|
||||
bestComponent = activeWindow;
|
||||
if (SwingUtilities.isDescendingFrom(parent, bestComponent)) {
|
||||
return bestComponent;
|
||||
}
|
||||
|
||||
// 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(parent);
|
||||
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 bestComponent;
|
||||
}
|
||||
|
||||
// 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 Window getParentWindow(Component parent) {
|
||||
|
||||
/*
|
||||
|
@ -1841,7 +1846,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) {
|
||||
if (c instanceof Frame && isNonTransientWindow(c)) {
|
||||
return (Window) c;
|
||||
}
|
||||
c = c.getParent();
|
||||
|
@ -1850,6 +1855,15 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
}
|
||||
|
||||
private static boolean isNonTransientWindow(Component c) {
|
||||
|
||||
if (c == null || !c.isShowing()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (c instanceof DockingFrame) {
|
||||
return !((DockingFrame) c).isTransient();
|
||||
}
|
||||
|
||||
if (c instanceof DockingDialog) {
|
||||
DockingDialog d = (DockingDialog) c;
|
||||
DialogComponentProvider provider = d.getComponent();
|
||||
|
@ -1857,9 +1871,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
return false; // we have seen this in testing
|
||||
}
|
||||
|
||||
if (provider.isTransient()) {
|
||||
return false;
|
||||
}
|
||||
return !provider.isTransient();
|
||||
}
|
||||
|
||||
return (c instanceof Window);
|
||||
|
@ -1868,23 +1880,22 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
private static Window getActiveNonTransientWindow() {
|
||||
|
||||
KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
|
||||
Window activeWindow = kfm.getActiveWindow();
|
||||
if (!(activeWindow instanceof DockingDialog)) {
|
||||
return activeWindow;
|
||||
}
|
||||
|
||||
Window bestWindow = kfm.getActiveWindow();
|
||||
if (bestWindow instanceof DockingDialog) {
|
||||
// We do not want Task Dialogs becoming parents, as they will get closed when the
|
||||
// task is finished, closing any other child dialogs, which means that dialogs such
|
||||
// as message dialogs will too be closed
|
||||
DockingDialog d = (DockingDialog) activeWindow;
|
||||
Window ancestor = SwingUtilities.getWindowAncestor(d);
|
||||
if (d.isShowing() && isNonTransientWindow(d)) {
|
||||
DockingDialog d = (DockingDialog) bestWindow;
|
||||
if (isNonTransientWindow(d)) {
|
||||
return d;
|
||||
}
|
||||
|
||||
// The active window is not a suitable parent; try its parent
|
||||
if (ancestor.isShowing() && isNonTransientWindow(ancestor)) {
|
||||
return ancestor;
|
||||
bestWindow = SwingUtilities.getWindowAncestor(d);
|
||||
}
|
||||
|
||||
if (isNonTransientWindow(bestWindow)) {
|
||||
return bestWindow;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -40,7 +40,7 @@ public class SplashScreen extends JWindow {
|
|||
private static final Color DEFAULT_BACKGROUND_COLOR = new Color(243, 250, 255);
|
||||
|
||||
private static SplashScreen splashWindow; // splash window displayed while ghidra is coming up
|
||||
private static JFrame hiddenFrame;
|
||||
private static DockingFrame hiddenFrame;
|
||||
private static JLabel statusLabel;
|
||||
private static Timer hideSplashWindowTimer;
|
||||
|
||||
|
@ -250,6 +250,7 @@ public class SplashScreen extends JWindow {
|
|||
List<Image> list = ApplicationInformationDisplayFactory.getWindowIcons();
|
||||
hiddenFrame.setIconImages(list);
|
||||
hiddenFrame.setUndecorated(true);
|
||||
hiddenFrame.setTransient();
|
||||
}
|
||||
return hiddenFrame;
|
||||
}
|
||||
|
@ -279,10 +280,6 @@ public class SplashScreen extends JWindow {
|
|||
updateStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the status label on the splash screen window.
|
||||
* @param status
|
||||
*/
|
||||
private static void updateStatus(String status) {
|
||||
statusLabel.setText(status);
|
||||
}
|
||||
|
|
|
@ -125,8 +125,8 @@ public class TaskLauncher {
|
|||
* A convenience method to directly run a {@link Runnable} in a separate
|
||||
* thread as a {@link Task}, displaying a non-modal progress dialog.
|
||||
*
|
||||
* <p>This modal will be launched immediately, without delay. Typically this launcher will
|
||||
* delay showing the modal dialog in order to prevent the dialog from being show, just
|
||||
* <p>This modal will be launched immediately, without delay. Typically the launcher will
|
||||
* delay showing the modal dialog in order to prevent the dialog from being shown, just
|
||||
* to have it immediately go away. If you desire this default behavior, then do not use
|
||||
* this convenience method.
|
||||
*
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* 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.util.task;
|
||||
|
||||
import ghidra.util.Msg;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
/**
|
||||
* A task that will simply invoke the given runnable later in the Swing thread. This class is
|
||||
* useful for executing long running tasks in the swing thread while using the
|
||||
* {@link TaskLauncher} to show a modal dialog.
|
||||
*/
|
||||
public class InvokeInSwingTask extends Task {
|
||||
|
||||
private final Runnable runnable;
|
||||
|
||||
public InvokeInSwingTask( String title, Runnable runnable ) {
|
||||
super( title, false, false, true );
|
||||
this.runnable = runnable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run( TaskMonitor monitor ) {
|
||||
try {
|
||||
SwingUtilities.invokeAndWait( runnable );
|
||||
} catch (InterruptedException e) {
|
||||
Msg.showError(runnable, null, "Task Error", "Task interrupted: " + getTaskTitle(), e);
|
||||
} catch (InvocationTargetException e) {
|
||||
Msg.showError(runnable, null, "Task Error", "Unexpected task exception: " + getTaskTitle(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -37,7 +37,6 @@ import ghidra.framework.plugintool.PluginTool;
|
|||
import ghidra.framework.store.LockException;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.exception.NotFoundException;
|
||||
import ghidra.util.task.InvokeInSwingTask;
|
||||
import ghidra.util.task.TaskLauncher;
|
||||
import resources.ResourceManager;
|
||||
|
||||
|
@ -280,8 +279,7 @@ class FileActionManager {
|
|||
*/
|
||||
final boolean openProject(ProjectLocator projectLocator) {
|
||||
OpenTaskRunnable openRunnable = new OpenTaskRunnable(projectLocator);
|
||||
InvokeInSwingTask task = new InvokeInSwingTask("Opening Project", openRunnable);
|
||||
new TaskLauncher(task, tool.getToolFrame(), 0);
|
||||
TaskLauncher.launchModal("Opening Project", () -> Swing.runNow(openRunnable));
|
||||
return openRunnable.getResult();
|
||||
}
|
||||
|
||||
|
|
|
@ -765,7 +765,7 @@ public class FrontEndTool extends PluginTool implements OptionsChangeListener {
|
|||
|
||||
if (logProvider == null) {
|
||||
logProvider = new LogComponentProvider(this, logFile);
|
||||
showDialog(logProvider, getToolFrame());
|
||||
showDialog(logProvider);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -287,7 +287,7 @@ class RepositoryChooser extends DialogComponentProvider {
|
|||
|
||||
init(initURL);
|
||||
|
||||
tool.showDialog(this, tool.getToolFrame());
|
||||
tool.showDialog(this);
|
||||
|
||||
if (!okPressed) {
|
||||
return null;
|
||||
|
|
|
@ -25,7 +25,6 @@ import javax.swing.*;
|
|||
import javax.swing.border.TitledBorder;
|
||||
|
||||
import docking.DialogComponentProvider;
|
||||
import docking.DockingWindowManager;
|
||||
import docking.options.editor.ButtonPanelFactory;
|
||||
import docking.widgets.checkbox.GCheckBox;
|
||||
import docking.widgets.list.ListPanel;
|
||||
|
@ -120,7 +119,7 @@ public class SaveDataDialog extends DialogComponentProvider {
|
|||
initList();
|
||||
|
||||
if (!files.isEmpty()) {
|
||||
tool.showDialog(this, DockingWindowManager.getActiveInstance().getActiveComponent());
|
||||
tool.showDialog(this);
|
||||
}
|
||||
else {
|
||||
operationCompleted = true;
|
||||
|
@ -238,8 +237,8 @@ public class SaveDataDialog extends DialogComponentProvider {
|
|||
*/
|
||||
private void deselectAll() {
|
||||
clearStatusText();
|
||||
for (int i = 0; i < checkboxes.length; i++) {
|
||||
checkboxes[i].setSelected(false);
|
||||
for (GCheckBox checkboxe : checkboxes) {
|
||||
checkboxe.setSelected(false);
|
||||
}
|
||||
listPanel.repaint();
|
||||
}
|
||||
|
@ -359,13 +358,13 @@ public class SaveDataDialog extends DialogComponentProvider {
|
|||
@Override
|
||||
public void run(TaskMonitor monitor) {
|
||||
try {
|
||||
for (int i = 0; i < domainFiles.length; i++) {
|
||||
for (DomainFile domainFile : domainFiles) {
|
||||
if (monitor.isCancelled()) {
|
||||
break;
|
||||
}
|
||||
monitor.setProgress(0);
|
||||
monitor.setMessage("Saving " + domainFiles[i].getName());
|
||||
domainFiles[i].save(monitor);
|
||||
monitor.setMessage("Saving " + domainFile.getName());
|
||||
domainFile.save(monitor);
|
||||
}
|
||||
operationCompleted = !monitor.isCancelled();
|
||||
|
||||
|
|
|
@ -267,7 +267,7 @@ class WorkspacePanel extends JPanel implements WorkspaceChangeListener {
|
|||
// query the user for the name of the workspace
|
||||
InputDialog nameDialog = new InputDialog("Create New Workspace", "Workspace Name",
|
||||
ToolManager.DEFAULT_WORKSPACE_NAME);
|
||||
plugin.getTool().showDialog(nameDialog, (Component) null);
|
||||
plugin.getTool().showDialog(nameDialog);
|
||||
if (nameDialog.isCanceled()) {
|
||||
return; // user canceled
|
||||
}
|
||||
|
@ -342,7 +342,7 @@ class WorkspacePanel extends JPanel implements WorkspaceChangeListener {
|
|||
String workspaceName = activeWorkspace.getName();
|
||||
InputDialog nameDialog =
|
||||
new InputDialog("Rename Workspace", "Workspace Name", workspaceName);
|
||||
plugin.getTool().showDialog(nameDialog, (Component) null);
|
||||
plugin.getTool().showDialog(nameDialog);
|
||||
if (nameDialog.isCanceled()) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,6 @@ import docking.actions.PopupActionProvider;
|
|||
import docking.actions.ToolActions;
|
||||
import docking.framework.AboutDialog;
|
||||
import docking.framework.ApplicationInformationDisplayFactory;
|
||||
import docking.framework.SplashScreen;
|
||||
import docking.help.Help;
|
||||
import docking.help.HelpService;
|
||||
import docking.tool.ToolConstants;
|
||||
|
@ -552,7 +551,6 @@ public abstract class PluginTool extends AbstractDockingTool {
|
|||
else {
|
||||
fullName = toolName + "(" + instanceName + ")";
|
||||
}
|
||||
SplashScreen.updateSplashScreenStatus("Loading " + fullName + " ...");
|
||||
|
||||
restoreOptionsFromXml(root);
|
||||
setDefaultOptionValues();
|
||||
|
@ -968,8 +966,8 @@ public abstract class PluginTool extends AbstractDockingTool {
|
|||
saveAsAction.setMenuBarData(menuData);
|
||||
|
||||
saveAsAction.setEnabled(true);
|
||||
saveAsAction
|
||||
.setHelpLocation(new HelpLocation(ToolConstants.TOOL_HELP_TOPIC, "Tool_Changes"));
|
||||
saveAsAction.setHelpLocation(
|
||||
new HelpLocation(ToolConstants.TOOL_HELP_TOPIC, "Tool_Changes"));
|
||||
|
||||
addAction(saveAction);
|
||||
addAction(saveAsAction);
|
||||
|
@ -994,8 +992,8 @@ public abstract class PluginTool extends AbstractDockingTool {
|
|||
new String[] { ToolConstants.MENU_FILE, exportPullright, "Export Tool..." });
|
||||
menuData.setMenuSubGroup(Integer.toString(subGroup++));
|
||||
exportToolAction.setMenuBarData(menuData);
|
||||
exportToolAction
|
||||
.setHelpLocation(new HelpLocation(ToolConstants.TOOL_HELP_TOPIC, "Export_Tool"));
|
||||
exportToolAction.setHelpLocation(
|
||||
new HelpLocation(ToolConstants.TOOL_HELP_TOPIC, "Export_Tool"));
|
||||
addAction(exportToolAction);
|
||||
|
||||
DockingAction exportDefautToolAction =
|
||||
|
@ -1418,9 +1416,12 @@ public abstract class PluginTool extends AbstractDockingTool {
|
|||
* time the dialog is shown.
|
||||
*
|
||||
* @param dialogComponent the DialogComponentProvider object to be shown in a dialog.
|
||||
*
|
||||
* @deprecated dialogs are now always shown over the active window when possible
|
||||
*/
|
||||
@Deprecated
|
||||
public void showDialogOnActiveWindow(DialogComponentProvider dialogComponent) {
|
||||
DockingWindowManager.showDialogOnActiveWindow(dialogComponent);
|
||||
DockingWindowManager.showDialog(dialogComponent);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue