mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GT-3044 - Table Actions - updated table actions to use the modern action
system
This commit is contained in:
parent
392c0846d1
commit
28f6500039
70 changed files with 642 additions and 493 deletions
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,26 +15,37 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.context;
|
package ghidra.app.context;
|
||||||
|
|
||||||
import ghidra.program.model.listing.Program;
|
import java.awt.Component;
|
||||||
|
import java.awt.KeyboardFocusManager;
|
||||||
|
|
||||||
import docking.ActionContext;
|
import docking.ActionContext;
|
||||||
import docking.ComponentProvider;
|
import docking.ComponentProvider;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
|
|
||||||
public class ProgramActionContext extends ActionContext {
|
public class ProgramActionContext extends ActionContext {
|
||||||
protected final Program program;
|
protected final Program program;
|
||||||
|
|
||||||
|
|
||||||
public ProgramActionContext(ComponentProvider provider, Program program) {
|
public ProgramActionContext(ComponentProvider provider, Program program) {
|
||||||
this(provider, program, null);
|
this(provider, program, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProgramActionContext(ComponentProvider provider, Program program, Object contextObject) {
|
public ProgramActionContext(ComponentProvider provider, Program program,
|
||||||
super(provider, contextObject);
|
Component sourceComponent) {
|
||||||
this.program = program;
|
this(provider, program, sourceComponent, sourceComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProgramActionContext(ComponentProvider provider, Program program,
|
||||||
|
Component sourceComponent, Object contextObject) {
|
||||||
|
super(provider, contextObject, sourceComponent);
|
||||||
|
this.program = program;
|
||||||
|
|
||||||
|
// the case where the first constructor is called, which does not specify the component
|
||||||
|
if (sourceComponent == null) {
|
||||||
|
KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
|
||||||
|
setSourceObject(kfm.getFocusOwner());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Returns the program.
|
|
||||||
*/
|
|
||||||
public Program getProgram() {
|
public Program getProgram() {
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.context;
|
package ghidra.app.context;
|
||||||
|
|
||||||
|
import java.awt.Component;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
@ -27,14 +28,9 @@ public class ProgramSymbolActionContext extends ProgramActionContext {
|
||||||
|
|
||||||
private final long[] symbolIDs;
|
private final long[] symbolIDs;
|
||||||
|
|
||||||
public ProgramSymbolActionContext(ComponentProvider provider, Program program,
|
|
||||||
long[] symbolIDs) {
|
|
||||||
this(provider, program, symbolIDs, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProgramSymbolActionContext(ComponentProvider provider, Program program, long[] symbolIDs,
|
public ProgramSymbolActionContext(ComponentProvider provider, Program program, long[] symbolIDs,
|
||||||
Object contextObj) {
|
Component sourceComponent) {
|
||||||
super(provider, program, contextObj);
|
super(provider, program, sourceComponent);
|
||||||
this.symbolIDs = symbolIDs;
|
this.symbolIDs = symbolIDs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ class MergeManagerProvider extends ComponentProviderAdapter {
|
||||||
if (event != null && event.getSource() instanceof FieldHeaderComp) {
|
if (event != null && event.getSource() instanceof FieldHeaderComp) {
|
||||||
FieldHeaderComp comp = (FieldHeaderComp) event.getSource();
|
FieldHeaderComp comp = (FieldHeaderComp) event.getSource();
|
||||||
FieldHeaderLocation fieldHeaderLocation = comp.getFieldHeaderLocation(event.getPoint());
|
FieldHeaderLocation fieldHeaderLocation = comp.getFieldHeaderLocation(event.getPoint());
|
||||||
return new ActionContext(this, fieldHeaderLocation);
|
return createContext(fieldHeaderLocation);
|
||||||
|
|
||||||
}
|
}
|
||||||
if (mergeManager instanceof ProgramMultiUserMergeManager) {
|
if (mergeManager instanceof ProgramMultiUserMergeManager) {
|
||||||
|
|
|
@ -47,7 +47,7 @@ public class ListingMergePanelProvider extends ComponentProviderAdapter
|
||||||
@Override
|
@Override
|
||||||
public ActionContext getActionContext(MouseEvent event) {
|
public ActionContext getActionContext(MouseEvent event) {
|
||||||
Object obj = mergePanel.getActionContext(event);
|
Object obj = mergePanel.getActionContext(event);
|
||||||
return new ActionContext(this, obj);
|
return createContext(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
@ -55,7 +55,7 @@ public class ListingMergePanelProvider extends ComponentProviderAdapter
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<DockingActionIf> getPopupActions(DockingTool tool, ActionContext context) {
|
public List<DockingActionIf> getPopupActions(DockingTool dt, ActionContext context) {
|
||||||
ListingPanel resultPanel = mergePanel.getResultPanel();
|
ListingPanel resultPanel = mergePanel.getResultPanel();
|
||||||
if (resultPanel != null) {
|
if (resultPanel != null) {
|
||||||
return resultPanel.getHeaderActions(getName());
|
return resultPanel.getHeaderActions(getName());
|
||||||
|
|
|
@ -105,7 +105,7 @@ public class BookmarkProvider extends ComponentProviderAdapter {
|
||||||
if (program == null) {
|
if (program == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new ProgramActionContext(this, program);
|
return new ProgramActionContext(this, program, bookmarkTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setGoToService(GoToService goToService) {
|
void setGoToService(GoToService goToService) {
|
||||||
|
|
|
@ -269,17 +269,17 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
|
||||||
FieldHeader headerPanel = listingPanel.getFieldHeader();
|
FieldHeader headerPanel = listingPanel.getFieldHeader();
|
||||||
if (headerPanel != null && source instanceof FieldHeaderComp) {
|
if (headerPanel != null && source instanceof FieldHeaderComp) {
|
||||||
FieldHeaderLocation fhLoc = headerPanel.getFieldHeaderLocation(event.getPoint());
|
FieldHeaderLocation fhLoc = headerPanel.getFieldHeaderLocation(event.getPoint());
|
||||||
return new ActionContext(this, fhLoc);
|
return createContext(fhLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (otherPanel != null && otherPanel.isAncestorOf((Component) source)) {
|
if (otherPanel != null && otherPanel.isAncestorOf((Component) source)) {
|
||||||
Object obj = getContextForMarginPanels(otherPanel, event);
|
Object obj = getContextForMarginPanels(otherPanel, event);
|
||||||
if (obj != null) {
|
if (obj != null) {
|
||||||
return new ActionContext(this, obj);
|
return createContext(obj);
|
||||||
}
|
}
|
||||||
return new OtherPanelContext(this, program);
|
return new OtherPanelContext(this, program);
|
||||||
}
|
}
|
||||||
return new ActionContext(this, getContextForMarginPanels(listingPanel, event));
|
return createContext(getContextForMarginPanels(listingPanel, event));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object getContextForMarginPanels(ListingPanel lp, MouseEvent event) {
|
private Object getContextForMarginPanels(ListingPanel lp, MouseEvent event) {
|
||||||
|
@ -955,11 +955,11 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<DockingActionIf> getPopupActions(DockingTool tool, ActionContext context) {
|
public List<DockingActionIf> getPopupActions(DockingTool dt, ActionContext context) {
|
||||||
if (context.getComponentProvider() == this) {
|
if (context.getComponentProvider() == this) {
|
||||||
return listingPanel.getHeaderActions(getName());
|
return listingPanel.getHeaderActions(getName());
|
||||||
}
|
}
|
||||||
return new ArrayList<>();
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.datamgr;
|
package ghidra.app.plugin.core.datamgr;
|
||||||
|
|
||||||
|
import java.awt.Component;
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
import java.awt.event.MouseAdapter;
|
import java.awt.event.MouseAdapter;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
|
@ -333,7 +334,8 @@ public class DataTypesProvider extends ComponentProviderAdapter {
|
||||||
|
|
||||||
Object source = event.getSource();
|
Object source = event.getSource();
|
||||||
if (source instanceof JTextField || source instanceof JTextPane) {
|
if (source instanceof JTextField || source instanceof JTextPane) {
|
||||||
return new ActionContext(this, source, source);
|
Component component = (Component) source;
|
||||||
|
return new ActionContext(this, source, component);
|
||||||
}
|
}
|
||||||
|
|
||||||
Point point = event.getPoint();
|
Point point = event.getPoint();
|
||||||
|
|
|
@ -18,7 +18,6 @@ package ghidra.app.plugin.core.editor;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
import java.awt.event.MouseEvent;
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -91,10 +90,10 @@ public class TextEditorComponentProvider extends ComponentProviderAdapter {
|
||||||
return textarea.getText();
|
return textarea.getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initialize(TextEditorManagerPlugin plugin, String textContents) {
|
private void initialize(TextEditorManagerPlugin p, String textContents) {
|
||||||
this.plugin = plugin;
|
this.plugin = p;
|
||||||
|
|
||||||
setHelpLocation(new HelpLocation(plugin.getName(), plugin.getName()));
|
setHelpLocation(new HelpLocation(p.getName(), p.getName()));
|
||||||
|
|
||||||
title = textFileName + (isReadOnly() ? " (Read-Only) " : "");
|
title = textFileName + (isReadOnly() ? " (Read-Only) " : "");
|
||||||
setTitle(title);
|
setTitle(title);
|
||||||
|
@ -106,7 +105,7 @@ public class TextEditorComponentProvider extends ComponentProviderAdapter {
|
||||||
|
|
||||||
addToTool();
|
addToTool();
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
plugin.getTool().setStatusInfo("Press F1 for help.");
|
p.getTool().setStatusInfo("Press F1 for help.");
|
||||||
|
|
||||||
createActions();
|
createActions();
|
||||||
}
|
}
|
||||||
|
@ -278,8 +277,7 @@ public class TextEditorComponentProvider extends ComponentProviderAdapter {
|
||||||
|
|
||||||
ActionContextProvider acp = e -> {
|
ActionContextProvider acp = e -> {
|
||||||
ComponentProvider p = TextEditorComponentProvider.this;
|
ComponentProvider p = TextEditorComponentProvider.this;
|
||||||
Object context = TextEditorComponentProvider.this;
|
return new ActionContext(p);
|
||||||
return new ActionContext(p, context);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
KeyBindingUtils.registerAction(textarea, saveAction, acp);
|
KeyBindingUtils.registerAction(textarea, saveAction, acp);
|
||||||
|
@ -374,11 +372,6 @@ public class TextEditorComponentProvider extends ComponentProviderAdapter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ActionContext getActionContext(MouseEvent event) {
|
|
||||||
return new ActionContext(this, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JComponent getComponent() {
|
public JComponent getComponent() {
|
||||||
return scrollpane;
|
return scrollpane;
|
||||||
|
@ -387,9 +380,10 @@ public class TextEditorComponentProvider extends ComponentProviderAdapter {
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
// Inner Classes
|
// Inner Classes
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special JTextArea that knows how to properly handle it's key events.
|
* Special JTextArea that knows how to properly handle it's key events.
|
||||||
* @see {@link #processKeyBinding(KeyStroke, KeyEvent, int, boolean)}
|
* @see #processKeyBinding(KeyStroke, KeyEvent, int, boolean)
|
||||||
*/
|
*/
|
||||||
private class KeyMasterTextArea extends JTextArea {
|
private class KeyMasterTextArea extends JTextArea {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
@ -455,7 +449,7 @@ public class TextEditorComponentProvider extends ComponentProviderAdapter {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SwingUtilities.notifyAction(action, ks, e, this, e.getModifiers());
|
return SwingUtilities.notifyAction(action, ks, e, this, e.getModifiersEx());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -71,11 +71,7 @@ public class FunctionWindowProvider extends ComponentProviderAdapter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActionContext getActionContext(MouseEvent event) {
|
public ActionContext getActionContext(MouseEvent event) {
|
||||||
if (event != null && event.getSource() == functionTable) {
|
return new ActionContext(this, functionTable);
|
||||||
return new ActionContext(this, functionTable);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -21,8 +21,7 @@ import java.util.List;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
import docking.*;
|
import docking.DockingWindowManager;
|
||||||
import docking.action.DockingActionIf;
|
|
||||||
import docking.widgets.EmptyBorderButton;
|
import docking.widgets.EmptyBorderButton;
|
||||||
import ghidra.app.plugin.core.instructionsearch.InstructionSearchPlugin;
|
import ghidra.app.plugin.core.instructionsearch.InstructionSearchPlugin;
|
||||||
import ghidra.app.plugin.core.instructionsearch.model.*;
|
import ghidra.app.plugin.core.instructionsearch.model.*;
|
||||||
|
@ -95,13 +94,9 @@ public class InstructionTable extends AbstractInstructionTable {
|
||||||
dialog.getSearchData().registerForGuiUpdates(this);
|
dialog.getSearchData().registerForGuiUpdates(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Override from abstract class so we can remove the select and copy options
|
|
||||||
* (which is all of them).
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public List<DockingActionIf> getPopupActions(DockingTool tool, ActionContext context) {
|
protected boolean supportsPopupActions() {
|
||||||
return null;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InsertBytesWidget getInsertBytesWidget() {
|
public InsertBytesWidget getInsertBytesWidget() {
|
||||||
|
|
|
@ -135,17 +135,25 @@ public class PreviewTable extends AbstractInstructionTable {
|
||||||
* Adds custom context-sensitive menus to the table. This does NOT modify
|
* Adds custom context-sensitive menus to the table. This does NOT modify
|
||||||
* any existing menus; it simply adds to them.
|
* any existing menus; it simply adds to them.
|
||||||
*/
|
*/
|
||||||
@Override
|
|
||||||
public List<DockingActionIf> getPopupActions(DockingTool tool, ActionContext context) {
|
|
||||||
|
|
||||||
// Invoke the base class method to add default menu options.
|
// TODO
|
||||||
List<DockingActionIf> list = super.getPopupActions(tool, context);
|
// TODO
|
||||||
|
// TODO
|
||||||
|
// TODO Change the custom menu items to be real Docking Actions
|
||||||
|
// TODO
|
||||||
|
// TODO
|
||||||
|
|
||||||
// And now add our own.
|
// @Override
|
||||||
addCustomMenuItems(list);
|
// public List<DockingActionIf> getPopupActions(DockingTool tool, ActionContext context) {
|
||||||
|
//
|
||||||
return list;
|
// // Invoke the base class method to add default menu options.
|
||||||
}
|
// List<DockingActionIf> list = super.getPopupActions(tool, context);
|
||||||
|
//
|
||||||
|
// // And now add our own.
|
||||||
|
// addCustomMenuItems(list);
|
||||||
|
//
|
||||||
|
// return list;
|
||||||
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces the contents of the preview table at the given row with the
|
* Replaces the contents of the preview table at the given row with the
|
||||||
|
|
|
@ -15,6 +15,15 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.programtree;
|
package ghidra.app.plugin.core.programtree;
|
||||||
|
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
|
||||||
|
import docking.ActionContext;
|
||||||
|
import docking.action.DockingAction;
|
||||||
import ghidra.app.events.ViewChangedPluginEvent;
|
import ghidra.app.events.ViewChangedPluginEvent;
|
||||||
import ghidra.app.services.GoToService;
|
import ghidra.app.services.GoToService;
|
||||||
import ghidra.app.services.ViewManagerService;
|
import ghidra.app.services.ViewManagerService;
|
||||||
|
@ -25,15 +34,6 @@ import ghidra.program.util.*;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.task.*;
|
import ghidra.util.task.*;
|
||||||
|
|
||||||
import java.awt.event.MouseEvent;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
|
|
||||||
import javax.swing.JComponent;
|
|
||||||
import javax.swing.event.ChangeEvent;
|
|
||||||
|
|
||||||
import docking.action.DockingAction;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a view of the program tree.
|
* Provides a view of the program tree.
|
||||||
*/
|
*/
|
||||||
|
@ -51,9 +51,6 @@ class TreeViewProvider implements ViewProviderService {
|
||||||
|
|
||||||
private final static int DELAY = 500;
|
private final static int DELAY = 500;
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for TreeViewProvider.
|
|
||||||
*/
|
|
||||||
public TreeViewProvider(String treeName, final ProgramTreePlugin plugin) {
|
public TreeViewProvider(String treeName, final ProgramTreePlugin plugin) {
|
||||||
|
|
||||||
treePanel = new ProgramTreePanel(treeName, plugin);
|
treePanel = new ProgramTreePanel(treeName, plugin);
|
||||||
|
@ -72,25 +69,16 @@ class TreeViewProvider implements ViewProviderService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.app.plugin.core.programtree.ViewProviderService#getViewComponent()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public JComponent getViewComponent() {
|
public JComponent getViewComponent() {
|
||||||
return treePanel;
|
return treePanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.app.plugin.core.programtree.ViewProviderService#getViewName()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getViewName() {
|
public String getViewName() {
|
||||||
return treePanel.getTreeName();
|
return treePanel.getTreeName();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.app.plugin.core.programtree.ViewProviderService#setHasFocus(JComponent, boolean)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void setHasFocus(boolean hasFocus) {
|
public void setHasFocus(boolean hasFocus) {
|
||||||
treePanel.setHasFocus(hasFocus);
|
treePanel.setHasFocus(hasFocus);
|
||||||
|
@ -107,33 +95,26 @@ class TreeViewProvider implements ViewProviderService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.app.plugin.core.programtree.ViewProviderService#getActivePopupObject(MouseEvent)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Object getActivePopupObject(MouseEvent event) {
|
public Object getActivePopupObject(MouseEvent event) {
|
||||||
return treePanel.prepareSelectionForPopup(event);
|
return treePanel.prepareSelectionForPopup(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see ghidra.app.plugin.core.programtree.ViewProviderService#getActiveObject()
|
public ActionContext getActionContext(MouseEvent event) {
|
||||||
*/
|
return new ActionContext().setContextObject(getActivePopupObject(event));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getActiveObject() {
|
public Object getActiveObject() {
|
||||||
return treePanel.getSelectedNode();
|
return treePanel.getSelectedNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.app.plugin.core.programtree.ViewProviderService#getToolBarActions()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public DockingAction[] getToolBarActions() {
|
public DockingAction[] getToolBarActions() {
|
||||||
return plugin.getToolBarActions();
|
return plugin.getToolBarActions();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.app.plugin.core.programtree.ViewProviderService#viewClosed()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean viewClosed() {
|
public boolean viewClosed() {
|
||||||
if (program == null) {
|
if (program == null) {
|
||||||
|
@ -146,9 +127,6 @@ class TreeViewProvider implements ViewProviderService {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.app.plugin.core.programtree.ViewProviderService#viewDeleted()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean viewDeleted() {
|
public boolean viewDeleted() {
|
||||||
if (program == null) {
|
if (program == null) {
|
||||||
|
@ -161,9 +139,6 @@ class TreeViewProvider implements ViewProviderService {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.app.plugin.core.programtree.ViewProviderService#viewRenamed(String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean viewRenamed(String newName) {
|
public boolean viewRenamed(String newName) {
|
||||||
if (program == null) {
|
if (program == null) {
|
||||||
|
@ -177,9 +152,6 @@ class TreeViewProvider implements ViewProviderService {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.app.plugin.core.programtree.ViewProviderService#addToView(ProgramLocation)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public AddressSetView addToView(ProgramLocation loc) {
|
public AddressSetView addToView(ProgramLocation loc) {
|
||||||
if (program != null && loc != null && loc.getAddress() != null) {
|
if (program != null && loc != null && loc.getAddress() != null) {
|
||||||
|
@ -192,9 +164,6 @@ class TreeViewProvider implements ViewProviderService {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.app.plugin.core.programtree.ViewProviderService#getCurrentView()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public AddressSetView getCurrentView() {
|
public AddressSetView getCurrentView() {
|
||||||
return view;
|
return view;
|
||||||
|
@ -212,14 +181,14 @@ class TreeViewProvider implements ViewProviderService {
|
||||||
ProgramModule root = program.getListing().getRootModule(group.getTreeName());
|
ProgramModule root = program.getListing().getRootModule(group.getTreeName());
|
||||||
ProgramModule[] parents = group.getParents();
|
ProgramModule[] parents = group.getParents();
|
||||||
if (parents != null && parents.length > 0) {
|
if (parents != null && parents.length > 0) {
|
||||||
for (int i = 0; i < parents.length; i++) {
|
for (ProgramModule parent : parents) {
|
||||||
LinkedList<String> myList = new LinkedList<String>(list);
|
LinkedList<String> myList = new LinkedList<>(list);
|
||||||
myList.addFirst(parents[i].getName());
|
myList.addFirst(parent.getName());
|
||||||
if (parents[i] == root) {
|
if (parent == root) {
|
||||||
pathNameList.add(myList);
|
pathNameList.add(myList);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
setAncestorList(parents[i], myList, pathNameList);
|
setAncestorList(parent, myList, pathNameList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -278,15 +247,12 @@ class TreeViewProvider implements ViewProviderService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the tree selection.
|
* Set the tree selection.
|
||||||
* @param groupPaths
|
* @param paths the paths to select
|
||||||
*/
|
*/
|
||||||
void setGroupSelection(GroupPath[] paths) {
|
void setGroupSelection(GroupPath[] paths) {
|
||||||
treePanel.setGroupSelection(paths);
|
treePanel.setGroupSelection(paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Write group paths in the view.
|
|
||||||
*/
|
|
||||||
void writeDataState(SaveState saveState) {
|
void writeDataState(SaveState saveState) {
|
||||||
GroupView currentView = treePanel.getGroupView();
|
GroupView currentView = treePanel.getGroupView();
|
||||||
String treeName = treePanel.getTreeName();
|
String treeName = treePanel.getTreeName();
|
||||||
|
@ -299,9 +265,6 @@ class TreeViewProvider implements ViewProviderService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the state from save state object.
|
|
||||||
*/
|
|
||||||
void readDataState(SaveState saveState) {
|
void readDataState(SaveState saveState) {
|
||||||
String treeName = treePanel.getTreeName();
|
String treeName = treePanel.getTreeName();
|
||||||
int numGroups = saveState.getInt(NUMBER_OF_GROUPS + treeName, 0);
|
int numGroups = saveState.getInt(NUMBER_OF_GROUPS + treeName, 0);
|
||||||
|
@ -329,9 +292,6 @@ class TreeViewProvider implements ViewProviderService {
|
||||||
return treePanel.getDnDTree();
|
return treePanel.getDnDTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the address set currently being viewed.
|
|
||||||
*/
|
|
||||||
AddressSet getView() {
|
AddressSet getView() {
|
||||||
if (program == null) {
|
if (program == null) {
|
||||||
return new AddressSet();
|
return new AddressSet();
|
||||||
|
@ -342,8 +302,8 @@ class TreeViewProvider implements ViewProviderService {
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
String treeName = treePanel.getTreeName();
|
String treeName = treePanel.getTreeName();
|
||||||
for (int i = 0; i < gp.length; i++) {
|
for (GroupPath element : gp) {
|
||||||
Group group = gp[i].getGroup(program, treeName);
|
Group group = element.getGroup(program, treeName);
|
||||||
if (group == null) {
|
if (group == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -365,8 +325,8 @@ class TreeViewProvider implements ViewProviderService {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
view = getView();
|
view = getView();
|
||||||
plugin.firePluginEvent(new ViewChangedPluginEvent(plugin.getName(),
|
plugin.firePluginEvent(
|
||||||
treePanel.getTreeName(), view));
|
new ViewChangedPluginEvent(plugin.getName(), treePanel.getTreeName(), view));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -379,7 +339,7 @@ class TreeViewProvider implements ViewProviderService {
|
||||||
if (fragment == null) {
|
if (fragment == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LinkedList<String> list = new LinkedList<String>();
|
LinkedList<String> list = new LinkedList<>();
|
||||||
list.add(fragment.getName());
|
list.add(fragment.getName());
|
||||||
Group group = fragment;
|
Group group = fragment;
|
||||||
while (group != null) {
|
while (group != null) {
|
||||||
|
@ -408,8 +368,8 @@ class TreeViewProvider implements ViewProviderService {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Group[] groups = ((ProgramModule) group).getChildren();
|
Group[] groups = ((ProgramModule) group).getChildren();
|
||||||
for (int i = 0; i < groups.length; i++) {
|
for (Group group2 : groups) {
|
||||||
getAddressSet(groups[i], set);
|
getAddressSet(group2, set);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -439,11 +399,11 @@ class TreeViewProvider implements ViewProviderService {
|
||||||
if (fragment == null) {
|
if (fragment == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LinkedList<String> list = new LinkedList<String>();
|
LinkedList<String> list = new LinkedList<>();
|
||||||
list.add(fragment.getName());
|
list.add(fragment.getName());
|
||||||
Group group = fragment;
|
Group group = fragment;
|
||||||
|
|
||||||
ArrayList<LinkedList<String>> pathNameList = new ArrayList<LinkedList<String>>();
|
ArrayList<LinkedList<String>> pathNameList = new ArrayList<>();
|
||||||
// need GroupPath for all occurrences of fragment
|
// need GroupPath for all occurrences of fragment
|
||||||
setAncestorList(group, list, pathNameList);
|
setAncestorList(group, list, pathNameList);
|
||||||
|
|
||||||
|
|
|
@ -196,11 +196,13 @@ public class ViewManagerComponentProvider extends ComponentProviderAdapter
|
||||||
if (currentProgram == null) {
|
if (currentProgram == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event != null) {
|
if (event != null) {
|
||||||
return new ProgramActionContext(this, currentProgram, getActivePopupObject(event));
|
return new ProgramActionContext(this, currentProgram, viewPanel,
|
||||||
|
getActivePopupObject(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ProgramActionContext(this, currentProgram, getFocusedContext());
|
return new ProgramActionContext(this, currentProgram, viewPanel, getFocusedContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object getFocusedContext() {
|
private Object getFocusedContext() {
|
||||||
|
|
|
@ -15,14 +15,14 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.programtree;
|
package ghidra.app.plugin.core.programtree;
|
||||||
|
|
||||||
import ghidra.app.services.ViewService;
|
|
||||||
import ghidra.framework.plugintool.ServiceInfo;
|
|
||||||
|
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
|
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
|
||||||
|
import docking.ActionContext;
|
||||||
import docking.action.DockingAction;
|
import docking.action.DockingAction;
|
||||||
|
import ghidra.app.services.ViewService;
|
||||||
|
import ghidra.framework.plugintool.ServiceInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define methods for notification of which service becomes active;
|
* Define methods for notification of which service becomes active;
|
||||||
|
@ -30,55 +30,62 @@ import docking.action.DockingAction;
|
||||||
*/
|
*/
|
||||||
@ServiceInfo(description = "Provide a view that is managed by the ViewManagerService")
|
@ServiceInfo(description = "Provide a view that is managed by the ViewManagerService")
|
||||||
public interface ViewProviderService extends ViewService {
|
public interface ViewProviderService extends ViewService {
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the viewer component.
|
|
||||||
*/
|
|
||||||
public JComponent getViewComponent();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the name of this view.
|
* Get the viewer component.
|
||||||
*/
|
*/
|
||||||
public String getViewName();
|
public JComponent getViewComponent();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set whether or not the component that is showing has focus.
|
* Get the name of this view.
|
||||||
|
*/
|
||||||
|
public String getViewName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether or not the component that is showing has focus.
|
||||||
* @param hasFocus true if the component has focus
|
* @param hasFocus true if the component has focus
|
||||||
*/
|
*/
|
||||||
public void setHasFocus(boolean hasFocus);
|
public void setHasFocus(boolean hasFocus);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the object under the mouse location for the popup
|
* Return the object under the mouse location for the popup
|
||||||
* @param event mouse event generated when the right mouse button is pressed
|
* @param event mouse event generated when the right mouse button is pressed
|
||||||
*/
|
*/
|
||||||
public Object getActivePopupObject(MouseEvent event);
|
public Object getActivePopupObject(MouseEvent event);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the actions that would go on a tool bar.
|
* Returns the current action context for this view service
|
||||||
*/
|
* @param event the mouse event
|
||||||
public DockingAction[] getToolBarActions();
|
* @return the context
|
||||||
|
*/
|
||||||
/**
|
public ActionContext getActionContext(MouseEvent event);
|
||||||
* Notification that this view is closed.
|
|
||||||
* @return true if the view can be closed
|
/**
|
||||||
*/
|
* Get the actions that would go on a tool bar.
|
||||||
public boolean viewClosed();
|
*/
|
||||||
|
public DockingAction[] getToolBarActions();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notification that this view is closed.
|
||||||
|
* @return true if the view can be closed
|
||||||
|
*/
|
||||||
|
public boolean viewClosed();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notification that this view should be deleted
|
* Notification that this view should be deleted
|
||||||
* @return true if the view can be deleted
|
* @return true if the view can be deleted
|
||||||
*/
|
*/
|
||||||
public boolean viewDeleted();
|
public boolean viewDeleted();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notification that this view should be renamed to newName.
|
* Notification that this view should be renamed to newName.
|
||||||
* @return true if the rename is allowed
|
* @return true if the rename is allowed
|
||||||
*/
|
*/
|
||||||
public boolean viewRenamed(String newName);
|
public boolean viewRenamed(String newName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the context for the current selection.
|
* Returns the context for the current selection.
|
||||||
*/
|
*/
|
||||||
public Object getActiveObject();
|
public Object getActiveObject();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -651,7 +651,7 @@ public class GhidraScriptEditorComponentProvider extends ComponentProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActionContext getActionContext(MouseEvent event) {
|
public ActionContext getActionContext(MouseEvent event) {
|
||||||
return new ActionContext(this, this);
|
return createContext(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -15,12 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.debug;
|
package ghidra.app.plugin.debug;
|
||||||
|
|
||||||
import java.awt.event.MouseEvent;
|
|
||||||
|
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
|
||||||
import db.DBHandle;
|
import db.DBHandle;
|
||||||
import docking.ActionContext;
|
|
||||||
import docking.WindowPosition;
|
import docking.WindowPosition;
|
||||||
import ghidra.framework.plugintool.ComponentProviderAdapter;
|
import ghidra.framework.plugintool.ComponentProviderAdapter;
|
||||||
import ghidra.framework.plugintool.Plugin;
|
import ghidra.framework.plugintool.Plugin;
|
||||||
|
@ -77,11 +74,6 @@ public class DbViewerProvider extends ComponentProviderAdapter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ActionContext getActionContext(MouseEvent event) {
|
|
||||||
return new ActionContext(this, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JComponent getComponent() {
|
public JComponent getComponent() {
|
||||||
if (comp == null) {
|
if (comp == null) {
|
||||||
|
|
|
@ -219,7 +219,7 @@ public class PropertyManagerProvider extends ComponentProviderAdapter {
|
||||||
Rectangle rowBounds =
|
Rectangle rowBounds =
|
||||||
table.getCellRect(row, PropertyManagerTableModel.PROPERTY_NAME_COLUMN, true);
|
table.getCellRect(row, PropertyManagerTableModel.PROPERTY_NAME_COLUMN, true);
|
||||||
if (rowBounds.contains(event.getPoint())) {
|
if (rowBounds.contains(event.getPoint())) {
|
||||||
return new ActionContext(this, rowBounds);
|
return createContext(rowBounds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,7 @@ import javax.swing.*;
|
||||||
import javax.swing.event.ChangeEvent;
|
import javax.swing.event.ChangeEvent;
|
||||||
import javax.swing.event.ChangeListener;
|
import javax.swing.event.ChangeListener;
|
||||||
|
|
||||||
import docking.ActionContext;
|
import docking.*;
|
||||||
import docking.ComponentProvider;
|
|
||||||
import docking.action.*;
|
import docking.action.*;
|
||||||
import docking.help.Help;
|
import docking.help.Help;
|
||||||
import docking.help.HelpService;
|
import docking.help.HelpService;
|
||||||
|
@ -700,7 +699,8 @@ public class ListingCodeComparisonPanel
|
||||||
NextDiffAction() {
|
NextDiffAction() {
|
||||||
super("Dual Listing Go To Next Area Marker", owner);
|
super("Dual Listing Go To Next Area Marker", owner);
|
||||||
setEnabled(true);
|
setEnabled(true);
|
||||||
setKeyBindingData(new KeyBindingData('N', InputEvent.CTRL_MASK | InputEvent.ALT_MASK));
|
setKeyBindingData(new KeyBindingData('N',
|
||||||
|
DockingUtils.CONTROL_KEY_MODIFIER_MASK | InputEvent.ALT_DOWN_MASK));
|
||||||
setDescription("Go to the next highlighted area.");
|
setDescription("Go to the next highlighted area.");
|
||||||
setPopupMenuData(new MenuData(new String[] { "Go To Next Highlighted Area" },
|
setPopupMenuData(new MenuData(new String[] { "Go To Next Highlighted Area" },
|
||||||
NEXT_DIFF_ICON, DIFF_NAVIGATE_GROUP));
|
NEXT_DIFF_ICON, DIFF_NAVIGATE_GROUP));
|
||||||
|
@ -738,7 +738,8 @@ public class ListingCodeComparisonPanel
|
||||||
PreviousDiffAction() {
|
PreviousDiffAction() {
|
||||||
super("Dual Listing Go To Previous Area Marker", owner);
|
super("Dual Listing Go To Previous Area Marker", owner);
|
||||||
setEnabled(true);
|
setEnabled(true);
|
||||||
setKeyBindingData(new KeyBindingData('P', InputEvent.CTRL_MASK | InputEvent.ALT_MASK));
|
setKeyBindingData(new KeyBindingData('P',
|
||||||
|
DockingUtils.CONTROL_KEY_MODIFIER_MASK | InputEvent.ALT_DOWN_MASK));
|
||||||
setDescription("Go to the previous highlighted area.");
|
setDescription("Go to the previous highlighted area.");
|
||||||
setPopupMenuData(new MenuData(new String[] { "Go To Previous Highlighted Area" },
|
setPopupMenuData(new MenuData(new String[] { "Go To Previous Highlighted Area" },
|
||||||
PREVIOUS_DIFF_ICON, DIFF_NAVIGATE_GROUP));
|
PREVIOUS_DIFF_ICON, DIFF_NAVIGATE_GROUP));
|
||||||
|
@ -796,9 +797,6 @@ public class ListingCodeComparisonPanel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the listings are showing the entire program.
|
|
||||||
*/
|
|
||||||
public boolean isEntireListingShowing() {
|
public boolean isEntireListingShowing() {
|
||||||
return isShowingEntireListing;
|
return isShowingEntireListing;
|
||||||
}
|
}
|
||||||
|
@ -857,9 +855,6 @@ public class ListingCodeComparisonPanel
|
||||||
toggleHeaderAction.setSelected(show);
|
toggleHeaderAction.setSelected(show);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the listings are being displayed side by side.
|
|
||||||
*/
|
|
||||||
public boolean isSideBySide() {
|
public boolean isSideBySide() {
|
||||||
return isSideBySide;
|
return isSideBySide;
|
||||||
}
|
}
|
||||||
|
@ -2024,18 +2019,18 @@ public class ListingCodeComparisonPanel
|
||||||
|
|
||||||
Object leftMarginContext = getContextForMarginPanels(leftPanel, event);
|
Object leftMarginContext = getContextForMarginPanels(leftPanel, event);
|
||||||
if (leftMarginContext != null) {
|
if (leftMarginContext != null) {
|
||||||
return new ActionContext(provider, leftMarginContext);
|
return new ActionContext(provider).setContextObject(leftMarginContext);
|
||||||
}
|
}
|
||||||
Object rightMarginContext = getContextForMarginPanels(rightPanel, event);
|
Object rightMarginContext = getContextForMarginPanels(rightPanel, event);
|
||||||
if (rightMarginContext != null) {
|
if (rightMarginContext != null) {
|
||||||
return new ActionContext(provider, rightMarginContext);
|
return new ActionContext(provider).setContextObject(rightMarginContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object source = event.getSource();
|
Object source = event.getSource();
|
||||||
if (source instanceof FieldHeaderComp) {
|
if (source instanceof FieldHeaderComp) {
|
||||||
FieldHeaderLocation fieldHeaderLocation =
|
FieldHeaderLocation fieldHeaderLocation =
|
||||||
leftPanel.getFieldHeader().getFieldHeaderLocation(event.getPoint());
|
leftPanel.getFieldHeader().getFieldHeaderLocation(event.getPoint());
|
||||||
return new ActionContext(provider, fieldHeaderLocation);
|
return new ActionContext(provider).setContextObject(fieldHeaderLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
Navigatable focusedNavigatable = dualListingPanel.getFocusedNavigatable();
|
Navigatable focusedNavigatable = dualListingPanel.getFocusedNavigatable();
|
||||||
|
@ -2043,7 +2038,7 @@ public class ListingCodeComparisonPanel
|
||||||
new DualListingActionContext(provider, focusedNavigatable);
|
new DualListingActionContext(provider, focusedNavigatable);
|
||||||
myActionContext.setContextObject(this);
|
myActionContext.setContextObject(this);
|
||||||
myActionContext.setCodeComparisonPanel(this);
|
myActionContext.setCodeComparisonPanel(this);
|
||||||
myActionContext.setSource(source);
|
myActionContext.setSourceObject(source);
|
||||||
return myActionContext;
|
return myActionContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2607,13 +2602,13 @@ public class ListingCodeComparisonPanel
|
||||||
// Are we on a marker margin of the left listing? Return that margin's context.
|
// Are we on a marker margin of the left listing? Return that margin's context.
|
||||||
Object sourceMarginContextObject = getContextObjectForMarginPanels(sourcePanel, event);
|
Object sourceMarginContextObject = getContextObjectForMarginPanels(sourcePanel, event);
|
||||||
if (sourceMarginContextObject != null) {
|
if (sourceMarginContextObject != null) {
|
||||||
return new ActionContext(provider, sourceMarginContextObject);
|
return new ActionContext(provider).setContextObject(sourceMarginContextObject);
|
||||||
}
|
}
|
||||||
// Are we on a marker margin of the right listing? Return that margin's context.
|
// Are we on a marker margin of the right listing? Return that margin's context.
|
||||||
Object destinationMarginContextObject =
|
Object destinationMarginContextObject =
|
||||||
getContextObjectForMarginPanels(destinationPanel, event);
|
getContextObjectForMarginPanels(destinationPanel, event);
|
||||||
if (destinationMarginContextObject != null) {
|
if (destinationMarginContextObject != null) {
|
||||||
return new ActionContext(provider, destinationMarginContextObject);
|
return new ActionContext(provider).setContextObject(destinationMarginContextObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the action is on the Field Header of the left listing panel return an
|
// If the action is on the Field Header of the left listing panel return an
|
||||||
|
@ -2621,7 +2616,7 @@ public class ListingCodeComparisonPanel
|
||||||
if (sourceComponent instanceof FieldHeaderComp) {
|
if (sourceComponent instanceof FieldHeaderComp) {
|
||||||
FieldHeaderLocation fieldHeaderLocation =
|
FieldHeaderLocation fieldHeaderLocation =
|
||||||
sourcePanel.getFieldHeader().getFieldHeaderLocation(event.getPoint());
|
sourcePanel.getFieldHeader().getFieldHeaderLocation(event.getPoint());
|
||||||
return new ActionContext(provider, fieldHeaderLocation);
|
return new ActionContext(provider).setContextObject(fieldHeaderLocation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -259,7 +259,7 @@ public class OpenVersionedFileDialog extends DataTreeDialog {
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
ActionContext actionContext = new ActionContext(null, event.getSource(), this);
|
ActionContext actionContext = new ActionContext(null, this, event.getComponent());
|
||||||
actionContext.setMouseEvent(event);
|
actionContext.setMouseEvent(event);
|
||||||
|
|
||||||
return actionContext;
|
return actionContext;
|
||||||
|
|
|
@ -35,7 +35,7 @@ public class FSBActionContext extends ActionContext {
|
||||||
* @param gTree {@link FileSystemBrowserPlugin} provider tree.
|
* @param gTree {@link FileSystemBrowserPlugin} provider tree.
|
||||||
*/
|
*/
|
||||||
public FSBActionContext(ComponentProvider provider, Object contextObject, GTree gTree) {
|
public FSBActionContext(ComponentProvider provider, Object contextObject, GTree gTree) {
|
||||||
super(provider, contextObject);
|
super(provider, contextObject, gTree);
|
||||||
this.gTree = gTree;
|
this.gTree = gTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ import java.util.Set;
|
||||||
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
import docking.ActionContext;
|
|
||||||
import docking.action.DockingActionIf;
|
import docking.action.DockingActionIf;
|
||||||
import ghidra.app.plugin.core.programtree.ProgramTreePlugin;
|
import ghidra.app.plugin.core.programtree.ProgramTreePlugin;
|
||||||
import ghidra.app.plugin.core.programtree.ViewProviderService;
|
import ghidra.app.plugin.core.programtree.ViewProviderService;
|
||||||
|
@ -99,7 +98,7 @@ public class ModuleAlgorithmPluginTest extends AbstractGhidraHeadedIntegrationTe
|
||||||
|
|
||||||
getContextObject(vps);
|
getContextObject(vps);
|
||||||
|
|
||||||
performAction(CollectionUtils.any(actions), new ActionContext(null, context), true);
|
performAction(CollectionUtils.any(actions), createContext(context), true);
|
||||||
|
|
||||||
waitForTasks();
|
waitForTasks();
|
||||||
program.flushEvents();
|
program.flushEvents();
|
||||||
|
|
|
@ -433,7 +433,7 @@ public class BookmarkPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
Address address = bookmark.getAddress();
|
Address address = bookmark.getAddress();
|
||||||
DeleteBookmarkAction action = new DeleteBookmarkAction(plugin, bookmark, true);
|
DeleteBookmarkAction action = new DeleteBookmarkAction(plugin, bookmark, true);
|
||||||
MarkerLocation markerLocation = new MarkerLocation(null, address, 0, 0);
|
MarkerLocation markerLocation = new MarkerLocation(null, address, 0, 0);
|
||||||
performAction(action, new ActionContext(null, markerLocation), true);
|
performAction(action, createContext(markerLocation), true);
|
||||||
list = getBookmarks(program.getBookmarkManager());
|
list = getBookmarks(program.getBookmarkManager());
|
||||||
assertFalse(list.contains(bookmark));
|
assertFalse(list.contains(bookmark));
|
||||||
|
|
||||||
|
@ -441,7 +441,7 @@ public class BookmarkPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
address = bookmark.getAddress();
|
address = bookmark.getAddress();
|
||||||
action = new DeleteBookmarkAction(plugin, bookmark, false);
|
action = new DeleteBookmarkAction(plugin, bookmark, false);
|
||||||
markerLocation = new MarkerLocation(null, address, 0, 0);
|
markerLocation = new MarkerLocation(null, address, 0, 0);
|
||||||
performAction(action, new ActionContext(null, markerLocation), true);
|
performAction(action, createContext(markerLocation), true);
|
||||||
list = getBookmarks(program.getBookmarkManager());
|
list = getBookmarks(program.getBookmarkManager());
|
||||||
assertFalse(list.contains(bookmark));
|
assertFalse(list.contains(bookmark));
|
||||||
}
|
}
|
||||||
|
@ -543,8 +543,8 @@ public class BookmarkPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
CreateStructureCmd cmd = new CreateStructureCmd(addr("0100b6db"), 20);
|
CreateStructureCmd cmd = new CreateStructureCmd(addr("0100b6db"), 20);
|
||||||
applyCmd(program, cmd);
|
applyCmd(program, cmd);
|
||||||
|
|
||||||
List<DockingActionIf> actions = runSwing(() -> plugin.getPopupActions(
|
List<DockingActionIf> actions = runSwing(() -> plugin.getPopupActions(null,
|
||||||
null, new ActionContext(null, new MarkerLocation(null, addr("0100b6db"), 0, 0))));
|
createContext(new MarkerLocation(null, addr("0100b6db"), 0, 0))));
|
||||||
assertEquals(10, actions.size());
|
assertEquals(10, actions.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -131,7 +131,7 @@ public class HeaderActionsTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
DockingAction headerAction = getHeaderAction("Remove All Fields");
|
DockingAction headerAction = getHeaderAction("Remove All Fields");
|
||||||
FieldHeaderLocation loc = new FieldHeaderLocation(functionFormat, factorys[0], 0, 0);
|
FieldHeaderLocation loc = new FieldHeaderLocation(functionFormat, factorys[0], 0, 0);
|
||||||
ActionContext context = new ActionContext(provider, loc);
|
ActionContext context = createContext(provider, loc);
|
||||||
performAction(headerAction, context, false);
|
performAction(headerAction, context, false);
|
||||||
pressContinueOnResetFormatDialog("Remove All Fields?");
|
pressContinueOnResetFormatDialog("Remove All Fields?");
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ public class HeaderActionsTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
selectHeaderField(factories[0]);
|
selectHeaderField(factories[0]);
|
||||||
FieldHeaderLocation loc = new FieldHeaderLocation(functionFormat, factories[0], 0, 0);
|
FieldHeaderLocation loc = new FieldHeaderLocation(functionFormat, factories[0], 0, 0);
|
||||||
ActionContext context = new ActionContext(provider, loc);
|
ActionContext context = createContext(provider, loc);
|
||||||
|
|
||||||
DockingAction headerAction = getHeaderAction("Add Spacer Field");
|
DockingAction headerAction = getHeaderAction("Add Spacer Field");
|
||||||
performAction(headerAction, context, true);
|
performAction(headerAction, context, true);
|
||||||
|
@ -173,7 +173,7 @@ public class HeaderActionsTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
selectHeaderField(factories[0]);
|
selectHeaderField(factories[0]);
|
||||||
|
|
||||||
FieldHeaderLocation loc = new FieldHeaderLocation(functionFormat, factories[0], 0, 0);
|
FieldHeaderLocation loc = new FieldHeaderLocation(functionFormat, factories[0], 0, 0);
|
||||||
ActionContext context = new ActionContext(provider, loc);
|
ActionContext context = createContext(provider, loc);
|
||||||
|
|
||||||
DockingAction headerAction = getHeaderAction("SetTextAction");
|
DockingAction headerAction = getHeaderAction("SetTextAction");
|
||||||
performAction(headerAction, context, false);
|
performAction(headerAction, context, false);
|
||||||
|
@ -200,7 +200,7 @@ public class HeaderActionsTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertTrue(factories[1].isEnabled());
|
assertTrue(factories[1].isEnabled());
|
||||||
|
|
||||||
FieldHeaderLocation loc = new FieldHeaderLocation(functionFormat, factories[1], 0, 0);
|
FieldHeaderLocation loc = new FieldHeaderLocation(functionFormat, factories[1], 0, 0);
|
||||||
ActionContext context = new ActionContext(provider, loc);
|
ActionContext context = createContext(provider, loc);
|
||||||
|
|
||||||
DockingAction headerAction = getHeaderAction("Disable Field");
|
DockingAction headerAction = getHeaderAction("Disable Field");
|
||||||
performAction(headerAction, context, true);
|
performAction(headerAction, context, true);
|
||||||
|
@ -222,7 +222,7 @@ public class HeaderActionsTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertTrue(factories[1] instanceof FunctionSignatureFieldFactory);
|
assertTrue(factories[1] instanceof FunctionSignatureFieldFactory);
|
||||||
|
|
||||||
FieldHeaderLocation loc = new FieldHeaderLocation(functionFormat, factories[1], 0, 1);
|
FieldHeaderLocation loc = new FieldHeaderLocation(functionFormat, factories[1], 0, 1);
|
||||||
ActionContext context = new ActionContext(provider, loc);
|
ActionContext context = createContext(provider, loc);
|
||||||
|
|
||||||
DockingAction headerAction = getHeaderAction("Remove Field");
|
DockingAction headerAction = getHeaderAction("Remove Field");
|
||||||
performAction(headerAction, context, true);
|
performAction(headerAction, context, true);
|
||||||
|
@ -242,7 +242,7 @@ public class HeaderActionsTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
functionFormat.removeAllFactories();
|
functionFormat.removeAllFactories();
|
||||||
|
|
||||||
FieldHeaderLocation loc = new FieldHeaderLocation(functionFormat, factories[1], 0, 1);
|
FieldHeaderLocation loc = new FieldHeaderLocation(functionFormat, factories[1], 0, 1);
|
||||||
ActionContext context = new ActionContext(provider, loc);
|
ActionContext context = createContext(provider, loc);
|
||||||
|
|
||||||
DockingAction headerAction = getHeaderAction("Add All Field");
|
DockingAction headerAction = getHeaderAction("Add All Field");
|
||||||
performAction(headerAction, context, true);
|
performAction(headerAction, context, true);
|
||||||
|
@ -272,8 +272,7 @@ public class HeaderActionsTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enterTextIntoDialog(String input) {
|
private void enterTextIntoDialog(String input) {
|
||||||
InputDialog dialog =
|
InputDialog dialog = waitForDialogComponent(InputDialog.class);
|
||||||
waitForDialogComponent(null, InputDialog.class, DEFAULT_WINDOW_TIMEOUT);
|
|
||||||
assertNotNull("Never found the spacer text input dialog", dialog);
|
assertNotNull("Never found the spacer text input dialog", dialog);
|
||||||
JTextComponent textField =
|
JTextComponent textField =
|
||||||
(JTextComponent) findComponentByName(dialog, "input.dialog.text.field.0");
|
(JTextComponent) findComponentByName(dialog, "input.dialog.text.field.0");
|
||||||
|
@ -291,7 +290,7 @@ public class HeaderActionsTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void pressContinueOnResetFormatDialog(String title) {
|
private void pressContinueOnResetFormatDialog(String title) {
|
||||||
Window window = waitForWindow(title, DEFAULT_WINDOW_TIMEOUT);
|
Window window = waitForWindow(title);
|
||||||
assertNotNull("Never found the dialog: " + title, window);
|
assertNotNull("Never found the dialog: " + title, window);
|
||||||
pressButtonByText(window, "Continue");
|
pressButtonByText(window, "Continue");
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
|
@ -275,14 +275,14 @@ public class HeaderTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
public void testInsertDeleteRow() {
|
public void testInsertDeleteRow() {
|
||||||
FieldFormatModel model = header.getHeaderTab().getModel();
|
FieldFormatModel model = header.getHeaderTab().getModel();
|
||||||
InsertRowAction act = new InsertRowAction("Test", header);
|
InsertRowAction act = new InsertRowAction("Test", header);
|
||||||
act.isEnabledForContext(
|
act.isEnabledForContext(new ActionContext(cb.getProvider()).setContextObject(
|
||||||
new ActionContext(null, new FieldHeaderLocation(model, null, 0, 0)));
|
new FieldHeaderLocation(model, null, 0, 0)));
|
||||||
performAction(act, true);
|
performAction(act, true);
|
||||||
assertEquals(8, model.getNumRows());
|
assertEquals(8, model.getNumRows());
|
||||||
assertEquals(0, model.getNumFactorys(0));
|
assertEquals(0, model.getNumFactorys(0));
|
||||||
RemoveRowAction act2 = new RemoveRowAction("Test", header);
|
RemoveRowAction act2 = new RemoveRowAction("Test", header);
|
||||||
act2.isEnabledForContext(
|
act2.isEnabledForContext(new ActionContext(cb.getProvider()).setContextObject(
|
||||||
new ActionContext(null, new FieldHeaderLocation(model, null, 0, 0)));
|
new FieldHeaderLocation(model, null, 0, 0)));
|
||||||
performAction(act2, true);
|
performAction(act2, true);
|
||||||
assertEquals(7, model.getNumRows());
|
assertEquals(7, model.getNumRows());
|
||||||
assertEquals(2, model.getNumFactorys(0));
|
assertEquals(2, model.getNumFactorys(0));
|
||||||
|
@ -294,8 +294,8 @@ public class HeaderTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
ListingField bf = cb.getCurrentField();
|
ListingField bf = cb.getCurrentField();
|
||||||
int startX = bf.getStartX();
|
int startX = bf.getStartX();
|
||||||
InsertRowAction act = new InsertRowAction("Test", header);
|
InsertRowAction act = new InsertRowAction("Test", header);
|
||||||
act.isEnabledForContext(
|
act.isEnabledForContext(new ActionContext(cb.getProvider()).setContextObject(
|
||||||
new ActionContext(null, new FieldHeaderLocation(model, null, 0, 0)));
|
new FieldHeaderLocation(model, null, 0, 0)));
|
||||||
performAction(act, true);
|
performAction(act, true);
|
||||||
int width = bf.getWidth();
|
int width = bf.getWidth();
|
||||||
int dragX = startX + width / 2;
|
int dragX = startX + width / 2;
|
||||||
|
|
|
@ -109,21 +109,21 @@ public class AutoRenamePluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
ViewProviderService vps = vmService.getCurrentViewProvider();
|
ViewProviderService vps = vmService.getCurrentViewProvider();
|
||||||
|
|
||||||
Object context = vps.getActivePopupObject(null);
|
Object context = vps.getActivePopupObject(null);
|
||||||
assertTrue(!renameAction.isEnabledForContext(new ActionContext(null, context)));
|
|
||||||
assertTrue(!labelAction.isEnabledForContext(new ActionContext(null, context)));
|
assertTrue(!renameAction.isEnabledForContext(createContext(context)));
|
||||||
|
assertTrue(!labelAction.isEnabledForContext(createContext(context)));
|
||||||
|
|
||||||
gps = new GroupPath[1];
|
gps = new GroupPath[1];
|
||||||
gps[0] = new GroupPath(new String[] { root.getName(), "DLLs", "USER32.DLL" });
|
gps[0] = new GroupPath(new String[] { root.getName(), "DLLs", "USER32.DLL" });
|
||||||
setSelection(gps);
|
setSelection(gps);
|
||||||
|
|
||||||
context = vps.getActivePopupObject(null);
|
context = vps.getActivePopupObject(null);
|
||||||
assertTrue(renameAction.isEnabledForContext(new ActionContext(null, context)));
|
assertTrue(renameAction.isEnabledForContext(createContext(context)));
|
||||||
assertTrue(!labelAction.isEnabledForContext(new ActionContext(null, context)));
|
assertTrue(!labelAction.isEnabledForContext(createContext(context)));
|
||||||
|
|
||||||
// fire Label program location
|
// fire Label program location
|
||||||
Address addr = getAddr(0x10033f6);
|
Address addr = getAddr(0x10033f6);
|
||||||
LabelFieldLocation loc =
|
LabelFieldLocation loc = new LabelFieldLocation(program, addr, "SUB_010033f6");
|
||||||
new LabelFieldLocation(program, addr, "SUB_010033f6");
|
|
||||||
tool.firePluginEvent(new ProgramLocationPluginEvent("test", loc, program));
|
tool.firePluginEvent(new ProgramLocationPluginEvent("test", loc, program));
|
||||||
|
|
||||||
ActionContext actionContext = cb.getProvider().getActionContext(null);
|
ActionContext actionContext = cb.getProvider().getActionContext(null);
|
||||||
|
@ -147,7 +147,7 @@ public class AutoRenamePluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
ViewManagerService vmService = tool.getService(ViewManagerService.class);
|
ViewManagerService vmService = tool.getService(ViewManagerService.class);
|
||||||
ViewProviderService vps = vmService.getCurrentViewProvider();
|
ViewProviderService vps = vmService.getCurrentViewProvider();
|
||||||
Object context = vps.getActivePopupObject(null);
|
Object context = vps.getActivePopupObject(null);
|
||||||
performAction(renameAction, new ActionContext(null, context), true);
|
performAction(renameAction, createContext(context), true);
|
||||||
program.flushEvents();
|
program.flushEvents();
|
||||||
|
|
||||||
assertNotNull(program.getListing().getFragment("Main Tree", s.getName()));
|
assertNotNull(program.getListing().getFragment("Main Tree", s.getName()));
|
||||||
|
@ -166,12 +166,8 @@ public class AutoRenamePluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
new LabelFieldLocation(program, addr, null, "SUB_010033f6", null, 0, 0);
|
new LabelFieldLocation(program, addr, null, "SUB_010033f6", null, 0, 0);
|
||||||
cb.goTo(loc);
|
cb.goTo(loc);
|
||||||
|
|
||||||
SwingUtilities.invokeAndWait(new Runnable() {
|
SwingUtilities.invokeAndWait(
|
||||||
@Override
|
() -> labelAction.actionPerformed(cb.getProvider().getActionContext(null)));
|
||||||
public void run() {
|
|
||||||
labelAction.actionPerformed(cb.getProvider().getActionContext(null));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
program.flushEvents();
|
program.flushEvents();
|
||||||
assertNull(program.getListing().getFragment("SUB_010033f6", origName));
|
assertNull(program.getListing().getFragment("SUB_010033f6", origName));
|
||||||
assertEquals("SUB_010033f6", frag.getName());
|
assertEquals("SUB_010033f6", frag.getName());
|
||||||
|
@ -182,22 +178,12 @@ public class AutoRenamePluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setViewToMainTree() {
|
private void setViewToMainTree() {
|
||||||
runSwing(new Runnable() {
|
runSwing(() -> service.setViewedTree("Main Tree"));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
service.setViewedTree("Main Tree");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setSelection(final GroupPath[] gps) {
|
private void setSelection(final GroupPath[] gps) {
|
||||||
|
|
||||||
runSwing(new Runnable() {
|
runSwing(() -> service.setGroupSelection(gps));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
service.setGroupSelection(gps);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@ import java.util.*;
|
||||||
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
import docking.ActionContext;
|
|
||||||
import docking.action.DockingActionIf;
|
import docking.action.DockingActionIf;
|
||||||
import ghidra.app.plugin.core.programtree.ProgramTreePlugin;
|
import ghidra.app.plugin.core.programtree.ProgramTreePlugin;
|
||||||
import ghidra.app.plugin.core.programtree.ViewProviderService;
|
import ghidra.app.plugin.core.programtree.ViewProviderService;
|
||||||
|
@ -113,7 +112,8 @@ public class ModuleSortPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
Object context = vps.getActivePopupObject(null);
|
Object context = vps.getActivePopupObject(null);
|
||||||
for (DockingActionIf action : actions) {
|
for (DockingActionIf action : actions) {
|
||||||
assertTrue(action.isAddToPopup(new ActionContext(null, context)));
|
|
||||||
|
assertTrue(action.isAddToPopup(vps.getActionContext(null)));
|
||||||
}
|
}
|
||||||
|
|
||||||
gps = new GroupPath[1];
|
gps = new GroupPath[1];
|
||||||
|
@ -122,7 +122,7 @@ public class ModuleSortPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
context = vps.getActivePopupObject(null);
|
context = vps.getActivePopupObject(null);
|
||||||
for (DockingActionIf action : actions) {
|
for (DockingActionIf action : actions) {
|
||||||
assertTrue(!action.isAddToPopup(new ActionContext(null, context)));
|
assertTrue(!action.isAddToPopup(vps.getActionContext(null)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,11 +159,10 @@ public class ModuleSortPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
ViewManagerService vmService = tool.getService(ViewManagerService.class);
|
ViewManagerService vmService = tool.getService(ViewManagerService.class);
|
||||||
ViewProviderService vps = vmService.getCurrentViewProvider();
|
ViewProviderService vps = vmService.getCurrentViewProvider();
|
||||||
|
|
||||||
Object context = vps.getActivePopupObject(null);
|
|
||||||
|
|
||||||
for (DockingActionIf action : actions) {
|
for (DockingActionIf action : actions) {
|
||||||
if (action.getName().indexOf("Name") > 0) {
|
if (action.getName().indexOf("Name") > 0) {
|
||||||
action.actionPerformed(new ActionContext(null, context));
|
|
||||||
|
action.actionPerformed(vps.getActionContext(null));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -205,7 +204,7 @@ public class ModuleSortPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
for (DockingActionIf action : actions) {
|
for (DockingActionIf action : actions) {
|
||||||
if (action.getName().indexOf("Address") > 0) {
|
if (action.getName().indexOf("Address") > 0) {
|
||||||
action.actionPerformed(new ActionContext(null, context));
|
action.actionPerformed(vps.getActionContext(null));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,7 +231,7 @@ public class ModuleSortPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
Object context = vps.getActivePopupObject(null);
|
Object context = vps.getActivePopupObject(null);
|
||||||
for (DockingActionIf action : actions) {
|
for (DockingActionIf action : actions) {
|
||||||
assertTrue(!action.isAddToPopup(new ActionContext(null, context)));
|
assertTrue(!action.isAddToPopup(vps.getActionContext(null)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,7 +152,7 @@ public class ProviderNavigationPluginTest extends AbstractProgramBasedTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void forceActivate(ComponentProvider provider) {
|
private void forceActivate(ComponentProvider provider) {
|
||||||
ActionContext context = new ActionContext(provider, provider);
|
ActionContext context = new ActionContext(provider);
|
||||||
for (DockingContextListener l : testContextListeners) {
|
for (DockingContextListener l : testContextListeners) {
|
||||||
l.contextChanged(context);
|
l.contextChanged(context);
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,4 +67,9 @@ public class DummyToolActions implements DockingToolActions {
|
||||||
public void removeActions(ComponentProvider provider) {
|
public void removeActions(ComponentProvider provider) {
|
||||||
// stub
|
// stub
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsAction(DockingActionIf action) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -528,13 +528,15 @@ public abstract class DecompilerCodeComparisonPanel<T extends DualDecompilerFiel
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActionContext getActionContext(ComponentProvider provider, MouseEvent event) {
|
public ActionContext getActionContext(ComponentProvider provider, MouseEvent event) {
|
||||||
Object sourceObject = null;
|
|
||||||
|
Component component = null;
|
||||||
if (event != null) {
|
if (event != null) {
|
||||||
sourceObject = event.getSource();
|
component = event.getComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
CDisplayPanel focusedDecompilerPanel = getFocusedDecompilerPanel();
|
CDisplayPanel focusedDecompilerPanel = getFocusedDecompilerPanel();
|
||||||
DualDecompilerActionContext dualDecompContext =
|
DualDecompilerActionContext dualDecompContext =
|
||||||
new DualDecompilerActionContext(provider, focusedDecompilerPanel, sourceObject);
|
new DualDecompilerActionContext(provider, focusedDecompilerPanel, component);
|
||||||
dualDecompContext.setCodeComparisonPanel(this);
|
dualDecompContext.setCodeComparisonPanel(this);
|
||||||
return dualDecompContext;
|
return dualDecompContext;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.decompiler.component;
|
package ghidra.app.decompiler.component;
|
||||||
|
|
||||||
|
import java.awt.Component;
|
||||||
|
|
||||||
import docking.ActionContext;
|
import docking.ActionContext;
|
||||||
import docking.ComponentProvider;
|
import docking.ComponentProvider;
|
||||||
import docking.widgets.fieldpanel.internal.FieldPanelCoordinator;
|
import docking.widgets.fieldpanel.internal.FieldPanelCoordinator;
|
||||||
|
@ -34,11 +36,11 @@ public class DualDecompilerActionContext extends ActionContext
|
||||||
* Creates an action context for a dual decompiler panel.
|
* Creates an action context for a dual decompiler panel.
|
||||||
* @param provider the provider for this context
|
* @param provider the provider for this context
|
||||||
* @param cPanel the decompiler panel associated with this context
|
* @param cPanel the decompiler panel associated with this context
|
||||||
* @param sourceObject the source of the action
|
* @param source the source of the action
|
||||||
*/
|
*/
|
||||||
public DualDecompilerActionContext(ComponentProvider provider, CDisplayPanel cPanel,
|
public DualDecompilerActionContext(ComponentProvider provider, CDisplayPanel cPanel,
|
||||||
Object sourceObject) {
|
Component source) {
|
||||||
super(provider, cPanel, sourceObject);
|
super(provider, cPanel, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -122,7 +122,7 @@ public class SetFormatDialogComponentProvider extends DialogComponentProvider {
|
||||||
FieldHeader headerPanel = listingPanel.getFieldHeader();
|
FieldHeader headerPanel = listingPanel.getFieldHeader();
|
||||||
if (headerPanel != null && headerPanel.isAncestorOf(event.getComponent())) {
|
if (headerPanel != null && headerPanel.isAncestorOf(event.getComponent())) {
|
||||||
FieldHeaderLocation fhLoc = headerPanel.getFieldHeaderLocation(event.getPoint());
|
FieldHeaderLocation fhLoc = headerPanel.getFieldHeaderLocation(event.getPoint());
|
||||||
return new ActionContext(null, fhLoc);
|
return new ActionContext().setContextObject(fhLoc);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -624,7 +624,7 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||||
assertNotNull(action);
|
assertNotNull(action);
|
||||||
|
|
||||||
FieldHeaderLocation fhLoc = createFieldHeaderLocation(provider);
|
FieldHeaderLocation fhLoc = createFieldHeaderLocation(provider);
|
||||||
ActionContext context = new ActionContext(null, fhLoc);
|
ActionContext context = createContext(fhLoc);
|
||||||
performAction(action, context, true);
|
performAction(action, context, true);
|
||||||
|
|
||||||
waitForConditionWithoutFailing(() -> fieldIsVisible(provider, actionName));
|
waitForConditionWithoutFailing(() -> fieldIsVisible(provider, actionName));
|
||||||
|
@ -728,7 +728,7 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||||
assertNotNull(action);
|
assertNotNull(action);
|
||||||
|
|
||||||
FieldHeaderLocation fhLoc = createFieldHeaderLocation(provider);
|
FieldHeaderLocation fhLoc = createFieldHeaderLocation(provider);
|
||||||
ActionContext context = new ActionContext(null, fhLoc);
|
ActionContext context = createContext(fhLoc);
|
||||||
performAction(action, context, false);
|
performAction(action, context, false);
|
||||||
|
|
||||||
Window dialog = waitForWindow("Reset All Formats?");
|
Window dialog = waitForWindow("Reset All Formats?");
|
||||||
|
|
|
@ -29,6 +29,6 @@ public class FcgActionContext extends ActionContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
public FcgActionContext(FcgProvider provider, Object contextObject) {
|
public FcgActionContext(FcgProvider provider, Object contextObject) {
|
||||||
super(provider, contextObject);
|
super(provider, contextObject, provider.getComponent());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -277,7 +277,7 @@ public class VTFunctionAssociationProvider extends ComponentProviderAdapter
|
||||||
getExistingMatch(sourceFunction, destinationFunction));
|
getExistingMatch(sourceFunction, destinationFunction));
|
||||||
vtListingContext.setCodeComparisonPanel(dualListingPanel);
|
vtListingContext.setCodeComparisonPanel(dualListingPanel);
|
||||||
vtListingContext.setContextObject(dualListingPanel);
|
vtListingContext.setContextObject(dualListingPanel);
|
||||||
vtListingContext.setSource(source);
|
vtListingContext.setSourceObject(source);
|
||||||
return vtListingContext;
|
return vtListingContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -493,7 +493,7 @@ public class VTMarkupItemsTableProvider extends ComponentProviderAdapter
|
||||||
new VTListingContext(this, vtListingNavigator);
|
new VTListingContext(this, vtListingNavigator);
|
||||||
vtListingContext.setCodeComparisonPanel(dualListingPanel);
|
vtListingContext.setCodeComparisonPanel(dualListingPanel);
|
||||||
vtListingContext.setContextObject(dualListingPanel);
|
vtListingContext.setContextObject(dualListingPanel);
|
||||||
vtListingContext.setSource(source);
|
vtListingContext.setSourceObject(source);
|
||||||
return vtListingContext;
|
return vtListingContext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,48 +15,128 @@
|
||||||
*/
|
*/
|
||||||
package docking;
|
package docking;
|
||||||
|
|
||||||
|
import java.awt.Component;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
|
|
||||||
|
import docking.action.DockingActionIf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ComponentProviders are required to return Objects of this type in their getActionContext()
|
* Action context is a class that contains state information that is given to
|
||||||
|
* {@link DockingActionIf}s for them to decide if they are enabled for a given user action. User
|
||||||
|
* actions are toolbar button presses, menu bar item presses and popup menu item presses. As
|
||||||
|
* the user changes focus in the system, all actions are queried with the current context. Thus,
|
||||||
|
* toolbar buttons and menu items will enable and disable as the user interacts with the system.
|
||||||
|
* When the user executes an action, the current context will be passed to the backing
|
||||||
|
* {@link DockingActionIf}. Ultimately, context serves to control action enablement and to
|
||||||
|
* allow plugins to share state with actions without having to store that state information
|
||||||
|
* in class fields of the plugin.
|
||||||
|
*
|
||||||
|
* <p>ComponentProviders are required to return Objects of this type in their getActionContext()
|
||||||
* methods. Generally, ComponentProviders have two ways to use this class. They can either create
|
* methods. Generally, ComponentProviders have two ways to use this class. They can either create
|
||||||
* an ActionContext instance and pass in a contextObject that will be useful to its actions or,
|
* an ActionContext instance and pass in a contextObject that will be useful to its actions or,
|
||||||
* subclass the ActionContext object to include specific methods to provide the information that
|
* subclass the ActionContext object to include specific methods to provide the information that
|
||||||
* actions will require.
|
* actions will require.
|
||||||
|
*
|
||||||
|
* <p>The data contained by this class has meaning that can change relative to the code that
|
||||||
|
* created it. The intended purpose for the fields of this class is as follows:
|
||||||
|
* <ul>
|
||||||
|
* <li><b>provider</b> - the component provider to which this context belongs; the provider that
|
||||||
|
* contains the component that is the source of the user action
|
||||||
|
* </li>
|
||||||
|
* <li><b>contextObject</b> - client-defined data object. This allows clients to save any
|
||||||
|
* information desired to be used when the action is performed.
|
||||||
|
* </li>
|
||||||
|
* <li><b>sourceObject</b> - when checking enablement, this is the item that was clicked or
|
||||||
|
* activated; when performing an action this is either the active
|
||||||
|
* object or the component that was clicked. This value may change
|
||||||
|
* between the check for
|
||||||
|
* {@link DockingActionIf#isEnabledForContext(ActionContext) enablement}
|
||||||
|
* and {@link DockingActionIf#actionPerformed(ActionContext) execution}.
|
||||||
|
* </li>
|
||||||
|
* <li><b>sourceComponent</b> - this value is the component that is the source of the current
|
||||||
|
* context. Whereas the <code>sourceObject</code> is the actual
|
||||||
|
* clicked item, this value is the focused/active component and
|
||||||
|
* will not change between
|
||||||
|
* {@link DockingActionIf#isEnabledForContext(ActionContext) enablement}
|
||||||
|
* and {@link DockingActionIf#actionPerformed(ActionContext) execution}.
|
||||||
|
* </li>
|
||||||
|
* <li><b>mouseEvent</b> - the mouse event that triggered the action; null if the action was
|
||||||
|
* triggered by a key binding.
|
||||||
|
* </li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>Ultimately, clients can pass any values they wish for the fields of this class, even if
|
||||||
|
* that changes the meaning of the fields outlined above.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class ActionContext {
|
public class ActionContext {
|
||||||
private ComponentProvider provider;
|
private ComponentProvider provider;
|
||||||
|
private MouseEvent mouseEvent;
|
||||||
private Object contextObject;
|
private Object contextObject;
|
||||||
private Object sourceObject;
|
private Object sourceObject;
|
||||||
private MouseEvent mouseEvent;
|
|
||||||
|
// Note: the setting of this object is delayed. This allows clients to build-up the state
|
||||||
|
// of this context. This object will be set when getSourceComponent() is called if it
|
||||||
|
// has not already been set.
|
||||||
|
private Component sourceComponent;
|
||||||
|
|
||||||
public ActionContext() {
|
public ActionContext() {
|
||||||
this(null, null);
|
this(null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ActionContext(ComponentProvider cp) {
|
||||||
|
this(cp, null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic constructor for ActionContext
|
* Basic constructor for ActionContext
|
||||||
* @param provider the ComponentProvider that generated this context.
|
* @param provider the ComponentProvider that generated this context.
|
||||||
* @param contextObject an optional contextObject that the ComponentProvider can provide
|
* @param sourceComponent an optional source object; this is intended to be the component that
|
||||||
* to the action.
|
* is the source of the context, usually the focused component
|
||||||
*/
|
*/
|
||||||
public ActionContext(ComponentProvider provider, Object contextObject) {
|
public ActionContext(ComponentProvider provider, Component sourceComponent) {
|
||||||
this.provider = provider;
|
this(provider, sourceComponent, sourceComponent);
|
||||||
this.contextObject = contextObject;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
* @param provider the ComponentProvider that generated this context.
|
* @param provider the ComponentProvider that generated this context.
|
||||||
* @param contextObject an optional contextObject that the ComponentProvider can provide
|
* @param contextObject an optional contextObject that the ComponentProvider can provide; this
|
||||||
* @param sourceObject an optional source object; this can be anything that actions wish to
|
* can be anything that actions wish to later retrieve
|
||||||
* later retrieve
|
* @param sourceComponent an optional source object; this is intended to be the component that
|
||||||
|
* is the source of the context, usually the focused component
|
||||||
*/
|
*/
|
||||||
public ActionContext(ComponentProvider provider, Object contextObject, Object sourceObject) {
|
public ActionContext(ComponentProvider provider, Object contextObject,
|
||||||
this(provider, contextObject);
|
Component sourceComponent) {
|
||||||
this.sourceObject = sourceObject;
|
this.provider = provider;
|
||||||
|
this.contextObject = contextObject;
|
||||||
|
this.sourceObject = sourceComponent;
|
||||||
|
this.sourceComponent = sourceComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void lazyDeriveSourceComponent() {
|
||||||
|
|
||||||
|
if (sourceComponent != null) {
|
||||||
|
// Do not allow this to change once set. This prevents the value from getting changed
|
||||||
|
// when the user clicks a menu item.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check this in order of preference
|
||||||
|
if (sourceObject instanceof Component) {
|
||||||
|
sourceComponent = (Component) sourceObject;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mouseEvent != null) {
|
||||||
|
sourceComponent = mouseEvent.getComponent();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contextObject instanceof Component) {
|
||||||
|
sourceComponent = (Component) contextObject;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -83,9 +163,11 @@ public class ActionContext {
|
||||||
* choosing that can be provided for later retrieval.
|
* choosing that can be provided for later retrieval.
|
||||||
*
|
*
|
||||||
* @param contextObject Sets the context object for this context.
|
* @param contextObject Sets the context object for this context.
|
||||||
|
* @return this context
|
||||||
*/
|
*/
|
||||||
public void setContextObject(Object contextObject) {
|
public ActionContext setContextObject(Object contextObject) {
|
||||||
this.contextObject = contextObject;
|
this.contextObject = contextObject;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -98,22 +180,28 @@ public class ActionContext {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the sourceObject for this ActionContext. This method is used internally by the
|
* Sets the sourceObject for this ActionContext. This method is used internally by the
|
||||||
* DockingWindowManager. ComponentProvider and action developers should
|
* DockingWindowManager. ComponentProvider and action developers should only use this
|
||||||
* only use this method for testing.
|
* method for testing.
|
||||||
|
*
|
||||||
* @param sourceObject the source object
|
* @param sourceObject the source object
|
||||||
|
* @return this context
|
||||||
*/
|
*/
|
||||||
public void setSource(Object sourceObject) {
|
public ActionContext setSourceObject(Object sourceObject) {
|
||||||
this.sourceObject = sourceObject;
|
this.sourceObject = sourceObject;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the context's mouse event. Contexts that are based upon key events will have no
|
* Updates the context's mouse event. Contexts that are based upon key events will have no
|
||||||
* mouse event.
|
* mouse event. This method is really for the framework to use. Client calls to this
|
||||||
|
* method will be overridden by the framework when menu items are clicked.
|
||||||
*
|
*
|
||||||
* @param e the event that triggered this context.
|
* @param e the event that triggered this context.
|
||||||
|
* @return this context
|
||||||
*/
|
*/
|
||||||
public void setMouseEvent(MouseEvent e) {
|
public ActionContext setMouseEvent(MouseEvent e) {
|
||||||
this.mouseEvent = e;
|
this.mouseEvent = e;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -126,6 +214,17 @@ public class ActionContext {
|
||||||
return mouseEvent;
|
return mouseEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the component that is the target of this context. This value should not change
|
||||||
|
* whether the context is triggered by a key binding or mouse event.
|
||||||
|
*
|
||||||
|
* @return the component; may be null
|
||||||
|
*/
|
||||||
|
public Component getSourceComponent() {
|
||||||
|
lazyDeriveSourceComponent();
|
||||||
|
return sourceComponent;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|
||||||
|
@ -134,6 +233,7 @@ public class ActionContext {
|
||||||
"\tprovider: " + provider + ",\n" +
|
"\tprovider: " + provider + ",\n" +
|
||||||
"\tcontextObject: " + contextObject + ",\n" +
|
"\tcontextObject: " + contextObject + ",\n" +
|
||||||
"\tsourceObject: " + sourceObject + ",\n" +
|
"\tsourceObject: " + sourceObject + ",\n" +
|
||||||
|
"\tsourceComponent: " + sourceComponent + ",\n" +
|
||||||
"\tmouseEvent: " + mouseEvent + "\n" +
|
"\tmouseEvent: " + mouseEvent + "\n" +
|
||||||
"}";
|
"}";
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
|
|
|
@ -27,6 +27,8 @@ public interface ComponentLoadedListener {
|
||||||
* Called when the component is made displayable
|
* Called when the component is made displayable
|
||||||
*
|
*
|
||||||
* @param windowManager the window manager associated with the loaded component
|
* @param windowManager the window manager associated with the loaded component
|
||||||
|
* @param provider the provider that is the parent of the given component; null if this
|
||||||
|
* component is not the child of a component provider
|
||||||
*/
|
*/
|
||||||
public void componentLoaded(DockingWindowManager windowManager);
|
public void componentLoaded(DockingWindowManager windowManager, ComponentProvider provider);
|
||||||
}
|
}
|
||||||
|
|
|
@ -387,7 +387,28 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ActionContext getActionContext(MouseEvent event) {
|
public ActionContext getActionContext(MouseEvent event) {
|
||||||
return new ActionContext(this, getComponent());
|
Component c = getComponent();
|
||||||
|
KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
|
||||||
|
Component focusedComponent = kfm.getFocusOwner();
|
||||||
|
if (focusedComponent != null && SwingUtilities.isDescendingFrom(focusedComponent, c)) {
|
||||||
|
c = focusedComponent;
|
||||||
|
}
|
||||||
|
return createContext(c, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
protected ActionContext createContext() {
|
||||||
|
return new ActionContext(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
protected ActionContext createContext(Object payload) {
|
||||||
|
return new ActionContext(this).setContextObject(payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
protected ActionContext createContext(Component source, Object payload) {
|
||||||
|
return new ActionContext(this, source).setContextObject(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1127,7 +1127,19 @@ public class DialogComponentProvider
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ActionContext getActionContext(MouseEvent event) {
|
public ActionContext getActionContext(MouseEvent event) {
|
||||||
return new ActionContext(null, null);
|
|
||||||
|
Component c = getComponent();
|
||||||
|
KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
|
||||||
|
Component focusedComponent = kfm.getFocusOwner();
|
||||||
|
if (focusedComponent != null && SwingUtilities.isDescendingFrom(focusedComponent, c)) {
|
||||||
|
c = focusedComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event == null) {
|
||||||
|
return new ActionContext(null, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ActionContext(null, c).setSourceObject(event.getSource());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -56,7 +56,7 @@ public class DialogComponentProviderPopupActionManager {
|
||||||
// If the source is null, must set it or we won't have
|
// If the source is null, must set it or we won't have
|
||||||
// any popups shown.
|
// any popups shown.
|
||||||
if (actionContext.getSourceObject() == null) {
|
if (actionContext.getSourceObject() == null) {
|
||||||
actionContext.setSource(e.getSource());
|
actionContext.setSourceObject(e.getSource());
|
||||||
}
|
}
|
||||||
|
|
||||||
MenuHandler popupMenuHandler = new PopupMenuHandler(actionContext);
|
MenuHandler popupMenuHandler = new PopupMenuHandler(actionContext);
|
||||||
|
@ -152,7 +152,7 @@ public class DialogComponentProviderPopupActionManager {
|
||||||
public void processMenuAction(final DockingActionIf action, final ActionEvent event) {
|
public void processMenuAction(final DockingActionIf action, final ActionEvent event) {
|
||||||
|
|
||||||
DockingWindowManager.clearMouseOverHelp();
|
DockingWindowManager.clearMouseOverHelp();
|
||||||
actionContext.setSource(event.getSource());
|
actionContext.setSourceObject(event.getSource());
|
||||||
|
|
||||||
// this gives the UI some time to repaint before executing the action
|
// this gives the UI some time to repaint before executing the action
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
|
|
@ -214,6 +214,11 @@ public class DockingActionProxy
|
||||||
dockingAction.setUnvalidatedKeyBindingData(newKeyBindingData);
|
dockingAction.setUnvalidatedKeyBindingData(newKeyBindingData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
dockingAction.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getHelpInfo() {
|
public String getHelpInfo() {
|
||||||
return dockingAction.getHelpInfo();
|
return dockingAction.getHelpInfo();
|
||||||
|
|
|
@ -62,7 +62,7 @@ public abstract class DockingKeyBindingAction extends AbstractAction {
|
||||||
tool.setStatusInfo("");
|
tool.setStatusInfo("");
|
||||||
ComponentProvider provider = tool.getActiveComponentProvider();
|
ComponentProvider provider = tool.getActiveComponentProvider();
|
||||||
ActionContext context = getLocalContext(provider);
|
ActionContext context = getLocalContext(provider);
|
||||||
context.setSource(e.getSource());
|
context.setSourceObject(e.getSource());
|
||||||
docakbleAction.actionPerformed(context);
|
docakbleAction.actionPerformed(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,9 @@ public interface DockingTool {
|
||||||
public void addComponentProvider(ComponentProvider componentProvider, boolean show);
|
public void addComponentProvider(ComponentProvider componentProvider, boolean show);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the given ComponentProvider from the tool
|
* Removes the given ComponentProvider from the tool. When a provider has been removed
|
||||||
|
* from the tool it is considered disposed and should not be reused.
|
||||||
|
*
|
||||||
* @param componentProvider the provider to remove from the tool
|
* @param componentProvider the provider to remove from the tool
|
||||||
*/
|
*/
|
||||||
public void removeComponentProvider(ComponentProvider componentProvider);
|
public void removeComponentProvider(ComponentProvider componentProvider);
|
||||||
|
@ -125,7 +127,8 @@ public interface DockingTool {
|
||||||
public void addAction(DockingActionIf action);
|
public void addAction(DockingActionIf action);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the given action from the tool
|
* Removes the given action from the tool. When an action is removed from the tool it will
|
||||||
|
* be disposed and should not be reused.
|
||||||
* @param action the action to be removed.
|
* @param action the action to be removed.
|
||||||
*/
|
*/
|
||||||
public void removeAction(DockingActionIf action);
|
public void removeAction(DockingActionIf action);
|
||||||
|
|
|
@ -63,8 +63,13 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
||||||
private static DockingActionIf actionUnderMouse;
|
private static DockingActionIf actionUnderMouse;
|
||||||
private static Object objectUnderMouse;
|
private static Object objectUnderMouse;
|
||||||
|
|
||||||
public static final String TOOL_PREFERENCES_XML_NAME = "PREFERENCES";
|
/**
|
||||||
|
* The owner name for docking windows actions.
|
||||||
|
* <p>Warning: Any action with this owner will get removed every time the 'Window' menu is
|
||||||
|
* rebuilt, with the exception if reserved key bindings.
|
||||||
|
*/
|
||||||
public static final String DOCKING_WINDOWS_OWNER = "DockingWindows";
|
public static final String DOCKING_WINDOWS_OWNER = "DockingWindows";
|
||||||
|
public static final String TOOL_PREFERENCES_XML_NAME = "PREFERENCES";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The helpService field should be set to the appropriate help service provider.
|
* The helpService field should be set to the appropriate help service provider.
|
||||||
|
@ -560,6 +565,25 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the component provider that is the conceptual parent of the given component. More
|
||||||
|
* precisely, this will return the component provider whose
|
||||||
|
* {@link ComponentProvider#getComponent() component} is the parent of the given component.
|
||||||
|
*
|
||||||
|
* @param component the component for which to find a provider
|
||||||
|
* @return the provider; null if the component is not the child of a provider
|
||||||
|
*/
|
||||||
|
private ComponentProvider getComponentProvider(Component component) {
|
||||||
|
Set<ComponentProvider> providers = placeholderManager.getActiveProviders();
|
||||||
|
for (ComponentProvider provider : providers) {
|
||||||
|
JComponent providerComponent = provider.getComponent();
|
||||||
|
if (SwingUtilities.isDescendingFrom(component, providerComponent)) {
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
DockableComponent getDockableComponent(ComponentProvider provider) {
|
DockableComponent getDockableComponent(ComponentProvider provider) {
|
||||||
ComponentPlaceholder placeholder = placeholderManager.getPlaceholder(provider);
|
ComponentPlaceholder placeholder = placeholderManager.getPlaceholder(provider);
|
||||||
return placeholder.getComponent();
|
return placeholder.getComponent();
|
||||||
|
@ -2165,7 +2189,8 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
||||||
component.removeHierarchyListener(this);
|
component.removeHierarchyListener(this);
|
||||||
DockingWindowManager dwm = getInstance(component);
|
DockingWindowManager dwm = getInstance(component);
|
||||||
if (dwm != null) {
|
if (dwm != null) {
|
||||||
listener.componentLoaded(dwm);
|
ComponentProvider provider = dwm.getComponentProvider(component);
|
||||||
|
listener.componentLoaded(dwm, provider);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -408,8 +408,9 @@ class KeyBindingOverrideKeyEventDispatcher implements KeyEventDispatcher {
|
||||||
|
|
||||||
// ...next see if there is a key binding for when the component is the child of the focus
|
// ...next see if there is a key binding for when the component is the child of the focus
|
||||||
// owner
|
// owner
|
||||||
return KeyBindingUtils.getAction(jComponent, keyStroke,
|
action = KeyBindingUtils.getAction(jComponent, keyStroke,
|
||||||
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
|
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
|
||||||
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -63,7 +62,7 @@ public class MenuBarMenuHandler extends MenuHandler {
|
||||||
return; // context is not valid, nothing to do
|
return; // context is not valid, nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
tempContext.setSource(event.getSource());
|
tempContext.setSourceObject(event.getSource());
|
||||||
final ActionContext finalContext = tempContext;
|
final ActionContext finalContext = tempContext;
|
||||||
|
|
||||||
// this gives the UI some time to repaint before executing the action
|
// this gives the UI some time to repaint before executing the action
|
||||||
|
|
|
@ -24,7 +24,6 @@ import java.util.*;
|
||||||
import javax.swing.JPopupMenu;
|
import javax.swing.JPopupMenu;
|
||||||
|
|
||||||
import docking.action.*;
|
import docking.action.*;
|
||||||
import docking.actions.PopupActionProvider;
|
|
||||||
import docking.menu.*;
|
import docking.menu.*;
|
||||||
|
|
||||||
public class PopupActionManager implements PropertyChangeListener {
|
public class PopupActionManager implements PropertyChangeListener {
|
||||||
|
@ -76,7 +75,7 @@ public class PopupActionManager implements PropertyChangeListener {
|
||||||
actionContext = new ActionContext();
|
actionContext = new ActionContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
actionContext.setSource(e.getSource());
|
actionContext.setSourceObject(e.getSource());
|
||||||
actionContext.setMouseEvent(e);
|
actionContext.setMouseEvent(e);
|
||||||
|
|
||||||
MenuHandler popupMenuHandler = new PopupMenuHandler(windowManager, actionContext);
|
MenuHandler popupMenuHandler = new PopupMenuHandler(windowManager, actionContext);
|
||||||
|
@ -145,7 +144,7 @@ public class PopupActionManager implements PropertyChangeListener {
|
||||||
|
|
||||||
Object source = actionContext.getSourceObject();
|
Object source = actionContext.getSourceObject();
|
||||||
|
|
||||||
// this interface is deprecated in favor of the next block
|
// this interface is deprecated in favor the code that calls this method; this will be deleted
|
||||||
if (source instanceof DockingActionProviderIf) {
|
if (source instanceof DockingActionProviderIf) {
|
||||||
DockingActionProviderIf actionProvider = (DockingActionProviderIf) source;
|
DockingActionProviderIf actionProvider = (DockingActionProviderIf) source;
|
||||||
List<DockingActionIf> dockingActions = actionProvider.getDockingActions();
|
List<DockingActionIf> dockingActions = actionProvider.getDockingActions();
|
||||||
|
@ -158,23 +157,6 @@ public class PopupActionManager implements PropertyChangeListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// note: this is temporary; there is only one client that needs this. This will be
|
|
||||||
// removed in a future ticket when that client uses the standard tool action system
|
|
||||||
if (source instanceof PopupActionProvider) {
|
|
||||||
PopupActionProvider actionProvider = (PopupActionProvider) source;
|
|
||||||
DockingTool tool = windowManager.getTool();
|
|
||||||
List<DockingActionIf> dockingActions =
|
|
||||||
actionProvider.getPopupActions(tool, actionContext);
|
|
||||||
for (DockingActionIf action : dockingActions) {
|
|
||||||
MenuData popupMenuData = action.getPopupMenuData();
|
|
||||||
if (popupMenuData != null && action.isValidContext(actionContext) &&
|
|
||||||
action.isAddToPopup(actionContext)) {
|
|
||||||
action.setEnabled(action.isEnabledForContext(actionContext));
|
|
||||||
menuMgr.addAction(action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isRemovingFromPopup(MenuData oldData, MenuData newData) {
|
private boolean isRemovingFromPopup(MenuData oldData, MenuData newData) {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -48,7 +47,7 @@ public class PopupMenuHandler extends MenuHandler {
|
||||||
public void processMenuAction(final DockingActionIf action, final ActionEvent event) {
|
public void processMenuAction(final DockingActionIf action, final ActionEvent event) {
|
||||||
|
|
||||||
DockingWindowManager.clearMouseOverHelp();
|
DockingWindowManager.clearMouseOverHelp();
|
||||||
actionContext.setSource(event.getSource());
|
actionContext.setSourceObject(event.getSource());
|
||||||
|
|
||||||
// this gives the UI some time to repaint before executing the action
|
// this gives the UI some time to repaint before executing the action
|
||||||
SwingUtilities.invokeLater( new Runnable() {
|
SwingUtilities.invokeLater( new Runnable() {
|
||||||
|
|
|
@ -372,9 +372,8 @@ public abstract class DockingAction implements DockingActionIf {
|
||||||
/**
|
/**
|
||||||
* Cleans up any resources used by the action.
|
* Cleans up any resources used by the action.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
// TODO this doesn't seem to be called by the framework. Should't we call this when
|
|
||||||
// an action is removed from the tool??
|
|
||||||
propertyListeners.clear();
|
propertyListeners.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -300,4 +300,9 @@ public interface DockingActionIf extends HelpDescriptor {
|
||||||
* @param newKeyBindingData the KeyBindingData to be used to assign this action to a keybinding
|
* @param newKeyBindingData the KeyBindingData to be used to assign this action to a keybinding
|
||||||
*/
|
*/
|
||||||
public void setUnvalidatedKeyBindingData(KeyBindingData newKeyBindingData);
|
public void setUnvalidatedKeyBindingData(KeyBindingData newKeyBindingData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the action's owner is removed from the tool
|
||||||
|
*/
|
||||||
|
public void dispose();
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,7 +119,7 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
||||||
// Build list of actions which are valid in current context
|
// Build list of actions which are valid in current context
|
||||||
ComponentProvider localProvider = tool.getActiveComponentProvider();
|
ComponentProvider localProvider = tool.getActiveComponentProvider();
|
||||||
ActionContext localContext = getLocalContext(localProvider);
|
ActionContext localContext = getLocalContext(localProvider);
|
||||||
localContext.setSource(event.getSource());
|
localContext.setSourceObject(event.getSource());
|
||||||
|
|
||||||
ActionContext globalContext = tool.getGlobalContext();
|
ActionContext globalContext = tool.getGlobalContext();
|
||||||
List<ExecutableKeyActionAdapter> list = getValidContextActions(localContext, globalContext);
|
List<ExecutableKeyActionAdapter> list = getValidContextActions(localContext, globalContext);
|
||||||
|
|
|
@ -122,7 +122,7 @@ public class ActionAdapter implements Action, PropertyChangeListener {
|
||||||
}
|
}
|
||||||
if (context == null) {
|
if (context == null) {
|
||||||
context = new ActionContext();
|
context = new ActionContext();
|
||||||
context.setSource(e.getSource());
|
context.setSourceObject(e.getSource());
|
||||||
}
|
}
|
||||||
if (dockingAction.isEnabledForContext(context)) {
|
if (dockingAction.isEnabledForContext(context)) {
|
||||||
dockingAction.actionPerformed(context);
|
dockingAction.actionPerformed(context);
|
||||||
|
|
|
@ -92,4 +92,6 @@ public interface DockingToolActions {
|
||||||
*/
|
*/
|
||||||
public Set<DockingActionIf> getAllActions();
|
public Set<DockingActionIf> getAllActions();
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
public boolean containsAction(DockingActionIf action);
|
||||||
}
|
}
|
||||||
|
|
|
@ -284,13 +284,32 @@ public class KeyBindingUtils {
|
||||||
am.put(keyText, action);
|
am.put(keyText, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows the client to clear Java key bindings when the client is creating a docking
|
||||||
|
* action. Without this call, any actions bound to the given component will prevent an
|
||||||
|
* action with the same key binding from firing. This is useful when your
|
||||||
|
* application is using tool-level key bindings that share the same
|
||||||
|
* keystroke as a built-in Java action, such as Ctrl-C for the copy action.
|
||||||
|
*
|
||||||
|
* @param component the component for which to clear the key binding
|
||||||
|
* @param action the action from which to get the key binding
|
||||||
|
*/
|
||||||
|
public static void clearKeyBinding(JComponent component, DockingActionIf action) {
|
||||||
|
KeyStroke keyBinding = action.getKeyBinding();
|
||||||
|
if (keyBinding == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
clearKeyBinding(component, keyBinding);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows clients to clear Java key bindings. This is useful when your
|
* Allows clients to clear Java key bindings. This is useful when your
|
||||||
* application is using tool-level key bindings that share the same
|
* application is using tool-level key bindings that share the same
|
||||||
* keystroke as a built-in Java action, such as Ctrl-C for the copy action.
|
* keystroke as a built-in Java action, such as Ctrl-C for the copy action.
|
||||||
* <p>
|
* <p>
|
||||||
* Note: this method clears focus for the default
|
* Note: this method clears the key binding for the
|
||||||
* ({@link JComponent#WHEN_FOCUSED}) focus condition.
|
* {@link JComponent#WHEN_FOCUSED} and
|
||||||
|
* {@link JComponent#WHEN_ANCESTOR_OF_FOCUSED_COMPONENT} focus conditions.
|
||||||
*
|
*
|
||||||
* @param component the component for which to clear the key binding
|
* @param component the component for which to clear the key binding
|
||||||
* @param keyStroke the keystroke of the binding to be cleared
|
* @param keyStroke the keystroke of the binding to be cleared
|
||||||
|
@ -298,6 +317,7 @@ public class KeyBindingUtils {
|
||||||
*/
|
*/
|
||||||
public static void clearKeyBinding(JComponent component, KeyStroke keyStroke) {
|
public static void clearKeyBinding(JComponent component, KeyStroke keyStroke) {
|
||||||
clearKeyBinding(component, keyStroke, JComponent.WHEN_FOCUSED);
|
clearKeyBinding(component, keyStroke, JComponent.WHEN_FOCUSED);
|
||||||
|
clearKeyBinding(component, keyStroke, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -314,12 +334,9 @@ public class KeyBindingUtils {
|
||||||
public static void clearKeyBinding(JComponent component, KeyStroke keyStroke,
|
public static void clearKeyBinding(JComponent component, KeyStroke keyStroke,
|
||||||
int focusCondition) {
|
int focusCondition) {
|
||||||
InputMap inputMap = component.getInputMap(focusCondition);
|
InputMap inputMap = component.getInputMap(focusCondition);
|
||||||
ActionMap actionMap = component.getActionMap();
|
if (inputMap != null) {
|
||||||
if (inputMap == null || actionMap == null) {
|
inputMap.put(keyStroke, "none");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inputMap.put(keyStroke, "none");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -32,8 +32,7 @@ import docking.*;
|
||||||
import docking.action.*;
|
import docking.action.*;
|
||||||
import docking.tool.util.DockingToolConstants;
|
import docking.tool.util.DockingToolConstants;
|
||||||
import ghidra.framework.options.*;
|
import ghidra.framework.options.*;
|
||||||
import ghidra.util.ReservedKeyBindings;
|
import ghidra.util.*;
|
||||||
import ghidra.util.SystemUtilities;
|
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
import util.CollectionUtils;
|
import util.CollectionUtils;
|
||||||
|
|
||||||
|
@ -187,6 +186,16 @@ public class ToolActions implements DockingToolActions, PropertyChangeListener {
|
||||||
action.removePropertyChangeListener(this);
|
action.removePropertyChangeListener(this);
|
||||||
removeAction(action);
|
removeAction(action);
|
||||||
actionGuiHelper.removeToolAction(action);
|
actionGuiHelper.removeToolAction(action);
|
||||||
|
dispose(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dispose(DockingActionIf action) {
|
||||||
|
try {
|
||||||
|
action.dispose();
|
||||||
|
}
|
||||||
|
catch (Throwable t) {
|
||||||
|
Msg.error(this, "Exception disposing action '" + action.getFullName() + "'", t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -311,6 +320,7 @@ public class ToolActions implements DockingToolActions, PropertyChangeListener {
|
||||||
removeAction(action);
|
removeAction(action);
|
||||||
keyBindingsManager.removeAction(action);
|
keyBindingsManager.removeAction(action);
|
||||||
actionGuiHelper.removeProviderAction(provider, action);
|
actionGuiHelper.removeProviderAction(provider, action);
|
||||||
|
dispose(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -395,6 +405,11 @@ public class ToolActions implements DockingToolActions, PropertyChangeListener {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsAction(DockingActionIf action) {
|
||||||
|
return getActionStorage(action).contains(action);
|
||||||
|
}
|
||||||
|
|
||||||
public Action getAction(KeyStroke ks) {
|
public Action getAction(KeyStroke ks) {
|
||||||
return keyBindingsManager.getDockingKeyAction(ks);
|
return keyBindingsManager.getDockingKeyAction(ks);
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,21 +197,22 @@ class MenuItemManager implements ManagedMenuItem, PropertyChangeListener, Action
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
if (menuHandler != null) {
|
if (menuHandler != null) {
|
||||||
menuHandler.processMenuAction(action, e);
|
menuHandler.processMenuAction(action, e);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
try {
|
try {
|
||||||
ActionContext context = new ActionContext(null, null, e.getSource());
|
ActionContext context = new ActionContext();
|
||||||
if (action.isEnabledForContext(context)) {
|
context.setSourceObject(e.getSource());
|
||||||
if (action instanceof ToggleDockingActionIf) {
|
if (action.isEnabledForContext(context)) {
|
||||||
ToggleDockingActionIf toggleAction = ((ToggleDockingActionIf) action);
|
if (action instanceof ToggleDockingActionIf) {
|
||||||
toggleAction.setSelected(!toggleAction.isSelected());
|
ToggleDockingActionIf toggleAction = ((ToggleDockingActionIf) action);
|
||||||
}
|
toggleAction.setSelected(!toggleAction.isSelected());
|
||||||
action.actionPerformed(context);
|
|
||||||
}
|
}
|
||||||
|
action.actionPerformed(context);
|
||||||
}
|
}
|
||||||
catch (Throwable t) {
|
}
|
||||||
Msg.error(this, "Unexpected Exception: " + t.getMessage(), t);
|
catch (Throwable t) {
|
||||||
}
|
Msg.error(this, "Unexpected Exception: " + t.getMessage(), t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -184,7 +184,7 @@ public class MultipleActionDockingToolbarButton extends EmptyBorderButton {
|
||||||
final DockingActionIf delegateAction = dockingAction;
|
final DockingActionIf delegateAction = dockingAction;
|
||||||
item.addActionListener(e -> {
|
item.addActionListener(e -> {
|
||||||
ActionContext context = getActionContext();
|
ActionContext context = getActionContext();
|
||||||
context.setSource(e.getSource());
|
context.setSourceObject(e.getSource());
|
||||||
if (delegateAction instanceof ToggleDockingAction) {
|
if (delegateAction instanceof ToggleDockingAction) {
|
||||||
ToggleDockingAction toggleAction = (ToggleDockingAction) delegateAction;
|
ToggleDockingAction toggleAction = (ToggleDockingAction) delegateAction;
|
||||||
toggleAction.setSelected(!toggleAction.isSelected());
|
toggleAction.setSelected(!toggleAction.isSelected());
|
||||||
|
|
|
@ -206,7 +206,7 @@ public class ToolBarItemManager implements PropertyChangeListener, ActionListene
|
||||||
else {
|
else {
|
||||||
return; // context is not valid, nothing to do
|
return; // context is not valid, nothing to do
|
||||||
}
|
}
|
||||||
tempContext.setSource(event.getSource());
|
tempContext.setSourceObject(event.getSource());
|
||||||
final ActionContext finalContext = tempContext;
|
final ActionContext finalContext = tempContext;
|
||||||
|
|
||||||
// this gives the UI some time to repaint before executing the action
|
// this gives the UI some time to repaint before executing the action
|
||||||
|
|
|
@ -1326,7 +1326,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
actionContext = newContext;
|
actionContext = newContext;
|
||||||
actionContext.setSource(provider.getComponent());
|
actionContext.setSourceObject(provider.getComponent());
|
||||||
|
|
||||||
return actionContext;
|
return actionContext;
|
||||||
});
|
});
|
||||||
|
@ -1349,7 +1349,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
|
||||||
ActionContext context = runSwing(() -> {
|
ActionContext context = runSwing(() -> {
|
||||||
ActionContext actionContext = provider.getActionContext(null);
|
ActionContext actionContext = provider.getActionContext(null);
|
||||||
if (actionContext != null) {
|
if (actionContext != null) {
|
||||||
actionContext.setSource(provider.getComponent());
|
actionContext.setSourceObject(provider.getComponent());
|
||||||
}
|
}
|
||||||
return actionContext;
|
return actionContext;
|
||||||
});
|
});
|
||||||
|
@ -2188,6 +2188,25 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
|
||||||
return ref.get();
|
return ref.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a generic action context with no provider, with the given payload
|
||||||
|
* @param payload the generic object to put in the context
|
||||||
|
* @return the new context
|
||||||
|
*/
|
||||||
|
public ActionContext createContext(Object payload) {
|
||||||
|
return new ActionContext().setContextObject(payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a generic action context with the given provider, with the given payload
|
||||||
|
* @param provider the provider
|
||||||
|
* @param payload the generic object to put in the context
|
||||||
|
* @return the new context
|
||||||
|
*/
|
||||||
|
public ActionContext createContext(ComponentProvider provider, Object payload) {
|
||||||
|
return new ActionContext(provider).setContextObject(payload);
|
||||||
|
}
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
// Screen Capture
|
// Screen Capture
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
|
@ -579,18 +579,6 @@ public class GhidraFileChooser extends DialogComponentProvider
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActionContext getActionContext(MouseEvent event) {
|
|
||||||
if (event == null) {
|
|
||||||
return super.getActionContext(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ActionContext(null, event.getSource());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.util.filechooser.GhidraFileChooserListener#modelChanged()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void modelChanged() {
|
public void modelChanged() {
|
||||||
SystemUtilities.runSwingLater(() -> {
|
SystemUtilities.runSwingLater(() -> {
|
||||||
directoryListModel.update();
|
directoryListModel.update();
|
||||||
|
@ -598,9 +586,6 @@ public class GhidraFileChooser extends DialogComponentProvider
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see java.io.FileFilter#accept(java.io.File)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean accept(File file) {
|
public boolean accept(File file) {
|
||||||
if (!showDotFiles) {
|
if (!showDotFiles) {
|
||||||
|
|
|
@ -32,7 +32,6 @@ import javax.swing.table.*;
|
||||||
import docking.*;
|
import docking.*;
|
||||||
import docking.action.*;
|
import docking.action.*;
|
||||||
import docking.actions.KeyBindingUtils;
|
import docking.actions.KeyBindingUtils;
|
||||||
import docking.actions.PopupActionProvider;
|
|
||||||
import docking.widgets.OptionDialog;
|
import docking.widgets.OptionDialog;
|
||||||
import docking.widgets.dialogs.SettingsDialog;
|
import docking.widgets.dialogs.SettingsDialog;
|
||||||
import docking.widgets.filechooser.GhidraFileChooser;
|
import docking.widgets.filechooser.GhidraFileChooser;
|
||||||
|
@ -70,12 +69,13 @@ import resources.ResourceManager;
|
||||||
*
|
*
|
||||||
* @see GTableFilterPanel
|
* @see GTableFilterPanel
|
||||||
*/
|
*/
|
||||||
public class GTable extends JTable implements KeyStrokeConsumer, PopupActionProvider {
|
public class GTable extends JTable implements KeyStrokeConsumer {
|
||||||
|
|
||||||
private static final String LAST_EXPORT_FILE = "LAST_EXPORT_DIR";
|
private static final String LAST_EXPORT_FILE = "LAST_EXPORT_DIR";
|
||||||
|
|
||||||
private int userDefinedRowHeight;
|
private int userDefinedRowHeight;
|
||||||
|
|
||||||
|
private boolean isInitialized;
|
||||||
private boolean allowActions;
|
private boolean allowActions;
|
||||||
private KeyListener autoLookupListener;
|
private KeyListener autoLookupListener;
|
||||||
private long lastLookupTime;
|
private long lastLookupTime;
|
||||||
|
@ -96,6 +96,8 @@ public class GTable extends JTable implements KeyStrokeConsumer, PopupActionProv
|
||||||
|
|
||||||
/** A flag to signal that a copy operation is being performed. */
|
/** A flag to signal that a copy operation is being performed. */
|
||||||
private boolean copying;
|
private boolean copying;
|
||||||
|
|
||||||
|
private static final String actionMenuGroup = "zzzTableGroup";
|
||||||
private DockingAction copyAction;
|
private DockingAction copyAction;
|
||||||
private DockingAction copyColumnsAction;
|
private DockingAction copyColumnsAction;
|
||||||
private DockingAction copyCurrentColumnAction;
|
private DockingAction copyCurrentColumnAction;
|
||||||
|
@ -103,8 +105,6 @@ public class GTable extends JTable implements KeyStrokeConsumer, PopupActionProv
|
||||||
private DockingAction exportAction;
|
private DockingAction exportAction;
|
||||||
private DockingAction exportColumnsAction;
|
private DockingAction exportColumnsAction;
|
||||||
|
|
||||||
private String actionMenuGroup = "zzzTableGroup";
|
|
||||||
|
|
||||||
private SelectionManager selectionManager;
|
private SelectionManager selectionManager;
|
||||||
private Integer visibleRowCount;
|
private Integer visibleRowCount;
|
||||||
|
|
||||||
|
@ -510,24 +510,6 @@ public class GTable extends JTable implements KeyStrokeConsumer, PopupActionProv
|
||||||
return autoLookupKeyStrokeConsumer.isKeyConsumed(keyStroke);
|
return autoLookupKeyStrokeConsumer.isKeyConsumed(keyStroke);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<DockingActionIf> getPopupActions(DockingTool tool, ActionContext context) {
|
|
||||||
|
|
||||||
// we want these top-level groups to all appear together, with no separator
|
|
||||||
tool.setMenuGroup(new String[] { "Copy" }, actionMenuGroup, "1");
|
|
||||||
tool.setMenuGroup(new String[] { "Export" }, actionMenuGroup, "2");
|
|
||||||
tool.setMenuGroup(new String[] { "Select All" }, actionMenuGroup, "3");
|
|
||||||
|
|
||||||
List<DockingActionIf> list = new ArrayList<>();
|
|
||||||
list.add(copyAction);
|
|
||||||
list.add(copyCurrentColumnAction);
|
|
||||||
list.add(copyColumnsAction);
|
|
||||||
list.add(selectAllAction);
|
|
||||||
list.add(exportAction);
|
|
||||||
list.add(exportColumnsAction);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init(boolean allowAutoEdit) {
|
private void init(boolean allowAutoEdit) {
|
||||||
ToolTipManager.sharedInstance().unregisterComponent(this);
|
ToolTipManager.sharedInstance().unregisterComponent(this);
|
||||||
ToolTipManager.sharedInstance().registerComponent(this);
|
ToolTipManager.sharedInstance().registerComponent(this);
|
||||||
|
@ -576,8 +558,27 @@ public class GTable extends JTable implements KeyStrokeConsumer, PopupActionProv
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
createPopupActions();
|
// updating the row height requires the 'isInitialized' to be set, so do it first
|
||||||
|
isInitialized = true;
|
||||||
initializeRowHeight();
|
initializeRowHeight();
|
||||||
|
|
||||||
|
DockingWindowManager.registerComponentLoadedListener(this, (dwm, provider) -> {
|
||||||
|
DockingTool tool = dwm.getTool();
|
||||||
|
regiserActions(tool, provider);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void regiserActions(DockingTool tool, ComponentProvider provider) {
|
||||||
|
|
||||||
|
tool.setMenuGroup(new String[] { "Copy" }, actionMenuGroup, "1");
|
||||||
|
tool.setMenuGroup(new String[] { "Export" }, actionMenuGroup, "2");
|
||||||
|
tool.setMenuGroup(new String[] { "Select All" }, actionMenuGroup, "3");
|
||||||
|
|
||||||
|
String owner = getClass().getSimpleName();
|
||||||
|
if (provider != null) {
|
||||||
|
owner = provider.getOwner();
|
||||||
|
}
|
||||||
|
installTableActions(tool, owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeHeader(JTableHeader header) {
|
private void initializeHeader(JTableHeader header) {
|
||||||
|
@ -600,7 +601,8 @@ public class GTable extends JTable implements KeyStrokeConsumer, PopupActionProv
|
||||||
}
|
}
|
||||||
|
|
||||||
private void adjustRowHeight() {
|
private void adjustRowHeight() {
|
||||||
if (copyAction == null) { // crude test to know if our constructor has finished
|
|
||||||
|
if (!isInitialized) {
|
||||||
return; // must be initializing
|
return; // must be initializing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1153,12 +1155,20 @@ public class GTable extends JTable implements KeyStrokeConsumer, PopupActionProv
|
||||||
return converted;
|
return converted;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createPopupActions() {
|
/**
|
||||||
|
* A method that subclasses can override to signal that they wish not to have this table's
|
||||||
|
* built-in popup actions. Subclasses will almost never need to override this method.
|
||||||
|
*
|
||||||
|
* @return true if popup actions are supported
|
||||||
|
*/
|
||||||
|
protected boolean supportsPopupActions() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void installTableActions(DockingTool tool, String owner) {
|
||||||
|
|
||||||
int subGroupIndex = 1; // order by insertion
|
int subGroupIndex = 1; // order by insertion
|
||||||
String owner = getClass().getSimpleName();
|
copyAction = new GTableAction("Table Data Copy", owner) {
|
||||||
owner = "GTable";
|
|
||||||
copyAction = new DockingAction("Table Data Copy", owner, KeyBindingType.SHARED) {
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionContext context) {
|
public void actionPerformed(ActionContext context) {
|
||||||
copying = true;
|
copying = true;
|
||||||
|
@ -1188,26 +1198,24 @@ public class GTable extends JTable implements KeyStrokeConsumer, PopupActionProv
|
||||||
copyAction.setHelpLocation(new HelpLocation("Tables", "Copy"));
|
copyAction.setHelpLocation(new HelpLocation("Tables", "Copy"));
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
|
|
||||||
copyCurrentColumnAction =
|
copyCurrentColumnAction = new GTableAction("Table Data Copy Current Column", owner) {
|
||||||
new DockingAction("Table Data Copy Current Column", owner, KeyBindingType.SHARED) {
|
@Override
|
||||||
@Override
|
public void actionPerformed(ActionContext context) {
|
||||||
public void actionPerformed(ActionContext context) {
|
|
||||||
|
|
||||||
int column = getSelectedColumn();
|
int column = getSelectedColumn();
|
||||||
|
MouseEvent event = context.getMouseEvent();
|
||||||
MouseEvent event = context.getMouseEvent();
|
if (event != null) {
|
||||||
if (event != null) {
|
column = columnAtPoint(event.getPoint());
|
||||||
column = columnAtPoint(event.getPoint());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (column < 0) {
|
|
||||||
Msg.debug(this, "Copy failed--no column selected");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
copyColumns(column);
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
if (column < 0) {
|
||||||
|
Msg.debug(this, "Copy failed--no column selected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
copyColumns(column);
|
||||||
|
}
|
||||||
|
};
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
copyCurrentColumnAction.setPopupMenuData(new MenuData(
|
copyCurrentColumnAction.setPopupMenuData(new MenuData(
|
||||||
new String[] { "Copy",
|
new String[] { "Copy",
|
||||||
|
@ -1226,18 +1234,17 @@ public class GTable extends JTable implements KeyStrokeConsumer, PopupActionProv
|
||||||
copyCurrentColumnAction.setHelpLocation(new HelpLocation("Tables", "Copy_Current_Column"));
|
copyCurrentColumnAction.setHelpLocation(new HelpLocation("Tables", "Copy_Current_Column"));
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
|
|
||||||
copyColumnsAction =
|
copyColumnsAction = new GTableAction("Table Data Copy by Columns", owner) {
|
||||||
new DockingAction("Table Data Copy by Columns", owner, KeyBindingType.SHARED) {
|
@Override
|
||||||
@Override
|
public void actionPerformed(ActionContext context) {
|
||||||
public void actionPerformed(ActionContext context) {
|
int[] userColumns = promptUserForColumns();
|
||||||
int[] userColumns = promptUserForColumns();
|
if (userColumns == null) {
|
||||||
if (userColumns == null) {
|
return; // cancelled
|
||||||
return; // cancelled
|
|
||||||
}
|
|
||||||
|
|
||||||
copyColumns(userColumns);
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
copyColumns(userColumns);
|
||||||
|
}
|
||||||
|
};
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
copyColumnsAction.setPopupMenuData(new MenuData(
|
copyColumnsAction.setPopupMenuData(new MenuData(
|
||||||
new String[] { "Copy", "Copy Columns..." },
|
new String[] { "Copy", "Copy Columns..." },
|
||||||
|
@ -1250,7 +1257,7 @@ public class GTable extends JTable implements KeyStrokeConsumer, PopupActionProv
|
||||||
copyColumnsAction.setHelpLocation(new HelpLocation("Tables", "Copy_Columns"));
|
copyColumnsAction.setHelpLocation(new HelpLocation("Tables", "Copy_Columns"));
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
|
|
||||||
exportAction = new DockingAction("Table Data CSV Export", owner, KeyBindingType.SHARED) {
|
exportAction = new GTableAction("Table Data CSV Export", owner) {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionContext context) {
|
public void actionPerformed(ActionContext context) {
|
||||||
File file = chooseExportFile();
|
File file = chooseExportFile();
|
||||||
|
@ -1271,27 +1278,26 @@ public class GTable extends JTable implements KeyStrokeConsumer, PopupActionProv
|
||||||
exportAction.setHelpLocation(new HelpLocation("Tables", "ExportCSV"));
|
exportAction.setHelpLocation(new HelpLocation("Tables", "ExportCSV"));
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
|
|
||||||
exportColumnsAction =
|
exportColumnsAction = new GTableAction("Table Data CSV Export (by Columns)", owner) {
|
||||||
new DockingAction("Table Data CSV Export (by Columns)", owner, KeyBindingType.SHARED) {
|
@Override
|
||||||
@Override
|
public void actionPerformed(ActionContext context) {
|
||||||
public void actionPerformed(ActionContext context) {
|
int[] userColumns = promptUserForColumns();
|
||||||
int[] userColumns = promptUserForColumns();
|
if (userColumns == null) {
|
||||||
if (userColumns == null) {
|
return; // cancelled
|
||||||
return; // cancelled
|
|
||||||
}
|
|
||||||
|
|
||||||
File file = chooseExportFile();
|
|
||||||
if (file == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Integer> columnList = new ArrayList<>();
|
|
||||||
for (int userColumn : userColumns) {
|
|
||||||
columnList.add(userColumn);
|
|
||||||
}
|
|
||||||
GTableToCSV.writeCSVUsingColunns(file, GTable.this, columnList);
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
File file = chooseExportFile();
|
||||||
|
if (file == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Integer> columnList = new ArrayList<>();
|
||||||
|
for (int userColumn : userColumns) {
|
||||||
|
columnList.add(userColumn);
|
||||||
|
}
|
||||||
|
GTableToCSV.writeCSVUsingColunns(file, GTable.this, columnList);
|
||||||
|
}
|
||||||
|
};
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
exportColumnsAction.setPopupMenuData(new MenuData(
|
exportColumnsAction.setPopupMenuData(new MenuData(
|
||||||
new String[] { "Export", "Export Columns to CSV..." },
|
new String[] { "Export", "Export Columns to CSV..." },
|
||||||
|
@ -1304,7 +1310,7 @@ public class GTable extends JTable implements KeyStrokeConsumer, PopupActionProv
|
||||||
exportColumnsAction.setHelpLocation(new HelpLocation("Tables", "ExportCSV_Columns"));
|
exportColumnsAction.setHelpLocation(new HelpLocation("Tables", "ExportCSV_Columns"));
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
|
|
||||||
selectAllAction = new DockingAction("Table Select All", owner, KeyBindingType.SHARED) {
|
selectAllAction = new GTableAction("Table Select All", owner) {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionContext context) {
|
public void actionPerformed(ActionContext context) {
|
||||||
selectAll();
|
selectAll();
|
||||||
|
@ -1312,6 +1318,9 @@ public class GTable extends JTable implements KeyStrokeConsumer, PopupActionProv
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEnabledForContext(ActionContext context) {
|
public boolean isEnabledForContext(ActionContext context) {
|
||||||
|
if (!super.isEnabledForContext(context)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return getSelectionModel().getSelectionMode() != ListSelectionModel.SINGLE_SELECTION;
|
return getSelectionModel().getSelectionMode() != ListSelectionModel.SINGLE_SELECTION;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1332,9 +1341,20 @@ public class GTable extends JTable implements KeyStrokeConsumer, PopupActionProv
|
||||||
selectAllAction.setHelpLocation(new HelpLocation("Tables", "SelectAll"));
|
selectAllAction.setHelpLocation(new HelpLocation("Tables", "SelectAll"));
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
|
|
||||||
KeyBindingUtils.registerAction(this, copyAction);
|
// remove any conflicting key bindings that Java has installed on this component
|
||||||
KeyBindingUtils.registerAction(this, copyCurrentColumnAction);
|
KeyBindingUtils.clearKeyBinding(this, copyAction);
|
||||||
KeyBindingUtils.registerAction(this, selectAllAction);
|
KeyBindingUtils.clearKeyBinding(this, copyCurrentColumnAction);
|
||||||
|
KeyBindingUtils.clearKeyBinding(this, copyColumnsAction);
|
||||||
|
KeyBindingUtils.clearKeyBinding(this, selectAllAction);
|
||||||
|
KeyBindingUtils.clearKeyBinding(this, exportAction);
|
||||||
|
KeyBindingUtils.clearKeyBinding(this, exportColumnsAction);
|
||||||
|
|
||||||
|
tool.addAction(copyAction);
|
||||||
|
tool.addAction(copyCurrentColumnAction);
|
||||||
|
tool.addAction(copyColumnsAction);
|
||||||
|
tool.addAction(selectAllAction);
|
||||||
|
tool.addAction(exportAction);
|
||||||
|
tool.addAction(exportColumnsAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void copyColumns(int... copyColumns) {
|
private void copyColumns(int... copyColumns) {
|
||||||
|
@ -1478,4 +1498,18 @@ public class GTable extends JTable implements KeyStrokeConsumer, PopupActionProv
|
||||||
// ignored
|
// ignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private abstract class GTableAction extends DockingAction {
|
||||||
|
|
||||||
|
GTableAction(String name, String owner) {
|
||||||
|
super(name, owner, KeyBindingType.SHARED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabledForContext(ActionContext context) {
|
||||||
|
Component sourceComponent = context.getSourceComponent();
|
||||||
|
return sourceComponent == GTable.this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,7 +214,7 @@ public class GTableFilterPanel<ROW_OBJECT> extends JPanel {
|
||||||
table.addPropertyChangeListener(badProgrammingPropertyChangeListener);
|
table.addPropertyChangeListener(badProgrammingPropertyChangeListener);
|
||||||
|
|
||||||
DockingWindowManager.registerComponentLoadedListener(this,
|
DockingWindowManager.registerComponentLoadedListener(this,
|
||||||
windowManager -> initialize(windowManager));
|
(windowManager, provider) -> initialize(windowManager));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initialize(DockingWindowManager windowManager) {
|
private void initialize(DockingWindowManager windowManager) {
|
||||||
|
|
|
@ -106,7 +106,7 @@ public class TableColumnModelState implements SortListener {
|
||||||
// We want to load our state after the column model is loaded. We are using this
|
// 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
|
// listener to know when the table has been added to the component hierarchy, as its
|
||||||
// model has been loaded by then.
|
// model has been loaded by then.
|
||||||
DockingWindowManager.registerComponentLoadedListener(table, windowManager -> {
|
DockingWindowManager.registerComponentLoadedListener(table, (windowManager, provider) -> {
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
setEnabled(true);
|
setEnabled(true);
|
||||||
restoreState();
|
restoreState();
|
||||||
|
|
|
@ -112,7 +112,7 @@ public class GTree extends JPanel implements BusyListener {
|
||||||
init();
|
init();
|
||||||
|
|
||||||
DockingWindowManager.registerComponentLoadedListener(this,
|
DockingWindowManager.registerComponentLoadedListener(this,
|
||||||
windowManager -> filterProvider.loadFilterPreference(windowManager,
|
(windowManager, provider) -> filterProvider.loadFilterPreference(windowManager,
|
||||||
uniquePreferenceKey));
|
uniquePreferenceKey));
|
||||||
|
|
||||||
filterUpdateManager = new SwingUpdateManager(1000, 30000, () -> performNodeFiltering());
|
filterUpdateManager = new SwingUpdateManager(1000, 30000, () -> performNodeFiltering());
|
||||||
|
|
|
@ -18,8 +18,6 @@ package ghidra.util.bean;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.awt.event.MouseEvent;
|
|
||||||
|
|
||||||
import javax.swing.ButtonModel;
|
import javax.swing.ButtonModel;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
@ -44,7 +42,7 @@ public class EmptyBorderButtonTest extends AbstractDockingTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testButtonBorderOnRollover() {
|
public void testButtonBorderOnRollover() {
|
||||||
assertEquals(emptyBorderButton.getBorder(), EmptyBorderButton.NO_BUTTON_BORDER);
|
assertEquals(emptyBorderButton.getBorder(), EmptyBorderButton.NO_BUTTON_BORDER);
|
||||||
|
|
||||||
buttonModel.setRollover(true);
|
buttonModel.setRollover(true);
|
||||||
|
@ -61,7 +59,7 @@ public class EmptyBorderButtonTest extends AbstractDockingTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testButtonBorderOnPress() {
|
public void testButtonBorderOnPress() {
|
||||||
assertEquals(emptyBorderButton.getBorder(), EmptyBorderButton.NO_BUTTON_BORDER);
|
assertEquals(emptyBorderButton.getBorder(), EmptyBorderButton.NO_BUTTON_BORDER);
|
||||||
|
|
||||||
// just pressing the button does not change the border...
|
// just pressing the button does not change the border...
|
||||||
|
@ -82,30 +80,15 @@ public class EmptyBorderButtonTest extends AbstractDockingTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setButtonArmed(final boolean armed) {
|
private void setButtonArmed(final boolean armed) {
|
||||||
runSwing(new Runnable() {
|
runSwing(() -> buttonModel.setArmed(armed));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
buttonModel.setArmed(armed);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setButtonPressed(final boolean pressed) {
|
private void setButtonPressed(final boolean pressed) {
|
||||||
runSwing(new Runnable() {
|
runSwing(() -> buttonModel.setPressed(pressed));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
buttonModel.setPressed(pressed);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setRollover(final boolean isRollover) {
|
private void setRollover(final boolean isRollover) {
|
||||||
runSwing(new Runnable() {
|
runSwing(() -> buttonModel.setRollover(isRollover));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
buttonModel.setRollover(isRollover);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// public void testButtonBorderOnModalDialog() throws InterruptedException {
|
// public void testButtonBorderOnModalDialog() throws InterruptedException {
|
||||||
|
@ -146,7 +129,7 @@ public class EmptyBorderButtonTest extends AbstractDockingTest {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testButtonEnablementFromAction() {
|
public void testButtonEnablementFromAction() {
|
||||||
DockingAction action = new DockingAction("name", "owner") {
|
DockingAction action = new DockingAction("name", "owner") {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionContext context) {
|
public void actionPerformed(ActionContext context) {
|
||||||
|
@ -158,13 +141,8 @@ public class EmptyBorderButtonTest extends AbstractDockingTest {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ActionContextProvider contextProvider = new ActionContextProvider() {
|
ActionContextProvider contextProvider =
|
||||||
|
e -> new ActionContext(null, e.getSource(), e.getComponent());
|
||||||
@Override
|
|
||||||
public ActionContext getActionContext(MouseEvent e) {
|
|
||||||
return new ActionContext(null, null, e.getSource());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
action.setToolBarData(new ToolBarData(ResourceManager.getDefaultIcon()));
|
action.setToolBarData(new ToolBarData(ResourceManager.getDefaultIcon()));
|
||||||
action.setEnabled(false);
|
action.setEnabled(false);
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,6 @@ import java.awt.event.KeyEvent;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import javax.swing.JMenuItem;
|
|
||||||
|
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
import org.jdom.input.SAXBuilder;
|
import org.jdom.input.SAXBuilder;
|
||||||
|
|
||||||
|
@ -511,7 +509,7 @@ class ToolActionManager implements ToolChestChangeListener {
|
||||||
ToolAction runAction = new ToolAction(toolName, "Run_Tool") {
|
ToolAction runAction = new ToolAction(toolName, "Run_Tool") {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionContext context) {
|
public void actionPerformed(ActionContext context) {
|
||||||
String name = ((JMenuItem) context.getSourceObject()).getText();
|
String name = getName();
|
||||||
Workspace ws = plugin.getActiveWorkspace();
|
Workspace ws = plugin.getActiveWorkspace();
|
||||||
ToolChest toolChest = plugin.getActiveProject().getLocalToolChest();
|
ToolChest toolChest = plugin.getActiveProject().getLocalToolChest();
|
||||||
ws.runTool(toolChest.getToolTemplate(name));
|
ws.runTool(toolChest.getToolTemplate(name));
|
||||||
|
@ -529,7 +527,7 @@ class ToolActionManager implements ToolChestChangeListener {
|
||||||
ToolAction deleteAction = new ToolAction(toolName, "Delete_Tool") {
|
ToolAction deleteAction = new ToolAction(toolName, "Delete_Tool") {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionContext context) {
|
public void actionPerformed(ActionContext context) {
|
||||||
String name = ((JMenuItem) context.getSourceObject()).getText();
|
String name = getName();
|
||||||
if (!plugin.confirmDelete(name + " from the project tool chest?")) {
|
if (!plugin.confirmDelete(name + " from the project tool chest?")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -549,7 +547,7 @@ class ToolActionManager implements ToolChestChangeListener {
|
||||||
ToolAction exportAction = new ToolAction(toolName, "Export_Tool") {
|
ToolAction exportAction = new ToolAction(toolName, "Export_Tool") {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionContext context) {
|
public void actionPerformed(ActionContext context) {
|
||||||
String name = ((JMenuItem) context.getSourceObject()).getText();
|
String name = getName();
|
||||||
ToolChest toolChest = plugin.getActiveProject().getLocalToolChest();
|
ToolChest toolChest = plugin.getActiveProject().getLocalToolChest();
|
||||||
plugin.exportToolConfig(toolChest.getToolTemplate(name), "Tool Menu");
|
plugin.exportToolConfig(toolChest.getToolTemplate(name), "Tool Menu");
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ public class ProjectDataActionContext extends ActionContext implements DomainFil
|
||||||
public ProjectDataActionContext(ComponentProvider provider, ProjectData projectData,
|
public ProjectDataActionContext(ComponentProvider provider, ProjectData projectData,
|
||||||
Object contextObject, List<DomainFolder> selectedFolders,
|
Object contextObject, List<DomainFolder> selectedFolders,
|
||||||
List<DomainFile> selectedFiles, Component comp, boolean isActiveProject) {
|
List<DomainFile> selectedFiles, Component comp, boolean isActiveProject) {
|
||||||
super(provider, contextObject);
|
super(provider, contextObject, comp);
|
||||||
this.projectData = projectData;
|
this.projectData = projectData;
|
||||||
this.selectedFolders = selectedFolders;
|
this.selectedFolders = selectedFolders;
|
||||||
this.selectedFiles = selectedFiles;
|
this.selectedFiles = selectedFiles;
|
||||||
|
|
|
@ -25,8 +25,8 @@ import java.util.List;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
import docking.*;
|
import docking.ActionContext;
|
||||||
import docking.action.DockingActionIf;
|
import docking.ComponentProvider;
|
||||||
import docking.help.Help;
|
import docking.help.Help;
|
||||||
import docking.help.HelpService;
|
import docking.help.HelpService;
|
||||||
import docking.widgets.label.GHtmlLabel;
|
import docking.widgets.label.GHtmlLabel;
|
||||||
|
@ -489,12 +489,8 @@ public class ProjectDataTablePanel extends JPanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<DockingActionIf> getPopupActions(DockingTool tool, ActionContext context) {
|
protected boolean supportsPopupActions() {
|
||||||
|
return false;
|
||||||
// TODO we should at least add the 'copy' action
|
|
||||||
|
|
||||||
// the table's default actions aren't that useful in the Front End
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,7 +135,7 @@ public class VersionHistoryDialog extends DialogComponentProvider implements Pro
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActionContext getActionContext(MouseEvent event) {
|
public ActionContext getActionContext(MouseEvent event) {
|
||||||
ActionContext actionContext = new ActionContext(null, versionPanel.getTable(), this);
|
ActionContext actionContext = new ActionContext(null, this, versionPanel.getTable());
|
||||||
actionContext.setMouseEvent(event);
|
actionContext.setMouseEvent(event);
|
||||||
return actionContext;
|
return actionContext;
|
||||||
}
|
}
|
||||||
|
|
|
@ -441,6 +441,8 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool, Se
|
||||||
winMgr.setVisible(false);
|
winMgr.setVisible(false);
|
||||||
eventMgr.clearLastEvents();
|
eventMgr.clearLastEvents();
|
||||||
pluginMgr.dispose();
|
pluginMgr.dispose();
|
||||||
|
|
||||||
|
toolActions.removeActions(ToolConstants.TOOL_OWNER);
|
||||||
toolActions.dispose();
|
toolActions.dispose();
|
||||||
|
|
||||||
if (project != null) {
|
if (project != null) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue