diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java index 15dee13241..04df545c3a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java @@ -173,8 +173,7 @@ public class CodeBrowserClipboardProvider extends ByteCopier return pasteByteString(string); } - tool.setStatusInfo("Paste failed: unsupported data type"); - tool.getToolFrame().getToolkit().beep(); + tool.setStatusInfo("Paste failed: unsupported data type", true); } catch (Exception e) { String msg = e.getMessage(); @@ -182,8 +181,7 @@ public class CodeBrowserClipboardProvider extends ByteCopier msg = e.toString(); Msg.error(this, "Unexpected Exception: " + e.getMessage(), e); } - tool.setStatusInfo("Paste failed: " + msg); - tool.getToolFrame().getToolkit().beep(); + tool.setStatusInfo("Paste failed: " + msg, true); } return false; } @@ -405,8 +403,7 @@ public class CodeBrowserClipboardProvider extends ByteCopier String message = "Copy failed: " + msg; Msg.error(this, message, e); - tool.setStatusInfo(message); - tool.getToolFrame().getToolkit().beep(); + tool.setStatusInfo(message, true); } return null; @@ -440,8 +437,7 @@ public class CodeBrowserClipboardProvider extends ByteCopier if (msg == null) { msg = e.toString(); } - tool.setStatusInfo("Paste failed: " + msg); - tool.getToolFrame().getToolkit().beep(); + tool.setStatusInfo("Paste failed: " + msg, true); } return false; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/ByteCopier.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/ByteCopier.java index c56ca18b5b..7bec236ec0 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/ByteCopier.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/ByteCopier.java @@ -125,8 +125,7 @@ public abstract class ByteCopier { String string = (String) object; if (!isOnlyAsciiBytes(string)) { tool.setStatusInfo("Paste string contains non-text ascii bytes. " + - "Only the ascii text will be pasted."); - tool.getToolFrame().getToolkit().beep(); + "Only the ascii text will be pasted.", true); string = keepOnlyAsciiBytes(string); } @@ -219,8 +218,7 @@ public abstract class ByteCopier { protected boolean pasteBytes(Transferable pasteData) throws UnsupportedFlavorException, IOException { if (!supportsPasteTransferable(pasteData)) { - tool.setStatusInfo("Paste failed: No valid data on clipboard"); - tool.getToolFrame().getToolkit().beep(); + tool.setStatusInfo("Paste failed: No valid data on clipboard", true); return false; } @@ -249,8 +247,7 @@ public abstract class ByteCopier { String validString = string; if (!isOnlyAsciiBytes(string)) { tool.setStatusInfo("Pasted string contained non-text ascii bytes. " + - "Only the ascii text was pasted."); - tool.getToolFrame().getToolkit().beep(); + "Only the ascii text was pasted.", true); validString = keepOnlyAsciiBytes(string); } @@ -258,7 +255,7 @@ public abstract class ByteCopier { byte[] bytes = getBytes(validString); if (bytes == null) { status = "Improper data format (expected sequence of hex bytes)"; - tool.getToolFrame().getToolkit().beep(); + tool.beep(); return false; } @@ -270,13 +267,13 @@ public abstract class ByteCopier { for (int i = 0; i < byteCount;) { if (curAddr == null) { status = "Not enough addresses to paste bytes"; - tool.getToolFrame().getToolkit().beep(); + tool.beep(); return false; } CodeUnit curCodeUnit = listing.getCodeUnitContaining(curAddr); if (!(curCodeUnit instanceof Data) || ((Data) curCodeUnit).isDefined()) { status = "Cannot paste on top of defined instructions/data"; - tool.getToolFrame().getToolkit().beep(); + tool.beep(); return false; } int length = curCodeUnit.getLength(); diff --git a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerClipboardProvider.java b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerClipboardProvider.java index 7393fc7230..3edbd252b8 100644 --- a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerClipboardProvider.java +++ b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerClipboardProvider.java @@ -86,8 +86,7 @@ public class ByteViewerClipboardProvider extends ByteCopier @Override public boolean paste(Transferable pasteData) { if (!supportsPasteTransferable(pasteData)) { - tool.setStatusInfo("Paste failed: No valid data on clipboard"); - tool.getToolFrame().getToolkit().beep(); + tool.setStatusInfo("Paste failed: No valid data on clipboard", true); return false; } @@ -96,8 +95,7 @@ public class ByteViewerClipboardProvider extends ByteCopier return pasteBytes(pasteData); } catch (Exception e) { - tool.setStatusInfo("Paste failed: " + e.getMessage()); - tool.getToolFrame().getToolkit().beep(); + tool.setStatusInfo("Paste failed: " + e.getMessage(), true); } return false; } diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FGClipboardProvider.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FGClipboardProvider.java index f1ba1b11e2..f1f733145e 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FGClipboardProvider.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FGClipboardProvider.java @@ -86,8 +86,7 @@ public class FGClipboardProvider extends CodeBrowserClipboardProvider { if (msg == null) { msg = e.toString(); } - tool.setStatusInfo("Copy failed: " + msg); - tool.getToolFrame().getToolkit().beep(); + tool.setStatusInfo("Copy failed: " + msg, true); } return null; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTPlugin.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTPlugin.java index d581f70a88..3ca1573024 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTPlugin.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTPlugin.java @@ -159,8 +159,7 @@ public class VTPlugin extends Plugin { Preferences.setProperty(SHOW_HELP_PREFERENCE, "No"); Preferences.store(); - URL url = - ResourceManager.getResource("help/topics/VersionTrackingPlugin/VT_Workflow.html"); + URL url = ResourceManager.getResource("help/topics/VersionTrackingPlugin/VT_Workflow.html"); if (url == null) { Msg.showError(this, null, "Help Not Found", "Unable to find the Version Tracking workflow help"); @@ -396,7 +395,7 @@ public class VTPlugin extends Plugin { */ static void showBusyToolMessage(PluginTool tool) { JFrame toolFrame = tool.getToolFrame(); - toolFrame.getToolkit().beep(); + tool.beep(); Msg.showInfo(VTPlugin.class, toolFrame, "Tool \"" + tool.getName() + "\" Busy", "You must stop all background tasks before exiting."); } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java b/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java index e8fd9e41e4..8b820875a4 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java @@ -1909,7 +1909,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder } /** - * Set the status text in the active component window. + * Set the status text in the active component window * @param text status text */ public void setStatusText(String text) { @@ -1918,6 +1918,30 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder } } + /** + * Set the status text in the active component window + * + * @param text string to be displayed in the Status display area + * @param beep whether to beep or not + */ + public void setStatusText(String text, boolean beep) { + if (root == null) { + return; + } + + setStatusText(text); + if (beep) { + Toolkit.getDefaultToolkit().beep(); + } + } + + /** + * A convenience method to make an attention-grabbing noise to the user + */ + public static void beep() { + Toolkit.getDefaultToolkit().beep(); + } + /** * Set the menu group associated with a cascaded submenu. This allows * a cascading menu item to be grouped with a specific set of actions. diff --git a/Ghidra/Framework/Docking/src/main/java/docking/action/MultipleKeyAction.java b/Ghidra/Framework/Docking/src/main/java/docking/action/MultipleKeyAction.java index a588c091b1..a57fc703df 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/action/MultipleKeyAction.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/action/MultipleKeyAction.java @@ -21,7 +21,7 @@ import java.util.*; import javax.swing.*; import docking.*; -import ghidra.util.SystemUtilities; +import ghidra.util.Swing; /** * Action that manages multiple PluginActions mapped to this action's key binding. @@ -146,7 +146,6 @@ public class MultipleKeyAction extends DockingKeyBindingAction { } // If more than one action, prompt user for selection - JFrame rootFrame = winMgr.getRootFrame(); if (list.size() > 1) { // popup dialog to show multiple actions if (dialog == null) { @@ -159,7 +158,7 @@ public class MultipleKeyAction extends DockingKeyBindingAction { // doing the show in an invoke later seems to fix a strange swing bug that lock up // the program if you tried to invoke a new action too quickly after invoking // it the first time - SystemUtilities.runSwingLater(() -> winMgr.showDialog(dialog)); + Swing.runLater(() -> DockingWindowManager.showDialog(dialog)); } else if (list.size() == 1) { final ExecutableKeyActionAdapter actionProxy = list.get(0); @@ -168,8 +167,7 @@ public class MultipleKeyAction extends DockingKeyBindingAction { } else { String name = (String) getValue(Action.NAME); - winMgr.setStatusText("Action (" + name + ") not valid in this context!"); - rootFrame.getToolkit().beep(); + winMgr.setStatusText("Action (" + name + ") not valid in this context!", true); } } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/PluginTool.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/PluginTool.java index 1d2a76399a..1e45ab40c7 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/PluginTool.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/PluginTool.java @@ -375,6 +375,13 @@ public abstract class PluginTool extends AbstractDockingTool serviceMgr.removeServiceListener(listener); } + /** + * A convenience method to make an attention-grabbing noise to the user + */ + public void beep() { + DockingWindowManager.beep(); + } + /** * Sets the provider that should get the default focus when no component has focus. * @param provider the provider that should get the default focus when no component has focus. @@ -1194,7 +1201,7 @@ public abstract class PluginTool extends AbstractDockingTool taskMgr.stop(false); } else { - getToolFrame().getToolkit().beep(); + beep(); Msg.showInfo(getClass(), getToolFrame(), "Tool Busy", "You must stop all background tasks before exiting."); return false;