diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/console/ConsoleComponentProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/console/ConsoleComponentProvider.java index b295457a29..f5ee090cff 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/console/ConsoleComponentProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/console/ConsoleComponentProvider.java @@ -83,6 +83,13 @@ public class ConsoleComponentProvider extends ComponentProviderAdapter createActions(); } + @Override + public boolean canBeParent() { + // the console window may appear and be closed often and thus is not a suitable parent when + // in a window by itself + return false; + } + void init() { stderr = new PrintWriter(new ConsoleWriter(this, true)); stdin = new PrintWriter(new ConsoleWriter(this, false)); @@ -203,7 +210,7 @@ public class ConsoleComponentProvider extends ComponentProviderAdapter return; } - // NOTE: must be case sensitive otherwise the service will report that it has + // NOTE: must be case sensitive otherwise the service will report that it has // processed the request even if there are no matches boolean found = gotoService.goToQuery(currentAddress, new QueryData(word.word, true), null, null); @@ -285,8 +292,8 @@ public class ConsoleComponentProvider extends ComponentProviderAdapter } }; scrollAction.setDescription("Scroll Lock"); - scrollAction.setToolBarData( - new ToolBarData(ResourceManager.loadImage(SCROLL_LOCK_GIF), null)); + scrollAction + .setToolBarData(new ToolBarData(ResourceManager.loadImage(SCROLL_LOCK_GIF), null)); scrollAction.setEnabled(true); scrollAction.setSelected(scrollLock); @@ -316,7 +323,7 @@ public class ConsoleComponentProvider extends ComponentProviderAdapter // // sometimes an exception will occur while printing // the stack trace on an exception. - // if that happens catch it and manually print + // if that happens catch it and manually print // some information about it. // see org.jruby.exceptions.RaiseException // diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptComponentProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptComponentProvider.java index c9bf4421c5..73ce3145f3 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptComponentProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptComponentProvider.java @@ -136,6 +136,13 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter { updateTitle(); } + @Override + public boolean canBeParent() { + // the script window may be open and closed often as users run scripts and thus is not a + // suitable parent when in a window by itself + return false; + } + private void buildCategoryTree() { scriptRoot = new RootNode(); @@ -812,7 +819,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter { /* Unusual Algorithm - + The tree nodes represent categories, but do not contain nodes for individual scripts. We wish to remove any of the tree nodes that no longer represent script categories. (This can happen when a script is deleted or its category is changed.) @@ -1171,7 +1178,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter { @Override public void bundleBuilt(GhidraBundle bundle, String summary) { - // on enable, build can happen before the refresh populates the info manager with this + // on enable, build can happen before the refresh populates the info manager with this // bundle's scripts, so allow for the possibility and create the info here. if (!(bundle instanceof GhidraSourceBundle)) { return; @@ -1180,7 +1187,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter { GhidraSourceBundle sourceBundle = (GhidraSourceBundle) bundle; ResourceFile sourceDirectory = sourceBundle.getFile(); if (summary == null) { - // a null summary means the build didn't change anything, so use any errors from + // a null summary means the build didn't change anything, so use any errors from // the last build for (ResourceFile sourceFile : sourceBundle.getAllErrors().keySet()) { if (sourceFile.getParentFile().equals(sourceDirectory)) { diff --git a/Ghidra/Framework/Docking/src/main/java/docking/ComponentProvider.java b/Ghidra/Framework/Docking/src/main/java/docking/ComponentProvider.java index 3d798d782f..408ad63a14 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/ComponentProvider.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/ComponentProvider.java @@ -30,11 +30,11 @@ import ghidra.util.exception.AssertException; import utilities.util.reflection.ReflectionUtilities; /** - * Abstract base class for creating dockable GUI components within a tool. + * Abstract base class for creating dockable GUI components within a tool. *

* The one method that must be implemented is {@link #getComponent()} which is where the top level * Swing JComponent is returned to be docked into the tool. Typically, the GUI components are - * created in the constructor along with any local actions for the provider. The getComponent() + * created in the constructor along with any local actions for the provider. The getComponent() * method then simply returns the top level component previously created by this provider. *

* There are many other methods for configuring how to dock the component, set title information, @@ -43,7 +43,7 @@ import utilities.util.reflection.ReflectionUtilities; * how the GUI component behaves within the tool, and then add the business logic that uses and reacts * to the GUI components created in this provider. *

- * To effectively use this class you merely need to create your component, add your actions to + * To effectively use this class you merely need to create your component, add your actions to * this class ({@link #addLocalAction(DockingActionIf)}) and then add this provider to the tool * ({@link #addToTool()}). *

@@ -51,7 +51,7 @@ import utilities.util.reflection.ReflectionUtilities; *

@@ -61,10 +61,10 @@ import utilities.util.reflection.ReflectionUtilities; *
  • {@link #componentActivated()} and {@link #componentDeactived()} *
  • {@link #componentHidden()} and {@link #componentShown()} * - * + * *

    * Show Provider Action - Each provider has an action to show the provider. For - * typical, non-transient providers (see {@link #setTransient()}) the action will appear in + * typical, non-transient providers (see {@link #setTransient()}) the action will appear in * the tool's Window menu. You can have your provider also appear in the tool's toolbar * by calling {@link #addToTool()}. *

    @@ -178,7 +178,7 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext * A method that allows children to set the instanceID to a desired value (useful for * restoring saved IDs). *

    - * Note: this can be called only once during the lifetime of the calling instance; otherwise, an + * Note: this can be called only once during the lifetime of the calling instance; otherwise, an * {@link AssertException} will be thrown. * @param newID the new ID of this provider */ @@ -220,7 +220,7 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext /** * Returns true if this provider has focus - * + * * @return true if this provider has focus */ public boolean isFocusedProvider() { @@ -319,12 +319,12 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext } /** - * A signal used when installing actions. Some actions are only added to a given window + * A signal used when installing actions. Some actions are only added to a given window * if there is a provider in that window that can work with that action. Providers can return * a context class from this method to control whether dependent actions get added. Most - * providers return null for this method, which means they will not have any dependent + * providers return null for this method, which means they will not have any dependent * actions added to windows other than the primary application window. - * + * * @return a class representing the desired context type or null; */ public Class getContextType() { @@ -351,8 +351,8 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext * This is the callback that will happen when the user presses the 'X' button of a provider. * Transient providers will be removed from the tool completely. Non-transient providers * will merely be hidden. - * - *

    Subclasses may override this method to prevent a provider from being closed; for + * + *

    Subclasses may override this method to prevent a provider from being closed; for * example, if an editor has unsaved changes, then this method could prevent the close from * happening. */ @@ -380,7 +380,7 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext } /** - * Notifies the provider that the component is being hidden. This happens when the + * Notifies the provider that the component is being hidden. This happens when the * provider is being closed. */ public void componentHidden() { @@ -423,7 +423,7 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext /** * A default method for creating an action context for this provider, using the given * {@link ActionContext#getContextObject() context object} - * + * * @param contextObject the provider-specific context object * @return the new context */ @@ -434,7 +434,7 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext /** * A default method for creating an action context for this provider, using the given * {@link ActionContext#getContextObject() context object} and component - * + * * @param sourceComponent the component that is the target of the context being created * @param contextObject the provider-specific context object * @return the new context @@ -451,10 +451,10 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext } /** - * Returns the general HelpLocation for this provider. Should return null only if no + * Returns the general HelpLocation for this provider. Should return null only if no * help documentation exists. - * - * @return the help location + * + * @return the help location */ public HelpLocation getHelpLocation() { return helpLocation; @@ -546,7 +546,7 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext /** * Returns the optionally set text to display in the tab for a component provider. The * text returned from {@link #getTitle()} will be used by default. - * + * * @return the optionally set text to display in the tab for a component provider. * @see #setTabText(String) */ @@ -558,7 +558,7 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext /** * Sets the default key binding that will show this provider when pressed. This value can * be changed by the user and saved as part of the Tool options. - * + * * @param kbData the key binding */ protected void setKeyBinding(KeyBindingData kbData) { @@ -596,7 +596,7 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext } /** - * Signals that this provider's action for showing the provider should appear in the main + * Signals that this provider's action for showing the provider should appear in the main * toolbar */ protected void addToToolbar() { @@ -629,9 +629,21 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext } /** - * A special marker that indicates this provider is a snapshot of a primary provider, + * Returns true if the window containing this provider can be used as a parent window when + * showing system windows. All providers will return true from this method by default. This + * method is intended for short-lived providers to signal that their window should not be made + * the parent of new windows. + * + * @return true if this provider can be a parent + */ + public boolean canBeParent() { + return true; + } + + /** + * A special marker that indicates this provider is a snapshot of a primary provider, * somewhat like a picture of the primary provider. - * + * * @return true if a snapshot */ public boolean isSnapshot() { @@ -667,9 +679,9 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext /** * Sets the window menu group. If the window menu group is null, the corresponding window menu - * item will appear in the root menu, otherwise it will appear in a + * item will appear in the root menu, otherwise it will appear in a * sub-menu named group. - * + * * @param group the name of the window's sub-menu for this provider */ protected void setWindowMenuGroup(String group) { @@ -678,10 +690,10 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext /** * The initial {@link WindowPosition} of this provider. If a {@link #getWindowGroup() window - * group} is provided, then this position is relative to that provider. Otherwise, this + * group} is provided, then this position is relative to that provider. Otherwise, this * position is relative to the tool window. - * - * @return The initial {@link WindowPosition} of this provider. + * + * @return The initial {@link WindowPosition} of this provider. */ public WindowPosition getDefaultWindowPosition() { return defaultWindowPosition; @@ -690,8 +702,8 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext /** * Sets the default position of this provider when being shown for the first time. If the * providers position in the tool has been saved before, then this value is ignored. - * - * @param windowPosition the position + * + * @param windowPosition the position * @see #getDefaultWindowPosition() */ protected void setDefaultWindowPosition(WindowPosition windowPosition) { @@ -701,13 +713,13 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext /** * The position of this provider when being placed with other members of the same group. As * an example, assume this provider is being shown for the first time while there is another - * member of its {@link #getWindowGroup() window group} already visible. Further, assume + * member of its {@link #getWindowGroup() window group} already visible. Further, assume * that this method will return {@link WindowPosition#STACK}. This provider will then be * stacked upon the already showing provider. *

    - * To determine where this provider should be initially shown, + * To determine where this provider should be initially shown, * see {@link #getDefaultWindowPosition()}. - * + * * @return The position of this provider when being placed with other members of the same group. */ public WindowPosition getIntraGroupPosition() { @@ -716,7 +728,7 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext /** * See {@link #getIntraGroupPosition()}. - * + * * @param position the new position */ public void setIntraGroupPosition(WindowPosition position) { @@ -724,18 +736,18 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext } /** - * Returns an optional group designator that, if non-null, the docking window manager uses to + * Returns an optional group designator that, if non-null, the docking window manager uses to * determine the initial location of the new component relative to any existing instances - * of this component Provider. + * of this component Provider. *

    - * The docking window manager will use {@link #getIntraGroupPosition() Intra-group Position} - * to decide where to place this provider inside of the already open instances of the + * The docking window manager will use {@link #getIntraGroupPosition() Intra-group Position} + * to decide where to place this provider inside of the already open instances of the * same group. The default position is 'stack', which results in the new instance being * stacked with other instances of this provider that have the same group unless that instance is * the active provider or is currently stacked with the active provider. (This is to prevent * new windows from covering the active window). - * - * @return the window group + * + * @return the window group */ public String getWindowGroup() { return group; @@ -743,7 +755,7 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext /** * Sets the window group. See {@link #getWindowGroup()}. - * + * * @param group the group for this provider. */ protected void setWindowGroup(String group) { @@ -808,14 +820,14 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext } /** - * Register a name and/or owner change to a provider so that old tools can restore those - * provider windows to their old position and size. Note you must supply all four - * arguments. If the name or owner did not change, use the name or owner that did not change + * Register a name and/or owner change to a provider so that old tools can restore those + * provider windows to their old position and size. Note you must supply all four + * arguments. If the name or owner did not change, use the name or owner that did not change * for both the old and new values. - * - *

    Note: when you make use of this method, please signal when it is safe to remove + * + *

    Note: when you make use of this method, please signal when it is safe to remove * its usage. - * + * * @param oldName the old name of the provider. * @param oldOwner the old owner of the provider. * @param newName the new name of the provider. If the name did not change, use the old name here. diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java b/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java index a89c66c022..e525d08419 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java @@ -114,7 +114,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Constructs a new DockingWindowManager - * + * * @param tool the tool * @param images the images to use for windows in this window manager */ @@ -163,7 +163,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Sets the help service for the all docking window managers. - * + * * @param helpSvc the help service to use. */ public static void setHelpService(HelpService helpSvc) { @@ -175,7 +175,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Returns the global help service. - * + * * @return the global help service. */ public static HelpService getHelpService() { @@ -192,7 +192,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Get the docking window manager instance which corresponds to the specified window. - * + * * @param win the window for which to find its parent docking window manager. * @return docking window manager or null if unknown. */ @@ -226,7 +226,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * A convenience method for getting the window for component and then calling * {@link #getInstanceForWindow(Window)}. - * + * * @param component The component for which to get the associated {@link DockingWindowManager} * instance. * @return The {@link DockingWindowManager} instance associated with component @@ -246,7 +246,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Returns the last active docking window manager which is visible. - * + * * @return the last active docking window manager which is visible. */ public static synchronized DockingWindowManager getActiveInstance() { @@ -268,7 +268,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Returns a new list of all DockingWindowManager instances known to exist, ordered from least * to most-recently active. - * + * * @return a new list of all DockingWindowManager instances know to exist. */ public static synchronized List getAllDockingWindowManagers() { @@ -277,7 +277,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * The specified docking window manager has just become active - * + * * @param mgr the window manager that became active. */ static synchronized void setActiveManager(DockingWindowManager mgr) { @@ -289,7 +289,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Register a specific Help content URL for a component. The DocWinListener will be notified * with the helpURL if the specified component 'c' has focus and the help key is pressed. - * + * * @param c component on which to set help. * @param helpLocation help content location */ @@ -299,7 +299,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Set the tool name which is displayed as the title for all windows. - * + * * @param toolName tool name / title */ public void setToolName(String toolName) { @@ -308,7 +308,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Set the Icon for all windows. - * + * * @param icon image icon */ public void setIcon(ImageIcon icon) { @@ -339,7 +339,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Returns the tool that owns this manager - * + * * @return the tool */ public Tool getTool() { @@ -348,7 +348,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Returns the root window frame. - * + * * @return the root window frame. */ public JFrame getRootFrame() { @@ -360,7 +360,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * 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. */ public void setDefaultComponent(ComponentProvider provider) { @@ -369,7 +369,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Get the window that contains the specified Provider's component - * + * * @param provider component provider * @return window or null if component is not visible or not found */ @@ -383,7 +383,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Get the provider that contains the specified component - * + * * @param c the component * @return the provider; null if now containing provider is found */ @@ -406,7 +406,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Returns the active window (or the root window if nobody has yet been made active). - * + * * @return the active window. */ public Window getActiveWindow() { @@ -419,7 +419,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Returns the current active component. - * + * * @return the current active component. */ public Component getActiveComponent() { @@ -431,7 +431,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Returns the component which has focus - * + * * @return the placeholder */ public ComponentPlaceholder getFocusedComponent() { @@ -451,7 +451,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Sets the visible state of the set of docking windows. - * + * * @param state if true the main window and all sub-windows are set to be visible. If state is * false, then all windows are set to be invisible. */ @@ -467,7 +467,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Returns true if the set of windows associated with this window manager are visible. - * + * * @return true if the set of windows associated with this window manager are visible. */ public boolean isVisible() { @@ -476,7 +476,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Returns true if the specified provider's component is visible - * + * * @param provider component provider * @return true if the specified provider's component is visible */ @@ -491,7 +491,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Adds a new component (via the provider) to be managed by this docking window manager. The * component is initially hidden. - * + * * @param provider the component provider */ public void addComponent(ComponentProvider provider) { @@ -501,7 +501,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Adds a new component (vial the provider) to be managed by this docking window manager. The * component will be initially shown or hidden based on the the "show" parameter. - * + * * @param provider the component provider. * @param show indicates whether or not the component should be initially shown. */ @@ -538,7 +538,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Returns the ComponentProvider with the given name. If more than one provider exists with the * name, one will be returned, but it could be any one of them. - * + * * @param name the name of the provider to return. * @return a provider with the given name, or null if no providers with that name exist. */ @@ -622,7 +622,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Set whether a component's header should be shown; the header is the component that is dragged * in order to move the component within the tool, or out of the tool into a separate window. - * + * * @param provider provider of the visible component in the tool * @param b true means to show the header */ @@ -663,7 +663,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Returns the current subtitle for the component for the given provider. - * + * * @param provider the component provider of the component for which to get its subtitle. * @return the current subtitle for the component for the given provider. */ @@ -678,7 +678,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Removes the ComponentProvider (component) from the docking windows manager. The location of * the window will be remember and reused if the provider is added back in later. - * + * * @param provider the provider to be removed. */ public void removeComponent(ComponentProvider provider) { @@ -730,7 +730,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Returns any action that is bound to the given keystroke for the tool associated with this * DockingWindowManager instance. - * + * * @param keyStroke The keystroke to check for key bindings. * @return The action that is bound to the keystroke, or null of there is no binding for the * given keystroke. @@ -934,7 +934,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Generates a JDOM element object for saving the window managers state to XML. - * + * * @param rootXMLElement The root element to which to save XML data. */ public void saveToXML(Element rootXMLElement) { @@ -955,7 +955,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Save this docking window manager's window layout and positioning information as XML. - * + * * @return An XML element with the above information. */ public Element saveWindowingDataToXml() { @@ -964,7 +964,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Restores the docking window managers state from the XML information. - * + * * @param rootXMLElement JDOM element from which to extract the state information. */ public void restoreFromXML(Element rootXMLElement) { @@ -974,7 +974,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Restore to the docking window manager the layout and positioning information from XML. - * + * * @param rootXMLElement JDOM element from which to extract the state information. */ public void restoreWindowDataFromXml(Element rootXMLElement) { @@ -1098,7 +1098,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Moves the component associated with the given source placeholder object from its current * docked location to its own window that will be anchored at the given point. - * + * * @param source the component placeholder containing the component to be moved. * @param p the location at which to create a new window for the component. */ @@ -1364,7 +1364,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Display an text edit box on top of the specified component. - * + * * @param defaultText initial text to be displayed in edit box * @param c component over which the edit box will be placed * @param r specifies the bounds of the edit box relative to the component. The height is @@ -1639,7 +1639,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder * Adds a PreferenceState object to this window manager instance that is bound to the given key. * When the state of the tool using this window manager is saved, then the mapped preferences * will also be saved. - * + * * @param key The key with which to store the preferences. * @param state The state object to store. * @see #getPreferenceState(String) @@ -1655,7 +1655,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Gets a preferences state object stored with the given key. The state objects are loaded from * persistent storage when the tool using this window manager has its state loaded. - * + * * @param key The key with which to store the preferences. * @return the PrefrenceState object stored by the given key, or null if one does not exist * @see #putPreferenceState(String, PreferenceState) @@ -1666,7 +1666,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Removes the Preferences state for the given key. - * + * * @param key the key to the preference state to be removed */ public void removePreferenceState(String key) { @@ -1739,7 +1739,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Shows the dialog using the given parent window using the optional component for positioning. - * + * *

    * 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 @@ -1890,7 +1890,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /* Note: Which window should be the parent of the dialog when the user does not specify? - + Some use cases; a dialog is shown from: 1) A toolbar action 2) A component provider's code @@ -1898,7 +1898,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder 4) A background thread 5) The help window 6) A modal password dialog appears over the splash screen - + It seems like the parent should be the active window for 1-2. Case 3 should probably use the window of the dialog provider. Case 4 should probably use the main tool frame, since the user may be @@ -1906,12 +1906,12 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder active window, we can default to the tool's frame. Case 5 should use the help window. Case 6 should use the splash screen as the parent. - + We have not yet solidified how we should parent. This documentation is meant to move us towards clarity as we find Use Cases that don't make sense. (Once we finalize our understanding, we should update the javadoc to list exactly where the given Dialog Component will be shown.) - + Use Case A -The user presses an action on a toolbar from a window on screen 1, while the main tool frame is on screen 2. We want the popup window to appear on screen @@ -1930,12 +1930,12 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder 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 window so that a dialog will appear in the user's view. If we find a case where this is not desired, then document it here. - + */ DockingWindowManager dwm = getActiveInstance(); @@ -1966,7 +1966,14 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder } if (c instanceof DockingFrame) { - return !((DockingFrame) c).isTransient(); + + DockingFrame frame = (DockingFrame) c; + if (frame.isTransient()) { + return false; + } + + // consider any window transient if all of its contained providers cannot be parents + return hasAnyParentableProvider(frame); } if (c instanceof DockingDialog) { @@ -1986,6 +1993,21 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder return (c instanceof Window); } + private static boolean hasAnyParentableProvider(Window window) { + boolean hasAnyParentableProvider = false; + DockingWindowManager dwm = getInstanceForWindow(window); + WindowNode node = dwm.root.getNodeForWindow(window); + List placeholders = node.getActiveComponents(); + for (ComponentPlaceholder placeholder : placeholders) { + DockableComponent dc = placeholder.getComponent(); + ComponentProvider provider = dc.getComponentProvider(); + hasAnyParentableProvider |= provider.canBeParent(); + + } + + return hasAnyParentableProvider; + } + private static Window getJavaActiveWindow() { KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); Window activeWindow = kfm.getActiveWindow(); @@ -2041,7 +2063,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Returns true if a status bar is present. - * + * * @return true if a status bar is present. */ public boolean hasStatusBar() { @@ -2051,7 +2073,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Add a new status item component to the status area. The preferred height and border for the * component will be altered. The components preferred width will be preserved. - * + * * @param c the status item component to add * @param addBorder True signals to add a border to the status area * @param rightSide component will be added to the right-side of the status area if true, else @@ -2063,7 +2085,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Remove the specified status item. - * + * * @param c status component previously added. */ public void removeStatusItem(JComponent c) { @@ -2072,7 +2094,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Set the status text in the active component window - * + * * @param text status text */ public void setStatusText(String text) { @@ -2100,7 +2122,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Get the status text in the active component window - * + * * @return string currently displayed in the Status display area */ public String getStatusText() { @@ -2144,7 +2166,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Tests if the given component is one of a known list of component classes that we don't ever * want to get keyboard focus. Currently excluded is JScrollPane - * + * * @param c the component to test for exclusion * @return true if the component should not be allowed to have keyboard focus. */ @@ -2155,7 +2177,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Sets the mode such that all satellite docking windows always appear on top of the root window - * + * * @param windowsOnTop true to set mode to on top, false to disable on top mode. */ public void setWindowsOnTop(boolean windowsOnTop) { @@ -2165,7 +2187,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Returns true if the window mode is "satellite windows always on top of root window". - * + * * @return true if the window mode is "satellite windows always on top of root window". */ public boolean isWindowsOnTop() { @@ -2174,7 +2196,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Returns a list with all the windows in the windowStack. Used for testing. - * + * * @param includeMain if true, include the main root window. * @return a list with all the windows in the windowStack. Used for testing. */ @@ -2218,7 +2240,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Returns the root window. - * + * * @return the root window. */ public Window getMainWindow() { @@ -2249,7 +2271,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Shows a popup menu over the given component. If this given component is not part of the * docking windows hierarchy, then no action is taken. - * + * * @param component the component */ public static void showContextMenu(Component component) { @@ -2290,7 +2312,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Adds the given popup action provider to this tool. This provider will be called each time the * popup menu is about to be shown. - * + * * @param provider the provider */ public void addPopupActionProvider(PopupActionProvider provider) { @@ -2299,7 +2321,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Removes the given popup action provider - * + * * @param provider the provider */ public void removePopupActionProvider(PopupActionProvider provider) { @@ -2337,7 +2359,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * Returns the default action context for the tool - * + * * @return the default action context for the tool */ public ActionContext getDefaultToolContext() { @@ -2378,11 +2400,11 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder /** * This call will notify any context listeners that the context has changed. - * + * *

    * Our {@link #contextChanged(ComponentProvider)} method will eventually call back into this * method after any buffering has taken place. - * + * * @param context the context */ void doContextChanged(ActionContext context) {