mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GT-2960 - Docking Actions - Consolidated the multiple methods of adding
dynamic popup actions
This commit is contained in:
parent
785eb5a2a5
commit
ab2a390fca
37 changed files with 375 additions and 341 deletions
|
@ -21,6 +21,7 @@ import java.util.*;
|
|||
import javax.swing.JFrame;
|
||||
|
||||
import docking.action.DockingActionIf;
|
||||
import docking.actions.PopupActionProvider;
|
||||
import docking.actions.ToolActions;
|
||||
import ghidra.framework.options.ToolOptions;
|
||||
import ghidra.util.Swing;
|
||||
|
@ -123,6 +124,16 @@ public abstract class AbstractDockingTool implements DockingTool {
|
|||
return toolActions.getAllActions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPopupActionProvider(PopupActionProvider provider) {
|
||||
winMgr.addPopupActionProvider(provider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePopupActionProvider(PopupActionProvider provider) {
|
||||
winMgr.removePopupActionProvider(provider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<DockingActionIf> getDockingActionsByOwnerName(String owner) {
|
||||
return toolActions.getActions(owner);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* 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.
|
||||
|
@ -16,7 +15,12 @@
|
|||
*/
|
||||
package docking;
|
||||
|
||||
import java.awt.Component;
|
||||
|
||||
/**
|
||||
* A listener interface to know when a component has been
|
||||
* made {@link Component#isDisplayable() displayable}
|
||||
*/
|
||||
public interface ComponentLoadedListener {
|
||||
public void componentLoaded(DockingWindowManager windowManager);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ import docking.actions.ActionAdapter;
|
|||
import docking.actions.KeyBindingUtils;
|
||||
import docking.event.mouse.GMouseListenerAdapter;
|
||||
import docking.menu.DockingToolbarButton;
|
||||
import docking.util.*;
|
||||
import docking.util.AnimationUtils;
|
||||
import docking.widgets.label.GDHtmlLabel;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.exception.AssertException;
|
||||
|
@ -43,9 +43,8 @@ import utility.function.Callback;
|
|||
* Base class used for creating dialogs in Ghidra. Subclass this to create a dialog provider that has
|
||||
* all the gui elements to appear in the dialog, then use tool.showDialog() to display your dialog.
|
||||
*/
|
||||
|
||||
public class DialogComponentProvider
|
||||
implements TaskListener, StatusListener, ActionContextProvider {
|
||||
implements ActionContextProvider, StatusListener, TaskListener {
|
||||
|
||||
private static final Color WARNING_COLOR = new Color(0xff9900);
|
||||
|
||||
|
@ -1369,5 +1368,4 @@ public class DialogComponentProvider
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ public class DialogComponentProviderPopupActionManager {
|
|||
MenuGroupMap menuGroupMap = actionManager.getMenuGroupMap();
|
||||
MenuManager menuMgr =
|
||||
new MenuManager("Popup", '\0', null, true, popupMenuHandler, menuGroupMap);
|
||||
populatePopupMenuActions(actionContext, menuMgr);
|
||||
populatePopupMenuActions(dwm, menuMgr, actionContext);
|
||||
if (menuMgr.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -85,7 +85,8 @@ public class DialogComponentProviderPopupActionManager {
|
|||
popupMenu.show(c, e.getX(), e.getY());
|
||||
}
|
||||
|
||||
private void populatePopupMenuActions(ActionContext actionContext, MenuManager menuMgr) {
|
||||
private void populatePopupMenuActions(DockingWindowManager dwm, MenuManager menuMgr,
|
||||
ActionContext actionContext) {
|
||||
|
||||
Iterator<DockingActionIf> iter = popupActions.iterator();
|
||||
while (iter.hasNext()) {
|
||||
|
@ -112,6 +113,18 @@ public class DialogComponentProviderPopupActionManager {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<DockingActionIf> tempActions = dwm.getTemporaryPopupActions(actionContext);
|
||||
if (tempActions != null) {
|
||||
for (DockingActionIf action : tempActions) {
|
||||
MenuData popupMenuData = action.getPopupMenuData();
|
||||
if (popupMenuData != null && action.isValidContext(actionContext) &&
|
||||
action.isAddToPopup(actionContext)) {
|
||||
action.setEnabled(action.isEnabledForContext(actionContext));
|
||||
menuMgr.addAction(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
|
|
@ -1,44 +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 docking;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import docking.action.DockingActionIf;
|
||||
|
||||
/**
|
||||
* Listener interface for the object to be notified when the user closes the
|
||||
* docking windows manager or initiates a popup menu.
|
||||
*/
|
||||
public interface DockWinListener {
|
||||
/**
|
||||
* Notification triggered when the user presses the "x" button in the main tool frame.
|
||||
* Typical reaction is to dispose the dockingWindowManger and/or exit.
|
||||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
* Provides notification when a popup menu is about to be displayed
|
||||
* and permits a list of temporary actions to be returned. Only
|
||||
* those actions which have a suitable popup menu path will be
|
||||
* considered.
|
||||
* @param context the ActionContext
|
||||
* @return list of temporary actions.
|
||||
*/
|
||||
List<DockingActionIf> getPopupActions(ActionContext context);
|
||||
|
||||
}
|
|
@ -22,6 +22,7 @@ import javax.swing.ImageIcon;
|
|||
|
||||
import docking.action.DockingActionIf;
|
||||
import docking.actions.DockingToolActions;
|
||||
import docking.actions.PopupActionProvider;
|
||||
import ghidra.framework.options.ToolOptions;
|
||||
|
||||
/**
|
||||
|
@ -129,6 +130,19 @@ public interface DockingTool {
|
|||
*/
|
||||
public void removeLocalAction(ComponentProvider componentProvider, DockingActionIf action);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Removes the given popup action provider
|
||||
* @param provider the provider
|
||||
*/
|
||||
public void removePopupActionProvider(PopupActionProvider provider);
|
||||
|
||||
/**
|
||||
* Return a set of all actions in the tool.
|
||||
*
|
||||
|
@ -273,4 +287,12 @@ public interface DockingTool {
|
|||
* @return the action manager
|
||||
*/
|
||||
public DockingToolActions getToolActions();
|
||||
|
||||
/**
|
||||
* Suggests the tool to attempt to close(). This will be as though the user
|
||||
* selected the close menu option on the tool or hit the closeWindow x button in
|
||||
* the upper corner (Windows systems).
|
||||
*/
|
||||
public void close();
|
||||
|
||||
}
|
||||
|
|
|
@ -30,8 +30,7 @@ import org.apache.commons.collections4.map.LazyMap;
|
|||
import org.jdom.Element;
|
||||
|
||||
import docking.action.DockingActionIf;
|
||||
import docking.actions.DockingToolActions;
|
||||
import docking.actions.ToolActions;
|
||||
import docking.actions.*;
|
||||
import docking.help.HelpService;
|
||||
import generic.util.WindowUtilities;
|
||||
import ghidra.framework.OperatingSystem;
|
||||
|
@ -87,9 +86,10 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
|
||||
private Map<String, ComponentProvider> providerNameCache = new HashMap<>();
|
||||
private Map<String, PreferenceState> preferenceStateMap = new HashMap<>();
|
||||
private DockWinListener docListener;
|
||||
private ActionToGuiMapper actionToGuiMapper;
|
||||
|
||||
private WeakSet<PopupActionProvider> popupActionProviders =
|
||||
WeakDataStructureFactory.createSingleThreadAccessWeakSet();
|
||||
private WeakSet<DockingContextListener> contextListeners =
|
||||
WeakDataStructureFactory.createSingleThreadAccessWeakSet();
|
||||
|
||||
|
@ -108,10 +108,9 @@ 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
|
||||
* @param docListener the listener to be notified when the user closes the manager
|
||||
*/
|
||||
public DockingWindowManager(DockingTool tool, List<Image> images, DockWinListener docListener) {
|
||||
this(tool, images, docListener, false, true, true, null);
|
||||
public DockingWindowManager(DockingTool tool, List<Image> images) {
|
||||
this(tool, images, false, true, true, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -119,20 +118,18 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
*
|
||||
* @param tool the tool
|
||||
* @param images the list of icons to set on the window
|
||||
* @param docListener the listener to be notified when the user closes the manager
|
||||
* @param modal if true then the root window will be a modal dialog instead of a frame
|
||||
* @param isDocking true for normal operation, false to suppress docking support(removes
|
||||
* component headers and window menu)
|
||||
* @param hasStatusBar if true a status bar will be created for the main window
|
||||
* @param factory the drop target factory
|
||||
*/
|
||||
public DockingWindowManager(DockingTool tool, List<Image> images, DockWinListener docListener,
|
||||
boolean modal, boolean isDocking, boolean hasStatusBar, DropTargetFactory factory) {
|
||||
public DockingWindowManager(DockingTool tool, List<Image> images, boolean modal,
|
||||
boolean isDocking, boolean hasStatusBar, DropTargetFactory factory) {
|
||||
|
||||
KeyBindingOverrideKeyEventDispatcher.install();
|
||||
|
||||
this.tool = tool;
|
||||
this.docListener = docListener;
|
||||
this.isDocking = isDocking;
|
||||
this.hasStatusBar = hasStatusBar;
|
||||
if (images == null) {
|
||||
|
@ -174,10 +171,6 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
return helpService;
|
||||
}
|
||||
|
||||
List<DockingActionIf> getTemporaryPopupActions(ActionContext context) {
|
||||
return docListener.getPopupActions(context);
|
||||
}
|
||||
|
||||
private static synchronized void addInstance(DockingWindowManager winMgr) {
|
||||
instanceList.add(winMgr);
|
||||
}
|
||||
|
@ -1084,7 +1077,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
* the main window frame.
|
||||
*/
|
||||
void close() {
|
||||
docListener.close();
|
||||
tool.close();
|
||||
}
|
||||
|
||||
boolean isDocking() {
|
||||
|
@ -2099,6 +2092,44 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
actionToGuiMapper.contextChanged(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) {
|
||||
popupActionProviders.add(provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the given popup action provider
|
||||
* @param provider the provider
|
||||
*/
|
||||
public void removePopupActionProvider(PopupActionProvider provider) {
|
||||
popupActionProviders.remove(provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of temporary popup actions to be returned. Only those actions which have
|
||||
* a suitable popup menu path will be considered. This mechanism allows clients to
|
||||
* add transient actions to be added to the tool without the accompanying management overhead.
|
||||
*
|
||||
* @param context the ActionContext
|
||||
* @return list of temporary actions
|
||||
* @see #addPopupActionProvider(PopupActionProvider)
|
||||
*/
|
||||
List<DockingActionIf> getTemporaryPopupActions(ActionContext context) {
|
||||
|
||||
List<DockingActionIf> actionList = new ArrayList<>();
|
||||
for (PopupActionProvider pl : popupActionProviders) {
|
||||
List<DockingActionIf> actions = pl.getPopupActions(context);
|
||||
if (actions != null) {
|
||||
actionList.addAll(actions);
|
||||
}
|
||||
}
|
||||
return actionList;
|
||||
}
|
||||
|
||||
public void addContextListener(DockingContextListener listener) {
|
||||
contextListeners.add(listener);
|
||||
}
|
||||
|
@ -2122,12 +2153,9 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
* @param component the component that will be parented in a docking window system.
|
||||
* @param listener the listener to be notified the component was parented.
|
||||
*/
|
||||
public static void registerComponentLoadedListener(final Component component,
|
||||
final ComponentLoadedListener listener) {
|
||||
public static void registerComponentLoadedListener(Component component,
|
||||
ComponentLoadedListener listener) {
|
||||
|
||||
// We want to load our state after the column model is loaded. We are using this
|
||||
// listener to know when the table has been added to the component hierarchy, as its
|
||||
// model has been loaded by then.
|
||||
component.addHierarchyListener(new HierarchyListener() {
|
||||
@Override
|
||||
public void hierarchyChanged(HierarchyEvent e) {
|
||||
|
|
|
@ -17,6 +17,8 @@ package docking.action;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import docking.DockingTool;
|
||||
|
||||
/**
|
||||
* An interface for objects (really Components) to implement that signals they provide actions
|
||||
* for the Docking environment. This interface will be called when the implementor is the source
|
||||
|
@ -25,8 +27,12 @@ import java.util.List;
|
|||
* As an example, a JTable that wishes to provide popup menu actions can implement this interface.
|
||||
* When the user right-clicks on said table, then Docking system will ask this object for its
|
||||
* actions. Further, in this example, the actions given will be inserted into the popup menu
|
||||
* that is shown.
|
||||
* that is shown.
|
||||
*
|
||||
* @deprecated use {@link DockingTool}
|
||||
*/
|
||||
// Note: this API is not likely used by forward-facing clients and can be removed in the next release
|
||||
@Deprecated(since = "9.1", forRemoval = true)
|
||||
public interface DockingActionProviderIf {
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package docking.actions;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import docking.ActionContext;
|
||||
import docking.DockingTool;
|
||||
import docking.action.DockingActionIf;
|
||||
|
||||
/**
|
||||
* Provides notification when the popup action menu is displayed. This interface allows
|
||||
* temporary/transient actions (those not registered with the tool via
|
||||
* {@link DockingTool#addAction(DockingActionIf)}) to be used in the popup context menu.
|
||||
*
|
||||
* <p>
|
||||
* Most clients will register actions directly with the tool. However, clients that have numerous
|
||||
* actions that vary greatly with the context can use this method to only create those actions
|
||||
* on demand as the popup is about to be shown, and only if their context is active. This
|
||||
* mechanism can reduce the tool's action management overhead.
|
||||
*/
|
||||
public interface PopupActionProvider {
|
||||
|
||||
/**
|
||||
* Provides notification that the popup menu is about to be displayed and allows a set of
|
||||
* temporary actions to be included in the popup menu. Actions returned will be
|
||||
* included in the menu if they have a valid popup menu path and respond true to the
|
||||
* {@link DockingActionIf#isValidContext(ActionContext)} call.
|
||||
*
|
||||
* @param context the ActionContext
|
||||
* @return list of temporary popup actions; return null if there are no popup actions
|
||||
*/
|
||||
public List<DockingActionIf> getPopupActions(ActionContext context);
|
||||
}
|
|
@ -32,6 +32,7 @@ import javax.swing.table.*;
|
|||
import docking.*;
|
||||
import docking.action.*;
|
||||
import docking.actions.KeyBindingUtils;
|
||||
import docking.actions.PopupActionProvider;
|
||||
import docking.widgets.OptionDialog;
|
||||
import docking.widgets.dialogs.SettingsDialog;
|
||||
import docking.widgets.filechooser.GhidraFileChooser;
|
||||
|
@ -69,7 +70,7 @@ import resources.ResourceManager;
|
|||
*
|
||||
* @see GTableFilterPanel
|
||||
*/
|
||||
public class GTable extends JTable implements KeyStrokeConsumer, DockingActionProviderIf {
|
||||
public class GTable extends JTable implements KeyStrokeConsumer, PopupActionProvider {
|
||||
|
||||
private static final String LAST_EXPORT_FILE = "LAST_EXPORT_DIR";
|
||||
|
||||
|
@ -510,20 +511,8 @@ public class GTable extends JTable implements KeyStrokeConsumer, DockingActionPr
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<DockingActionIf> getDockingActions() {
|
||||
return getDefaultDockingActions();
|
||||
}
|
||||
public List<DockingActionIf> getPopupActions(ActionContext context) {
|
||||
|
||||
/**
|
||||
* Returns the default actions of this table. Normally, the Docking Windows systems uses
|
||||
* {@link #getDockingActions()} to get the correct actions to show. However,
|
||||
* there are some cases where clients override what appears when you click on a table (such
|
||||
* as in {@link DialogComponentProvider}s. For those clients that are creating their own
|
||||
* action building, they need a way to get the default actions, hence this method.
|
||||
*
|
||||
* @return the default actions
|
||||
*/
|
||||
public List<DockingActionIf> getDefaultDockingActions() {
|
||||
// we want these top-level groups to all appear together, with no separator
|
||||
DockingWindowManager dwm = DockingWindowManager.getInstance(this);
|
||||
dwm.setMenuGroup(new String[] { "Copy" }, actionMenuGroup, "1");
|
||||
|
@ -590,6 +579,10 @@ public class GTable extends JTable implements KeyStrokeConsumer, DockingActionPr
|
|||
|
||||
createPopupActions();
|
||||
initializeRowHeight();
|
||||
|
||||
DockingWindowManager.registerComponentLoadedListener(this, dwm -> {
|
||||
dwm.getTool().addPopupActionProvider(this);
|
||||
});
|
||||
}
|
||||
|
||||
private void initializeHeader(JTableHeader header) {
|
||||
|
@ -1490,5 +1483,4 @@ public class GTable extends JTable implements KeyStrokeConsumer, DockingActionPr
|
|||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue