GT-2869 - Shared Key Bindings - removed Dummy Key Binding class

This commit is contained in:
dragonmacher 2019-05-31 16:38:53 -04:00
parent 3705ac3d1f
commit 5a9067832a
69 changed files with 555 additions and 1170 deletions

View file

@ -113,7 +113,6 @@ src/main/help/help/topics/BookmarkPlugin/images/BookmarksFilter.png||GHIDRA||||E
src/main/help/help/topics/BookmarkPlugin/images/MarkerForBookmark.png||GHIDRA||||END|
src/main/help/help/topics/BookmarkPlugin/images/NextSelectionBlock16.gif||GHIDRA||||END|
src/main/help/help/topics/BookmarkPlugin/images/PreviousSelectionBlock16.gif||GHIDRA||||END|
src/main/help/help/topics/BookmarkPlugin/images/text_align_justify.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/help/help/topics/CParserPlugin/CParser.htm||GHIDRA||||END|
src/main/help/help/topics/CParserPlugin/images/ParseCSource.png||GHIDRA||||END|
src/main/help/help/topics/CParserPlugin/images/ParseError.png||GHIDRA||||END|
@ -167,7 +166,6 @@ src/main/help/help/topics/CodeBrowserPlugin/images/hoverOff.gif||GHIDRA||||END|
src/main/help/help/topics/CodeBrowserPlugin/images/hoverOn.gif||GHIDRA||||END|
src/main/help/help/topics/CommentWindowPlugin/comment_window.htm||GHIDRA||||END|
src/main/help/help/topics/CommentWindowPlugin/images/CommentsWindow.png||GHIDRA||||END|
src/main/help/help/topics/CommentWindowPlugin/images/text_align_justify.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/help/help/topics/CommentsPlugin/Comments.htm||GHIDRA||||END|
src/main/help/help/topics/CommentsPlugin/images/Comment.png||GHIDRA||||END|
src/main/help/help/topics/CommentsPlugin/images/ShowCommentHistory.png||GHIDRA||||END|
@ -264,7 +262,6 @@ src/main/help/help/topics/DataTypePreviewPlugin/images/edit-delete.png||Oxygen I
src/main/help/help/topics/DataWindowPlugin/data_window.htm||GHIDRA||||END|
src/main/help/help/topics/DataWindowPlugin/images/DataWindow.png||GHIDRA||||END|
src/main/help/help/topics/DataWindowPlugin/images/DataWindowFilter.png||GHIDRA||||END|
src/main/help/help/topics/DataWindowPlugin/images/text_align_justify.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/help/help/topics/DbViewerPlugin/DbViewer.htm||GHIDRA||reviewed||END|
src/main/help/help/topics/DbViewerPlugin/images/DatabaseViewer.png||GHIDRA||||END|
src/main/help/help/topics/DisassembledViewPlugin/DisassembledViewPlugin.htm||GHIDRA||||END|
@ -404,7 +401,6 @@ src/main/help/help/topics/FunctionTagPlugin/images/InputField.png||GHIDRA||||END
src/main/help/help/topics/FunctionWindowPlugin/function_window.htm||GHIDRA||||END|
src/main/help/help/topics/FunctionWindowPlugin/images/FunctionWindow.png||GHIDRA||||END|
src/main/help/help/topics/FunctionWindowPlugin/images/page_white_c.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/help/help/topics/FunctionWindowPlugin/images/text_align_justify.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/help/help/topics/GhidraScriptMgrPlugin/GhidraScriptMgrPlugin.htm||GHIDRA||||END|
src/main/help/help/topics/GhidraScriptMgrPlugin/ScriptDevelopment.htm||GHIDRA||||END|
src/main/help/help/topics/GhidraScriptMgrPlugin/images/Assign_Key_Binding.png||GHIDRA||||END|
@ -470,7 +466,6 @@ src/main/help/help/topics/LocationReferencesPlugin/images/ReferencesToDialog.png
src/main/help/help/topics/LocationReferencesPlugin/images/XRefLabelReferencesSample.png||GHIDRA||||END|
src/main/help/help/topics/LocationReferencesPlugin/images/go-home.png||Tango Icons - Public Domain|||Tango|END|
src/main/help/help/topics/LocationReferencesPlugin/images/tag_yellow.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/help/help/topics/LocationReferencesPlugin/images/text_align_justify.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/help/help/topics/MemoryMapPlugin/Memory_Map.htm||GHIDRA||||END|
src/main/help/help/topics/MemoryMapPlugin/images/AddMappedBlock.png||GHIDRA||||END|
src/main/help/help/topics/MemoryMapPlugin/images/AddMemoryBlock.png||GHIDRA||||END|
@ -598,7 +593,6 @@ src/main/help/help/topics/ReferencesPlugin/images/erase16.png||GHIDRA||||END|
src/main/help/help/topics/ReferencesPlugin/images/go-home.png||Tango Icons - Public Domain|||Tango|END|
src/main/help/help/topics/ReferencesPlugin/images/locationIn.gif||GHIDRA||||END|
src/main/help/help/topics/ReferencesPlugin/images/locationOut.gif||GHIDRA||||END|
src/main/help/help/topics/ReferencesPlugin/images/text_align_justify.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/help/help/topics/ReferencesPlugin/images/unchecked.png||GHIDRA||||END|
src/main/help/help/topics/RegisterPlugin/Registers.htm||GHIDRA||||END|
src/main/help/help/topics/RegisterPlugin/images/ClearRegisterValues.png||GHIDRA||||END|
@ -609,7 +603,6 @@ src/main/help/help/topics/RegisterPlugin/images/edit-delete.png||Oxygen Icons -
src/main/help/help/topics/RegisterPlugin/images/locationIn.gif||GHIDRA||||END|
src/main/help/help/topics/RegisterPlugin/images/registerGroup.png||GHIDRA||||END|
src/main/help/help/topics/RegisterPlugin/images/registerIcon.png||GHIDRA||||END|
src/main/help/help/topics/RegisterPlugin/images/text_align_justify.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/help/help/topics/RegisterPlugin/images/view-filter.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END|
src/main/help/help/topics/RelocationTablePlugin/images/Relocation_Table.png||GHIDRA||||END|
src/main/help/help/topics/RelocationTablePlugin/relocation_table.htm||GHIDRA||||END|
@ -712,7 +705,6 @@ src/main/help/help/topics/Search/images/page_white_copy.png||FAMFAMFAM Icons - C
src/main/help/help/topics/Search/images/reload.png||Nuvola Icons - LGPL 2.1||||END|
src/main/help/help/topics/Search/images/searchm_obj.gif||GHIDRA||||END|
src/main/help/help/topics/Search/images/table_delete.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/help/help/topics/Search/images/text_align_justify.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/help/help/topics/Search/images/view-filter.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END|
src/main/help/help/topics/SelectBlockPlugin/Select_Block_Help.html||GHIDRA||||END|
src/main/help/help/topics/SelectBlockPlugin/images/Dialog.png||GHIDRA||||END|
@ -749,7 +741,6 @@ src/main/help/help/topics/SymbolTablePlugin/images/edit-delete.png||Oxygen Icons
src/main/help/help/topics/SymbolTablePlugin/images/references_to.gif||GHIDRA||||END|
src/main/help/help/topics/SymbolTablePlugin/images/table.png||FAMFAMFAM Icons - CC 2.5|||silk|END|
src/main/help/help/topics/SymbolTablePlugin/images/table_go.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/help/help/topics/SymbolTablePlugin/images/text_align_justify.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/help/help/topics/SymbolTablePlugin/images/view-filter.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END|
src/main/help/help/topics/SymbolTablePlugin/symbol_references.htm||GHIDRA||||END|
src/main/help/help/topics/SymbolTablePlugin/symbol_table.htm||GHIDRA||||END|
@ -830,7 +821,6 @@ src/main/help/help/topics/VersionControl/images/vcUndoCheckOut.png||GHIDRA||||EN
src/main/help/help/topics/VersionControl/project_repository.htm||GHIDRA||||END|
src/main/help/help/topics/ViewStringsPlugin/ViewStringsPlugin.htm||GHIDRA||||END|
src/main/help/help/topics/ViewStringsPlugin/images/Defined_String_Table.png||GHIDRA||||END|
src/main/help/help/topics/ViewStringsPlugin/images/text_align_justify.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/java/ghidra/app/cmd/comments/package.html||GHIDRA||reviewed||END|
src/main/java/ghidra/app/cmd/data/package.html||GHIDRA||||END|
src/main/java/ghidra/app/cmd/disassemble/package.html||GHIDRA||||END|
@ -1162,7 +1152,6 @@ src/main/resources/images/table_delete.png||FAMFAMFAM Icons - CC 2.5|||famfamfam
src/main/resources/images/table_go.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/resources/images/table_row_delete.png||FAMFAMFAM Icons - CC 2.5|||silk|END|
src/main/resources/images/tag_yellow.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/resources/images/text_align_justify.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/resources/images/text_list_bullets.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/resources/images/text_lowercase.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/resources/images/textfield.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|

View file

@ -305,7 +305,7 @@
<OL>
<LI>Select one or more rows in the Bookmarks table.</LI>
<LI>Click the Select Bookmark Locations <IMG src="images/text_align_justify.png" alt="">
<LI>Click the Select Bookmark Locations <IMG src="Icons.MAKE_SELECTION_ICON" alt="">
button in the local toolbar.</LI>
<LI>The corresponding addresses are selected in the browser.</LI>

View file

@ -42,7 +42,7 @@
"help/topics/Selection/Selecting.htm">select</A> all of the code units in the Code Browser
display corresponding to the selected rows&nbsp; in the table. Since the table allows for
multiple selections, any number of comment items may be selected. To make the selection, either
click on <IMG src="images/text_align_justify.png">, or right mouse click in the table and choose
click on <IMG src="Icons.MAKE_SELECTION_ICON">, or right mouse click in the table and choose
<B>Make Selection</B>.</P>
</BLOCKQUOTE>

View file

@ -36,13 +36,13 @@
<H3><A name="Make_Selection"></A>Make Selection</H3>
<BLOCKQUOTE>
<P><IMG src="images/text_align_justify.png"></P>
<P><IMG src="Icons.MAKE_SELECTION_ICON"></P>
<P>The data window's tool bar has a button that will <A href=
"help/topics/Selection/Selecting.htm">select</A> all of the code units in the Code Browser
display corresponding to the selected rows&nbsp; in the table. Since the table allows for
multiple selections, any number of data items may be selected. To make the selection, either
click on <IMG src="images/text_align_justify.png">, or right mouse click in the table and choose
click on <IMG src="Icons.MAKE_SELECTION_ICON">, or right mouse click in the table and choose
<B>Make Selection</B>.</P>
</BLOCKQUOTE>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 B

View file

@ -30,12 +30,12 @@ function's signature. Click on the top of a column to sort the list by that col
<h3><a name="Make_Selection"></a>Make Selection</h3>
<blockquote>
<p>The Functions window has an icon (<img src="images/text_align_justify.png">)
<p>The Functions window has an icon (<img src="Icons.MAKE_SELECTION_ICON">)
on the tool bar to make a selection in the Code Browser. To make a selection,</p>
<ol>
<li>&nbsp;Select the functions in the <b>Functions</b> window.</li>
<li>Right mouse click and select the <img src="images/text_align_justify.png"> <b>Make
Selection</b> option, OR select the <img src="images/text_align_justify.png">button on
<li>Right mouse click and select the <img src="Icons.MAKE_SELECTION_ICON"> <b>Make
Selection</b> option, OR select the <img src="Icons.MAKE_SELECTION_ICON">button on
the tool bar.</li>
</ol>
</blockquote>

View file

@ -121,7 +121,7 @@
become color filled, as it is here. You may push the button for a refresh in either
state.</P>
<P align="left"><A name="Select"></A>The <IMG alt="" src="images/text_align_justify.png"> button
<P align="left"><A name="Select"></A>The <IMG alt="" src="Icons.MAKE_SELECTION_ICON"> button
will create a selection in the code browser with the reference entries selected in the
table. You may also access this feature by right-clicking an item in the table and
selecting <B>Make Selection</B>.</P>

View file

@ -924,7 +924,7 @@
single reference row is selected.<BR>
</P>
<P><A name="Select_Destinations"></A><IMG src="images/text_align_justify.png" alt=""> <I><B>Select
<P><A name="Select_Destinations"></A><IMG src="Icons.MAKE_SELECTION_ICON" alt=""> <I><B>Select
Memory Reference Destination</B></I> - With one or more memory references selected in the
table, invoking this action will cause the corresponding locations within the&nbsp;<A href=
"help/topics/CodeBrowserPlugin/CodeBrowser.htm">Listing</A> to become selected.<BR>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 B

View file

@ -85,7 +85,7 @@
<P><IMG src="images/edit-delete.png">Deletes the register value associations for all the
selected ranges in the table.</P>
<P><IMG src="images/text_align_justify.png">Creates a selection in the browser for all the address
<P><IMG src="Icons.MAKE_SELECTION_ICON">Creates a selection in the browser for all the address
ranges selected in the register values table.</P>
<P><IMG src="images/view-filter.png">Filters out all registers in the register tree that

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 B

View file

@ -129,7 +129,7 @@
<BLOCKQUOTE>
<H3><A NAME="Make_Selection"></A>Make Selection
<IMG border="0" src="images/text_align_justify.png"></H3>
<IMG border="0" src="Icons.MAKE_SELECTION_ICON"></H3>
<BLOCKQUOTE>
<P>

View file

@ -65,7 +65,7 @@
were found.</P>
</BLOCKQUOTE>
<H3><A name="Make_Selection"></A>Make Selection <IMG border="0" src="images/text_align_justify.png"></H3>
<H3><A name="Make_Selection"></A>Make Selection <IMG border="0" src="Icons.MAKE_SELECTION_ICON"></H3>
<BLOCKQUOTE>
<P>A selection in the Listing can be created from the entries in the results table.
@ -79,7 +79,7 @@
<OL>
<LI>Click in the results table and press <TT><B>Ctrl+A</B></TT>.</LI>
<LI>Click on the <IMG border="0" src="images/text_align_justify.png" > in
<LI>Click on the <IMG border="0" src="Icons.MAKE_SELECTION_ICON" > in
the tool bar, or right mouse click and choose <B>Make Selection</B>.</LI>
<LI>The current selection will be set to the address of each result item.</LI>
@ -93,7 +93,7 @@
<LI>Press and hold the right mouse button over the results table.</LI>
<LI>Click on the <IMG border="0" src="images/text_align_justify.png" > in
<LI>Click on the <IMG border="0" src="Icons.MAKE_SELECTION_ICON" > in
the tool bar, or right mouse click and choose <B>Make Selection</B>.</LI>
<LI>The current selection will be set to the address of all the highlighted items.</LI>

View file

@ -145,7 +145,7 @@
<BLOCKQUOTE>
<H3></A>Make Selection <IMG border="0" src="images/text_align_justify.png"></H3>
<H3></A>Make Selection <IMG border="0" src="Icons.MAKE_SELECTION_ICON"></H3>
<BLOCKQUOTE>
<P>

View file

@ -133,7 +133,7 @@
<BLOCKQUOTE>
<H3></A>Make Selection <IMG border="0" src="images/text_align_justify.png"></H3>
<H3></A>Make Selection <IMG border="0" src="Icons.MAKE_SELECTION_ICON"></H3>
<BLOCKQUOTE>
<P>

View file

@ -206,7 +206,7 @@
results.</P>
</BLOCKQUOTE>
<H3>Make Selection <IMG alt="" border="0" src="images/text_align_justify.png"></H3>
<H3>Make Selection <IMG alt="" border="0" src="Icons.MAKE_SELECTION_ICON"></H3>
<BLOCKQUOTE>
<P><I>See <A href="help/topics/Search/Query_Results_Dialog.htm#Make_Selection">Make

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 B

View file

@ -189,7 +189,7 @@
for more discussion on the use of the edit dialog).
</BLOCKQUOTE>
<H2><A name="Make_Selection"></A>Making a Selection&nbsp;<IMG src="images/text_align_justify.png"></H2>
<H2><A name="Make_Selection"></A>Making a Selection&nbsp;<IMG src="Icons.MAKE_SELECTION_ICON"></H2>
<BLOCKQUOTE>
<P>You can make a selection that corresponds to the symbol addresses that are selected in the
@ -205,7 +205,7 @@
Right-mouse-click and select "Make Selection" from the popup menu.
<UL>
<LI>Or, click the&nbsp;<IMG src="images/text_align_justify.png"> &nbsp;button in the <I>Symbol
<LI>Or, click the&nbsp;<IMG src="Icons.MAKE_SELECTION_ICON"> &nbsp;button in the <I>Symbol
Table</I> toolbar.</LI>
</UL>
</LI>

View file

@ -53,12 +53,12 @@
<blockquote>
<h3><a name="Make_Selection"></a>Make Selection</h3>
<blockquote>
<p>The Defined Strings window has an icon (<img src="images/text_align_justify.png">)
<p>The Defined Strings window has an icon (<img src="Icons.MAKE_SELECTION_ICON">)
on the tool bar to make a selection in the Code Browser. To make a selection,</p>
<ol>
<li>&nbsp;Select the rows containing the desired strings in the table.</li>
<li>Right mouse click and select the <img src="images/text_align_justify.png"> <b>Make
Selection</b> option, OR select the <img src="images/text_align_justify.png">button on
<li>Right mouse click and select the <img src="Icons.MAKE_SELECTION_ICON"> <b>Make
Selection</b> option, OR select the <img src="Icons.MAKE_SELECTION_ICON">button on
the tool bar.</li>
</ol>
</blockquote>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 B

View file

@ -22,6 +22,8 @@ import javax.swing.KeyStroke;
import docking.ActionContext;
import docking.DockingUtils;
import docking.action.DockingAction;
import docking.action.KeyBindingData;
import ghidra.app.plugin.core.navigation.FindAppliedDataTypesService;
import ghidra.app.plugin.core.navigation.locationreferences.ReferenceUtils;
import ghidra.framework.plugintool.PluginTool;
@ -29,11 +31,12 @@ import ghidra.program.model.data.Composite;
import ghidra.program.model.data.DataType;
import ghidra.util.*;
public abstract class AbstractFindReferencesDataTypeAction extends AbstractSharedKeybindingAction {
public abstract class AbstractFindReferencesDataTypeAction extends DockingAction {
public static final String NAME = "Find References To";
public static final KeyStroke DEFAULT_KEY_STROKE = KeyStroke.getKeyStroke(KeyEvent.VK_F,
DockingUtils.CONTROL_KEY_MODIFIER_MASK | InputEvent.SHIFT_DOWN_MASK);
private PluginTool tool;
protected AbstractFindReferencesDataTypeAction(PluginTool tool, String name, String owner) {
this(tool, name, owner, null);
@ -41,10 +44,13 @@ public abstract class AbstractFindReferencesDataTypeAction extends AbstractShare
protected AbstractFindReferencesDataTypeAction(PluginTool tool, String name, String owner,
KeyStroke defaultKeyStroke) {
super(tool, name, owner, defaultKeyStroke);
super(name, owner);
this.tool = tool;
setHelpLocation(new HelpLocation("LocationReferencesPlugin", "Data_Types"));
setDescription("Shows all uses of the selected data type");
initKeyStroke(defaultKeyStroke);
}
protected abstract DataType getDataType(ActionContext context);
@ -55,6 +61,20 @@ public abstract class AbstractFindReferencesDataTypeAction extends AbstractShare
return null;
}
private void initKeyStroke(KeyStroke keyStroke) {
if (keyStroke == null) {
return;
}
// we don't have a default keybinding, so any value implies user-defined
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
@Override
public boolean usesSharedKeyBinding() {
return true;
}
@Override
public boolean isEnabledForContext(ActionContext context) {
DataType dataType = getDataType(context);
@ -80,17 +100,15 @@ public abstract class AbstractFindReferencesDataTypeAction extends AbstractShare
if (field != null && !(baseDataType instanceof Composite)) {
Msg.error(this, "Somehow have a field without a Composite parent--searching " +
"only for the parent type '" + dataType + "'; field '" + field + "'");
SystemUtilities.runSwingLater(
() -> service.findAndDisplayAppliedDataTypeAddresses(dataType));
Swing.runLater(() -> service.findAndDisplayAppliedDataTypeAddresses(dataType));
return;
}
if (field == null) {
SystemUtilities.runSwingLater(
() -> service.findAndDisplayAppliedDataTypeAddresses(dataType));
Swing.runLater(() -> service.findAndDisplayAppliedDataTypeAddresses(dataType));
}
else {
SystemUtilities.runSwingLater(() -> service.findAndDisplayAppliedDataTypeAddresses(
Swing.runLater(() -> service.findAndDisplayAppliedDataTypeAddresses(
(Composite) baseDataType, field));
}
}

View file

@ -1,83 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.actions;
import javax.swing.KeyStroke;
import docking.action.DockingAction;
import docking.action.KeyBindingData;
import ghidra.framework.options.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.ToolConstants;
/**
* An action that can be extended in order to share keybindings.
* <p>
* Any group of actions that wish to share a keybinding must all use the same <tt>name</tt> and
* default <tt>keystroke</tt> value.
* <p>
* As the end-user assigns keybindings, each subclass will update accordingly.
*
* @see DummyKeyBindingsOptionsAction
*/
public abstract class AbstractSharedKeybindingAction extends DockingAction
implements OptionsChangeListener {
protected PluginTool tool;
protected AbstractSharedKeybindingAction(PluginTool tool, String name, String owner,
KeyStroke defaultkeyStroke) {
super(name, owner, false /* not keybinding managed--the dummy handles that */);
this.tool = tool;
DockingAction action = new DummyKeyBindingsOptionsAction(name, defaultkeyStroke);
tool.addAction(action);
// setup options to know when the dummy key binding is changed
ToolOptions options = tool.getOptions(ToolConstants.KEY_BINDINGS);
KeyStroke optionsKeyStroke = options.getKeyStroke(action.getFullName(), defaultkeyStroke);
if (defaultkeyStroke != null) {
if (!defaultkeyStroke.equals(optionsKeyStroke)) {
// user-defined keystroke
setUnvalidatedKeyBindingData(new KeyBindingData(optionsKeyStroke));
}
else {
setKeyBindingData(new KeyBindingData(optionsKeyStroke));
}
}
else {
if (optionsKeyStroke != null) {
// user-defined keystroke
setUnvalidatedKeyBindingData(new KeyBindingData(optionsKeyStroke));
}
}
options.addOptionsChangeListener(this);
}
@Override
public void optionsChanged(ToolOptions options, String name, Object oldValue, Object newValue) {
KeyStroke keyStroke = (KeyStroke) newValue;
String actionName = getName();
if (name.startsWith(actionName)) {
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
}
}

View file

@ -15,28 +15,24 @@
*/
package ghidra.app.plugin.core.commentwindow;
import javax.swing.ImageIcon;
import javax.swing.KeyStroke;
import docking.ActionContext;
import docking.action.*;
import docking.action.DockingAction;
import ghidra.app.CorePluginPackage;
import ghidra.app.events.ProgramSelectionPluginEvent;
import ghidra.app.plugin.PluginCategoryNames;
import ghidra.app.plugin.ProgramPlugin;
import ghidra.app.services.GoToService;
import ghidra.framework.model.*;
import ghidra.framework.options.*;
import ghidra.framework.plugintool.*;
import ghidra.framework.plugintool.util.*;
import ghidra.framework.plugintool.PluginInfo;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.PluginStatus;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.CodeUnit;
import ghidra.program.model.listing.Program;
import ghidra.program.util.*;
import ghidra.util.table.GhidraTable;
import ghidra.util.table.SelectionNavigationAction;
import ghidra.util.table.actions.MakeProgramSelectionAction;
import ghidra.util.task.SwingUpdateManager;
import resources.ResourceManager;
/*
* This plugin shows a filterable Ghidra table containing all the comments in the active program
@ -53,8 +49,7 @@ import resources.ResourceManager;
servicesRequired = { GoToService.class }
)
//@formatter:on
public class CommentWindowPlugin extends ProgramPlugin
implements DomainObjectListener, OptionsChangeListener {
public class CommentWindowPlugin extends ProgramPlugin implements DomainObjectListener {
private DockingAction selectAction;
private CommentWindowProvider provider;
@ -63,12 +58,7 @@ public class CommentWindowPlugin extends ProgramPlugin
public CommentWindowPlugin(PluginTool tool) {
super(tool, true, true);
reloadUpdateMgr = new SwingUpdateManager(1000, 60000, new Runnable() {
@Override
public void run() {
doReload();
}
});
reloadUpdateMgr = new SwingUpdateManager(1000, 60000, () -> doReload());
}
@Override
@ -89,12 +79,6 @@ public class CommentWindowPlugin extends ProgramPlugin
super.dispose();
}
////////////////////////////////////////////////////////////////////////////
//
// Implementation of DomainObjectListener
//
////////////////////////////////////////////////////////////////////////////
private int getCommentType(int type) {
if (type == ChangeManager.DOCR_PRE_COMMENT_CHANGED) {
return CodeUnit.PRE_COMMENT;
@ -169,9 +153,7 @@ public class CommentWindowPlugin extends ProgramPlugin
provider.getComponent().repaint();
}
}
}
}
private void reload() {
@ -198,39 +180,18 @@ public class CommentWindowPlugin extends ProgramPlugin
return currentProgram;
}
// Junit access
CommentWindowProvider getProvider() {
return provider;
}
/**
* Create the action objects for this plugin.
*/
private void createActions() {
selectAction = new DockingAction("Make Selection", getName(), false) {
selectAction = new MakeProgramSelectionAction(getName(), provider.getTable()) {
@Override
public void actionPerformed(ActionContext context) {
protected void makeSelection(ActionContext context) {
selectComment(provider.selectComment());
}
@Override
public boolean isEnabledForContext(ActionContext context) {
if (!(context instanceof CommentWindowContext)) {
return false;
}
CommentWindowContext commentWindowContext = (CommentWindowContext) context;
GhidraTable table = commentWindowContext.getCommentTable();
return table.getSelectedRows().length > 0;
}
};
selectAction.setEnabled(false);
ImageIcon icon = ResourceManager.loadImage("images/text_align_justify.png");
selectAction.setPopupMenuData(new MenuData(new String[] { "Make Selection" }, icon));
selectAction.setDescription("Selects currently selected comment in table");
selectAction.setToolBarData(new ToolBarData(icon));
installDummyAction(selectAction);
tool.addLocalAction(provider, selectAction);
@ -238,34 +199,10 @@ public class CommentWindowPlugin extends ProgramPlugin
tool.addLocalAction(provider, selectionAction);
}
private void installDummyAction(DockingAction action) {
DummyKeyBindingsOptionsAction dummyAction =
new DummyKeyBindingsOptionsAction(action.getName(), null);
tool.addAction(dummyAction);
ToolOptions options = tool.getOptions(ToolConstants.KEY_BINDINGS);
options.addOptionsChangeListener(this);
KeyStroke keyStroke = options.getKeyStroke(dummyAction.getFullName(), null);
if (keyStroke != null) {
action.setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
}
@Override
public void optionsChanged(ToolOptions options, String optionName, Object oldValue,
Object newValue) {
if (optionName.startsWith(selectAction.getName())) {
KeyStroke keyStroke = (KeyStroke) newValue;
selectAction.setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
}
void selectComment(ProgramSelection selection) {
private void selectComment(ProgramSelection selection) {
ProgramSelectionPluginEvent pspe =
new ProgramSelectionPluginEvent("Selection", selection, currentProgram);
firePluginEvent(pspe);
processEvent(pspe);
}
}

View file

@ -18,56 +18,40 @@ package ghidra.app.plugin.core.compositeeditor;
import javax.swing.KeyStroke;
import docking.ActionContext;
import docking.action.DockingAction;
import docking.action.KeyBindingData;
import ghidra.framework.options.*;
import ghidra.framework.plugintool.util.ToolConstants;
import ghidra.program.model.data.CycleGroup;
/**
* Action to apply a data type cycle group.
* For use in the composite data type editor.
* This action has help associated with it.
* Action to apply a data type cycle group. For use in the composite data type editor.
*/
public class CycleGroupAction extends CompositeEditorTableAction implements OptionsChangeListener {
public class CycleGroupAction extends CompositeEditorTableAction {
private final static String GROUP_NAME = CYCLE_ACTION_GROUP;
private CycleGroup cycleGroup;
/**
* Creates an action for applying a data type cycle group.
* @param owner the plugin that owns this action
* @param cycleGroup the data type cycle group
*/
public CycleGroupAction(CompositeEditorProvider provider, CycleGroup cycleGroup) {
super(provider, cycleGroup.getName(), GROUP_NAME,
new String[] { "Cycle", cycleGroup.getName() },
new String[] { "Cycle", cycleGroup.getName() }, null);
this.cycleGroup = cycleGroup;
// register an action that allows users to edit keystrokes
DockingAction action = new DummyKeyBindingsOptionsAction(cycleGroup.getName(),
cycleGroup.getDefaultKeyStroke());
tool.addAction(action);
ToolOptions options = tool.getOptions(ToolConstants.KEY_BINDINGS);
KeyStroke defaultKeyStroke = cycleGroup.getDefaultKeyStroke();
KeyStroke keyStroke = options.getKeyStroke(action.getFullName(), defaultKeyStroke);
options.addOptionsChangeListener(this);
if (!defaultKeyStroke.equals(keyStroke)) {
// user-defined keystroke
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
else {
setKeyBindingData(new KeyBindingData(keyStroke));
}
adjustEnablement();
initKeyStroke(cycleGroup.getDefaultKeyStroke());
}
private void initKeyStroke(KeyStroke keyStroke) {
if (keyStroke == null) {
return;
}
// we don't have a default keybinding, so any value implies user-defined
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
@Override
public boolean usesSharedKeyBinding() {
return true;
}
/**
* Gets the data type cycle group for this action.
*/
public CycleGroup getCycleGroup() {
return cycleGroup;
}
@ -87,12 +71,4 @@ public class CycleGroupAction extends CompositeEditorTableAction implements Opti
public String getHelpName() {
return "Cycle";
}
@Override
public void optionsChanged(ToolOptions options, String name, Object oldValue, Object newValue) {
KeyStroke keyStroke = (KeyStroke) newValue;
if (name.startsWith(cycleGroup.getName())) {
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
}
}

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,11 +15,16 @@
*/
package ghidra.app.plugin.core.data;
import java.awt.event.KeyEvent;
import javax.swing.KeyStroke;
import docking.ActionContext;
import docking.action.DockingAction;
import docking.action.KeyBindingData;
import ghidra.app.context.ListingActionContext;
import ghidra.app.util.datatype.DataTypeSelectionDialog;
import ghidra.framework.options.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.ToolConstants;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRange;
import ghidra.program.model.data.*;
@ -29,18 +33,10 @@ import ghidra.program.util.*;
import ghidra.util.SystemUtilities;
import ghidra.util.data.DataTypeParser.AllowedDataTypes;
import java.awt.event.KeyEvent;
import javax.swing.KeyStroke;
import docking.ActionContext;
import docking.action.DockingAction;
import docking.action.KeyBindingData;
/**
* An action that allows the user to change or select a data type.
*/
public class ChooseDataTypeAction extends DockingAction implements OptionsChangeListener {
public class ChooseDataTypeAction extends DockingAction {
private DataPlugin plugin;
private static final KeyStroke KEY_BINDING = KeyStroke.getKeyStroke(KeyEvent.VK_T, 0);
@ -48,34 +44,23 @@ public class ChooseDataTypeAction extends DockingAction implements OptionsChange
public ChooseDataTypeAction(DataPlugin plugin) {
super(ACTION_NAME, plugin.getName(), false);
this.plugin = plugin;
PluginTool tool = plugin.getTool();
DockingAction action = new DummyKeyBindingsOptionsAction(ACTION_NAME, KEY_BINDING);
tool.addAction(action);
initKeyStroke(KEY_BINDING);
}
// setup options to know when the dummy key binding is changed
ToolOptions options = tool.getOptions(ToolConstants.KEY_BINDINGS);
KeyStroke keyStroke = options.getKeyStroke(action.getFullName(), KEY_BINDING);
if (!KEY_BINDING.equals(keyStroke)) {
// user-defined keystroke
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
else {
setKeyBindingData(new KeyBindingData(keyStroke));
private void initKeyStroke(KeyStroke keyStroke) {
if (keyStroke == null) {
return;
}
options.addOptionsChangeListener(this);
// we don't have a default keybinding, so any value implies user-defined
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
@Override
public void optionsChanged(ToolOptions options, String name, Object oldValue, Object newValue) {
KeyStroke keyStroke = (KeyStroke) newValue;
if (name.startsWith(ACTION_NAME)) {
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
public boolean usesSharedKeyBinding() {
return true;
}
@Override
@ -191,9 +176,8 @@ public class ChooseDataTypeAction extends DockingAction implements OptionsChange
int defaultPointerSize) {
PluginTool tool = plugin.getTool();
Data data = plugin.getDataUnit(context);
DataTypeSelectionDialog selectionDialog =
new DataTypeSelectionDialog(tool, data.getProgram().getDataTypeManager(), maxElements,
AllowedDataTypes.ALL);
DataTypeSelectionDialog selectionDialog = new DataTypeSelectionDialog(tool,
data.getProgram().getDataTypeManager(), maxElements, AllowedDataTypes.ALL);
DataType currentDataType = data.getBaseDataType();
selectionDialog.setInitialDataType(currentDataType);
tool.showDialog(selectionDialog);

View file

@ -27,16 +27,14 @@ import ghidra.app.cmd.data.CreateArrayCmd;
import ghidra.app.cmd.data.CreateArrayInStructureCmd;
import ghidra.app.context.ListingActionContext;
import ghidra.framework.cmd.Command;
import ghidra.framework.options.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.ToolConstants;
import ghidra.program.model.address.*;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.*;
import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.util.*;
class CreateArrayAction extends DockingAction implements OptionsChangeListener {
class CreateArrayAction extends DockingAction {
private static final KeyStroke DEFAULT_KEY_STROKE =
KeyStroke.getKeyStroke(KeyEvent.VK_OPEN_BRACKET, 0);
@ -51,26 +49,22 @@ class CreateArrayAction extends DockingAction implements OptionsChangeListener {
setPopupMenuData(new MenuData(CREATE_ARRAY_POPUP_MENU, "BasicData"));
setEnabled(true);
initializeKeybinding();
initKeyStroke(DEFAULT_KEY_STROKE);
}
private void initializeKeybinding() {
PluginTool tool = plugin.getTool();
DockingAction dummyKeybindingsAction =
new DummyKeyBindingsOptionsAction(getName(), DEFAULT_KEY_STROKE);
tool.addAction(dummyKeybindingsAction);
ToolOptions options = tool.getOptions(ToolConstants.KEY_BINDINGS);
options.addOptionsChangeListener(this);
KeyStroke keyStroke =
options.getKeyStroke(dummyKeybindingsAction.getFullName(), DEFAULT_KEY_STROKE);
private void initKeyStroke(KeyStroke keyStroke) {
if (keyStroke == null) {
return;
}
if (!DEFAULT_KEY_STROKE.equals(keyStroke)) {
// user-defined keystroke
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
else {
setKeyBindingData(new KeyBindingData(keyStroke));
}
// we don't have a default keybinding, so any value implies user-defined
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
@Override
public boolean usesSharedKeyBinding() {
return true;
}
@Override
@ -342,12 +336,4 @@ class CreateArrayAction extends DockingAction implements OptionsChangeListener {
return false;
}
@Override
public void optionsChanged(ToolOptions options, String optionName, Object oldValue,
Object newValue) {
KeyStroke keyStroke = (KeyStroke) newValue;
if (optionName.startsWith(getName())) {
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
}
}

View file

@ -18,13 +18,11 @@ package ghidra.app.plugin.core.data;
import javax.swing.KeyStroke;
import docking.ActionContext;
import docking.action.*;
import docking.action.DockingAction;
import docking.action.KeyBindingData;
import ghidra.app.cmd.data.*;
import ghidra.app.context.ListingActionContext;
import ghidra.framework.cmd.BackgroundCommand;
import ghidra.framework.options.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.ToolConstants;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.CycleGroup;
import ghidra.program.model.data.DataType;
@ -37,48 +35,33 @@ import ghidra.util.Msg;
* <code>CycleGroupAction</code> cycles data through a series of data types
* defined by a <code>CycleGroup</code>.
*/
public class CycleGroupAction extends DockingAction implements OptionsChangeListener {
public class CycleGroupAction extends DockingAction {
private DataPlugin plugin;
private CycleGroup cycleGroup;
/**
* Creates a new instance of the action.
*
* @param plugin Data Plugin instance
*/
CycleGroupAction(CycleGroup group, DataPlugin plugin) {
super(group.getName(), plugin.getName(), false);
this.plugin = plugin;
this.cycleGroup = group;
// register an action that allows users to edit keystrokes
PluginTool tool = plugin.getTool();
DockingAction action = new DummyKeyBindingsOptionsAction(cycleGroup.getName(),
cycleGroup.getDefaultKeyStroke());
tool.addAction(action);
ToolOptions options = tool.getOptions(ToolConstants.KEY_BINDINGS);
KeyStroke defaultKeyStroke = cycleGroup.getDefaultKeyStroke();
KeyStroke keyStroke = options.getKeyStroke(action.getFullName(), defaultKeyStroke);
options.addOptionsChangeListener(this);
setPopupMenuData(
new MenuData(new String[] { "Data", "Cycle", group.getName() }, null, null));
if (!defaultKeyStroke.equals(keyStroke)) {
// user-defined keystroke
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
else {
setKeyBindingData(new KeyBindingData(keyStroke));
}
setEnabled(true);
initKeyStroke(cycleGroup.getDefaultKeyStroke());
}
private void initKeyStroke(KeyStroke keyStroke) {
if (keyStroke == null) {
return;
}
// we don't have a default keybinding, so any value implies user-defined
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
@Override
public boolean usesSharedKeyBinding() {
return true;
}
/**
* @see ghidra.framework.plugintool.DockingAction#dispose()
*/
@Override
public void dispose() {
cycleGroup = null;
@ -86,9 +69,6 @@ public class CycleGroupAction extends DockingAction implements OptionsChangeList
super.dispose();
}
/*
* @see docking.DockableAction#isValidContext(java.lang.Object)
*/
@Override
public boolean isEnabledForContext(ActionContext context) {
Object contextObject = context.getContextObject();
@ -192,12 +172,4 @@ public class CycleGroupAction extends DockingAction implements OptionsChangeList
}
}
}
@Override
public void optionsChanged(ToolOptions options, String name, Object oldValue, Object newValue) {
KeyStroke keyStroke = (KeyStroke) newValue;
if (name.startsWith(cycleGroup.getName())) {
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
}
}

View file

@ -15,13 +15,9 @@
*/
package ghidra.app.plugin.core.datamgr.actions;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import javax.swing.tree.TreePath;
import docking.ActionContext;
import docking.action.KeyBindingData;
import docking.action.MenuData;
import docking.widgets.tree.GTree;
import docking.widgets.tree.GTreeNode;
@ -38,8 +34,6 @@ public class FindReferencesToDataTypeAction extends AbstractFindReferencesDataTy
String menuGroup = "ZVeryLast"; // it's own group; on the bottom
setPopupMenuData(new MenuData(new String[] { "Find Uses of" }, null, menuGroup));
setKeyBindingData(new KeyBindingData(KeyEvent.VK_F,
InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK));
}
@Override

View file

@ -18,11 +18,8 @@ package ghidra.app.plugin.core.datawindow;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.ImageIcon;
import javax.swing.KeyStroke;
import docking.ActionContext;
import docking.action.*;
import docking.action.DockingAction;
import ghidra.app.CorePluginPackage;
import ghidra.app.events.ProgramSelectionPluginEvent;
import ghidra.app.events.ViewChangedPluginEvent;
@ -31,10 +28,9 @@ import ghidra.app.plugin.ProgramPlugin;
import ghidra.app.services.GoToService;
import ghidra.app.services.ProgramTreeService;
import ghidra.framework.model.*;
import ghidra.framework.options.*;
import ghidra.framework.options.SaveState;
import ghidra.framework.plugintool.*;
import ghidra.framework.plugintool.util.PluginStatus;
import ghidra.framework.plugintool.util.ToolConstants;
import ghidra.program.model.address.AddressRangeIterator;
import ghidra.program.model.address.AddressSet;
import ghidra.program.model.data.DataType;
@ -42,10 +38,9 @@ import ghidra.program.model.data.DataTypeManager;
import ghidra.program.model.listing.Data;
import ghidra.program.model.listing.Program;
import ghidra.program.util.*;
import ghidra.util.table.GhidraTable;
import ghidra.util.table.SelectionNavigationAction;
import ghidra.util.table.actions.MakeProgramSelectionAction;
import ghidra.util.task.SwingUpdateManager;
import resources.ResourceManager;
//@formatter:off
@PluginInfo(
@ -60,10 +55,7 @@ import resources.ResourceManager;
eventsConsumed = { ViewChangedPluginEvent.class }
)
//@formatter:on
public class DataWindowPlugin extends ProgramPlugin
implements DomainObjectListener, OptionsChangeListener {
// private final static String[] DISPLAY_MENU_PATH = { ToolConstants.MENU_VIEW, "Defined Data..." };
public class DataWindowPlugin extends ProgramPlugin implements DomainObjectListener {
private DockingAction selectAction;
private FilterAction filterAction;
@ -73,24 +65,12 @@ public class DataWindowPlugin extends ProgramPlugin
private SwingUpdateManager reloadUpdateMgr;
private boolean resetTypesNeeded;
///////////////////////////////////////////////////////////
public DataWindowPlugin(PluginTool tool) {
super(tool, true, true);
resetUpdateMgr = new SwingUpdateManager(100, 60000, new Runnable() {
@Override
public void run() {
doReset();
}
});
resetUpdateMgr = new SwingUpdateManager(100, 60000, () -> doReset());
reloadUpdateMgr = new SwingUpdateManager(100, 60000, new Runnable() {
@Override
public void run() {
doReload();
}
});
reloadUpdateMgr = new SwingUpdateManager(100, 60000, () -> doReload());
}
@Override
@ -112,12 +92,6 @@ public class DataWindowPlugin extends ProgramPlugin
super.dispose();
}
////////////////////////////////////////////////////////////////////////////
//
// Implementation of DomainObjectListener
//
////////////////////////////////////////////////////////////////////////////
@Override
public void domainObjectChanged(DomainObjectChangedEvent ev) {
if (ev.containsEvent(DomainObject.DO_OBJECT_RESTORED)) {
@ -153,8 +127,6 @@ public class DataWindowPlugin extends ProgramPlugin
}
}
////////////////////////////////////////////////////////////////////////////
void reload() {
reloadUpdateMgr.update();
}
@ -163,9 +135,6 @@ public class DataWindowPlugin extends ProgramPlugin
provider.reload();
}
/* (non-Javadoc)
* @see ghidra.framework.plugintool.Plugin#processEvent(ghidra.framework.plugintool.PluginEvent)
*/
@Override
public void processEvent(PluginEvent event) {
if (event instanceof ViewChangedPluginEvent) {
@ -193,8 +162,6 @@ public class DataWindowPlugin extends ProgramPlugin
filterAction.programClosed();
}
////////////////////////////////////////////////////////////////////////////
Program getProgram() {
return currentProgram;
}
@ -208,36 +175,17 @@ public class DataWindowPlugin extends ProgramPlugin
return provider;
}
////////////////////////////////////////////////////////////////////////////
/**
* Create the action objects for this plugin.
*/
private void createActions() {
selectAction = new DockingAction("Make Selection", getName(), false) {
selectAction = new MakeProgramSelectionAction(getName(), provider.getTable()) {
@Override
public void actionPerformed(ActionContext context) {
protected void makeSelection(ActionContext context) {
selectData(provider.selectData());
}
@Override
public boolean isEnabledForContext(ActionContext context) {
if (!(context instanceof DataWindowContext)) {
return false;
}
DataWindowContext dataWindowContext = (DataWindowContext) context;
GhidraTable table = dataWindowContext.getDataTable();
return table.getSelectedRows().length > 0;
}
};
selectAction.setEnabled(false);
ImageIcon icon = ResourceManager.loadImage("images/text_align_justify.png");
selectAction.setPopupMenuData(new MenuData(new String[] { "Make Selection" }, icon));
selectAction.setDescription("Selects currently selected data in table");
selectAction.setToolBarData(new ToolBarData(icon));
installDummyAction(selectAction);
tool.addLocalAction(provider, selectAction);
@ -249,28 +197,6 @@ public class DataWindowPlugin extends ProgramPlugin
tool.addLocalAction(provider, selectionAction);
}
private void installDummyAction(DockingAction action) {
DummyKeyBindingsOptionsAction dummyAction =
new DummyKeyBindingsOptionsAction(action.getName(), null);
tool.addAction(dummyAction);
ToolOptions options = tool.getOptions(ToolConstants.KEY_BINDINGS);
options.addOptionsChangeListener(this);
KeyStroke keyStroke = options.getKeyStroke(dummyAction.getFullName(), null);
if (keyStroke != null) {
action.setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
}
@Override
public void optionsChanged(ToolOptions options, String optionName, Object oldValue, Object newValue) {
if (optionName.startsWith(selectAction.getName())) {
KeyStroke keyStroke = (KeyStroke) newValue;
selectAction.setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
}
void selectData(ProgramSelection selection) {
ProgramSelectionPluginEvent pspe =
new ProgramSelectionPluginEvent("Selection", selection, currentProgram);

View file

@ -23,9 +23,7 @@ import docking.ActionContext;
import docking.action.*;
import ghidra.app.context.ListingActionContext;
import ghidra.app.util.datatype.DataTypeSelectionDialog;
import ghidra.framework.options.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.ToolConstants;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.DataTypeManager;
import ghidra.program.model.listing.*;
@ -36,7 +34,7 @@ import ghidra.util.data.DataTypeParser.AllowedDataTypes;
/**
* An action that allows the user to change or select a data type.
*/
public class ChooseDataTypeAction extends DockingAction implements OptionsChangeListener {
public class ChooseDataTypeAction extends DockingAction {
private static final KeyStroke KEY_BINDING = KeyStroke.getKeyStroke(KeyEvent.VK_T, 0);
private final static String ACTION_NAME = "Choose Data Type";
@ -44,37 +42,25 @@ public class ChooseDataTypeAction extends DockingAction implements OptionsChange
public ChooseDataTypeAction(FunctionPlugin plugin) {
super(ACTION_NAME, plugin.getName(), false);
this.plugin = plugin;
// setup key binding management
PluginTool tool = plugin.getTool();
DockingAction action = new DummyKeyBindingsOptionsAction(ACTION_NAME, KEY_BINDING);
tool.addAction(action);
// setup options to know when the dummy key binding is changed
ToolOptions options = tool.getOptions(ToolConstants.KEY_BINDINGS);
KeyStroke keyStroke = options.getKeyStroke(action.getFullName(), KEY_BINDING);
setPopupMenu(plugin.getDataActionMenuName(null), true);
if (!KEY_BINDING.equals(keyStroke)) {
// user-defined keystroke
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
else {
setKeyBindingData(new KeyBindingData(keyStroke));
}
options.addOptionsChangeListener(this);
setHelpLocation(new HelpLocation("DataTypeEditors", "DataTypeSelectionDialog"));
initKeyStroke(KEY_BINDING);
}
private void initKeyStroke(KeyStroke keyStroke) {
if (keyStroke == null) {
return;
}
// we don't have a default keybinding, so any value implies user-defined
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
@Override
public void optionsChanged(ToolOptions options, String name, Object oldValue, Object newValue) {
KeyStroke keyStroke = (KeyStroke) newValue;
if (name.startsWith(ACTION_NAME)) {
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
public boolean usesSharedKeyBinding() {
return true;
}
@Override

View file

@ -19,20 +19,18 @@ import java.awt.event.KeyEvent;
import javax.swing.KeyStroke;
import docking.action.*;
import docking.action.KeyBindingData;
import docking.action.MenuData;
import docking.widgets.dialogs.NumberInputDialog;
import ghidra.app.context.ListingActionContext;
import ghidra.app.context.ListingContextAction;
import ghidra.framework.options.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.ToolConstants;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.Variable;
import ghidra.program.util.*;
import ghidra.util.HelpLocation;
class CreateArrayAction extends ListingContextAction implements OptionsChangeListener {
class CreateArrayAction extends ListingContextAction {
private static final KeyStroke DEFAULT_KEY_STROKE =
KeyStroke.getKeyStroke(KeyEvent.VK_OPEN_BRACKET, 0);
@ -44,26 +42,22 @@ class CreateArrayAction extends ListingContextAction implements OptionsChangeLis
setPopupMenu(plugin.getDataActionMenuName(null));
setHelpLocation(new HelpLocation(plugin.getName(), "DataType"));
initializeKeybinding();
initKeyStroke(DEFAULT_KEY_STROKE);
}
private void initializeKeybinding() {
PluginTool tool = plugin.getTool();
DockingAction dummyKeybindingsAction =
new DummyKeyBindingsOptionsAction(getName(), DEFAULT_KEY_STROKE);
tool.addAction(dummyKeybindingsAction);
ToolOptions options = tool.getOptions(ToolConstants.KEY_BINDINGS);
options.addOptionsChangeListener(this);
KeyStroke keyStroke =
options.getKeyStroke(dummyKeybindingsAction.getFullName(), DEFAULT_KEY_STROKE);
private void initKeyStroke(KeyStroke keyStroke) {
if (keyStroke == null) {
return;
}
if (!DEFAULT_KEY_STROKE.equals(keyStroke)) {
// user-defined keystroke
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
else {
setKeyBindingData(new KeyBindingData(keyStroke));
}
// we don't have a default keybinding, so any value implies user-defined
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
@Override
public boolean usesSharedKeyBinding() {
return true;
}
private void setPopupMenu(String name) {
@ -141,13 +135,4 @@ class CreateArrayAction extends ListingContextAction implements OptionsChangeLis
return dialog.getValue();
}
@Override
public void optionsChanged(ToolOptions options, String optionName, Object oldValue,
Object newValue) {
KeyStroke keyStroke = (KeyStroke) newValue;
if (optionName.startsWith(getName())) {
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
}
}

View file

@ -17,13 +17,11 @@ package ghidra.app.plugin.core.function;
import javax.swing.KeyStroke;
import docking.action.*;
import docking.action.KeyBindingData;
import docking.action.MenuData;
import ghidra.app.context.ListingActionContext;
import ghidra.app.context.ListingContextAction;
import ghidra.app.util.HelpTopics;
import ghidra.framework.options.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.ToolConstants;
import ghidra.program.model.data.CycleGroup;
import ghidra.program.model.data.DataType;
import ghidra.program.util.ProgramLocation;
@ -34,42 +32,34 @@ import ghidra.util.HelpLocation;
* <code>CycleGroupAction</code> cycles data through a series
* of data types defined by a <code>CycleGroup</code>.
*/
public class CycleGroupAction extends ListingContextAction implements OptionsChangeListener {
public class CycleGroupAction extends ListingContextAction {
private FunctionPlugin plugin;
private CycleGroup cycleGroup;
/**
* Creates a new instance of the action.
*
* @param plugin Data Plugin instance
*/
CycleGroupAction(CycleGroup group, FunctionPlugin plugin) {
super(group.getName(), plugin.getName(), false);
this.plugin = plugin;
this.cycleGroup = group;
setPopupMenu(plugin.getDataActionMenuName(null), true);
// register an action that allows users to edit keystrokes
PluginTool tool = plugin.getTool();
DockingAction action = new DummyKeyBindingsOptionsAction(cycleGroup.getName(),
cycleGroup.getDefaultKeyStroke());
tool.addAction(action);
ToolOptions options = tool.getOptions(ToolConstants.KEY_BINDINGS);
KeyStroke defaultKeyStroke = cycleGroup.getDefaultKeyStroke();
KeyStroke keyStroke = options.getKeyStroke(action.getFullName(), defaultKeyStroke);
if (!defaultKeyStroke.equals(keyStroke)) {
// user-defined keystroke
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
else {
setKeyBindingData(new KeyBindingData(keyStroke));
}
options.addOptionsChangeListener(this);
setHelpLocation(new HelpLocation(HelpTopics.DATA, group.getName()));
initKeyStroke(cycleGroup.getDefaultKeyStroke());
}
private void initKeyStroke(KeyStroke keyStroke) {
if (keyStroke == null) {
return;
}
// we don't have a default keybinding, so any value implies user-defined
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
@Override
public boolean usesSharedKeyBinding() {
return true;
}
private void setPopupMenu(String name, boolean isSignatureAction) {
@ -95,9 +85,6 @@ public class CycleGroupAction extends ListingContextAction implements OptionsCha
return false;
}
/**
* @see ghidra.framework.plugintool.DockingAction#dispose()
*/
@Override
public void dispose() {
cycleGroup = null;
@ -115,12 +102,4 @@ public class CycleGroupAction extends ListingContextAction implements OptionsCha
}
}
}
@Override
public void optionsChanged(ToolOptions options, String name, Object oldValue, Object newValue) {
KeyStroke keyStroke = (KeyStroke) newValue;
if (name.startsWith(cycleGroup.getName())) {
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
}
}

View file

@ -15,13 +15,9 @@
*/
package ghidra.app.plugin.core.functioncompare;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import docking.ActionContext;
import docking.DockingUtils;
import docking.action.KeyBindingData;
import docking.action.MenuData;
import ghidra.app.context.*;
import ghidra.program.model.listing.*;
@ -52,12 +48,6 @@ public class CompareFunctionsAction extends ProgramContextAction {
FunctionComparisonPlugin.FUNCTION_MENU_SUBGROUP, MenuData.NO_MNEMONIC,
"Z_End" /* See the FunctionPlugin for this value */));
// TODO this binding needs to be revisited; probably needs to be more modified, like
// Ctrl-Shift-F; it currently interferes with other uses of Ctrl-F, usually when
// performing a find function.
setKeyBindingData(new KeyBindingData(KeyEvent.VK_F,
DockingUtils.CONTROL_KEY_MODIFIER_MASK | InputEvent.SHIFT_DOWN_MASK));
setHelpLocation(new HelpLocation("FunctionComparison", "Compare_Selected_Functions"));
}

View file

@ -18,7 +18,6 @@ package ghidra.app.plugin.core.functionwindow;
import java.util.List;
import javax.swing.ImageIcon;
import javax.swing.KeyStroke;
import docking.ActionContext;
import docking.action.*;
@ -30,11 +29,9 @@ import ghidra.app.plugin.ProgramPlugin;
import ghidra.app.plugin.core.functioncompare.FunctionComparisonProvider;
import ghidra.app.plugin.core.functioncompare.FunctionComparisonProviderManager;
import ghidra.framework.model.*;
import ghidra.framework.options.*;
import ghidra.framework.plugintool.PluginInfo;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.PluginStatus;
import ghidra.framework.plugintool.util.ToolConstants;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.Symbol;
@ -42,6 +39,7 @@ import ghidra.program.util.*;
import ghidra.util.Msg;
import ghidra.util.table.GhidraTable;
import ghidra.util.table.SelectionNavigationAction;
import ghidra.util.table.actions.MakeProgramSelectionAction;
import ghidra.util.task.SwingUpdateManager;
import resources.ResourceManager;
@ -55,8 +53,7 @@ import resources.ResourceManager;
eventsConsumed = { ProgramClosedPluginEvent.class }
)
//@formatter:on
public class FunctionWindowPlugin extends ProgramPlugin
implements DomainObjectListener, OptionsChangeListener {
public class FunctionWindowPlugin extends ProgramPlugin implements DomainObjectListener {
private DockingAction selectAction;
private DockingAction compareAction;
@ -64,19 +61,12 @@ public class FunctionWindowPlugin extends ProgramPlugin
private SwingUpdateManager swingMgr;
private FunctionComparisonProviderManager functionComparisonManager;
///////////////////////////////////////////////////////////
public FunctionWindowPlugin(PluginTool tool) {
super(tool, true, false);
functionComparisonManager = new FunctionComparisonProviderManager(this);
swingMgr = new SwingUpdateManager(1000, new Runnable() {
@Override
public void run() {
provider.reload();
}
});
swingMgr = new SwingUpdateManager(1000, () -> provider.reload());
}
@ -98,12 +88,6 @@ public class FunctionWindowPlugin extends ProgramPlugin
super.dispose();
}
////////////////////////////////////////////////////////////////////////////
//
// Implementation of DomainObjectListener
//
////////////////////////////////////////////////////////////////////////////
@Override
public void domainObjectChanged(DomainObjectChangedEvent ev) {
if (ev.containsEvent(DomainObject.DO_OBJECT_RESTORED)) {
@ -168,20 +152,18 @@ public class FunctionWindowPlugin extends ProgramPlugin
provider.update(function);
}
break;
/*case ChangeManager.DOCR_SYMBOL_REMOVED:
rec = (ProgramChangeRecord)ev.getChangeRecord(i);
addr = (Address)rec.getObject();
function = currentProgram.getListing().getFunctionAt(addr);
if (function != null) {
provider.functionChanged(function);
}
break;*/
/*case ChangeManager.DOCR_SYMBOL_REMOVED:
rec = (ProgramChangeRecord)ev.getChangeRecord(i);
addr = (Address)rec.getObject();
function = currentProgram.getListing().getFunctionAt(addr);
if (function != null) {
provider.functionChanged(function);
}
break;*/
}
}
}
////////////////////////////////////////////////////////////////////////////
@Override
protected void programActivated(Program program) {
program.addListener(this);
@ -194,17 +176,10 @@ public class FunctionWindowPlugin extends ProgramPlugin
provider.programClosed();
}
////////////////////////////////////////////////////////////////////////////
Program getProgram() {
return currentProgram;
}
////////////////////////////////////////////////////////////////////////////
/**
* Create the action objects for this plugin.
*/
private void createActions() {
addSelectAction();
addCompareAction();
@ -214,19 +189,13 @@ public class FunctionWindowPlugin extends ProgramPlugin
}
private void addSelectAction() {
selectAction = new DockingAction("Make Selection", getName(), false) {
selectAction = new MakeProgramSelectionAction(getName(), provider.getTable()) {
@Override
public void actionPerformed(ActionContext context) {
protected void makeSelection(ActionContext context) {
selectFunctions(provider.selectFunctions());
}
};
selectAction.setEnabled(false);
ImageIcon icon = ResourceManager.loadImage("images/text_align_justify.png");
selectAction.setPopupMenuData(new MenuData(new String[] { "Make Selection" }, icon));
selectAction.setDescription("Selects currently selected function(s) in table");
selectAction.setToolBarData(new ToolBarData(icon));
installDummyAction(selectAction);
tool.addLocalAction(provider, selectAction);
}
@ -238,43 +207,15 @@ public class FunctionWindowPlugin extends ProgramPlugin
compareSelectedFunctions();
}
};
compareAction.setEnabled(false);
ImageIcon icon = ResourceManager.loadImage("images/page_white_c.png");
compareAction.setPopupMenuData(new MenuData(new String[] { "Compare Functions" }, icon));
compareAction.setDescription("Compares the currently selected function(s) in the table.");
compareAction.setToolBarData(new ToolBarData(icon));
installDummyAction(compareAction);
tool.addLocalAction(provider, compareAction);
}
private void installDummyAction(DockingAction action) {
DummyKeyBindingsOptionsAction dummyAction =
new DummyKeyBindingsOptionsAction(action.getName(), null);
tool.addAction(dummyAction);
ToolOptions options = tool.getOptions(ToolConstants.KEY_BINDINGS);
options.addOptionsChangeListener(this);
KeyStroke keyStroke = options.getKeyStroke(dummyAction.getFullName(), null);
if (keyStroke != null) {
action.setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
}
@Override
public void optionsChanged(ToolOptions options, String optionName, Object oldValue, Object newValue) {
if (optionName.startsWith(selectAction.getName())) {
KeyStroke keyStroke = (KeyStroke) newValue;
selectAction.setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
if (optionName.startsWith(compareAction.getName())) {
KeyStroke keyStroke = (KeyStroke) newValue;
compareAction.setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
}
void setActionsEnabled(boolean enabled) {
selectAction.setEnabled(enabled);
compareAction.setEnabled(enabled);

View file

@ -17,20 +17,18 @@ package ghidra.app.plugin.core.navigation.locationreferences;
import javax.swing.KeyStroke;
import docking.action.*;
import docking.action.KeyBindingData;
import docking.action.MenuData;
import ghidra.app.actions.AbstractFindReferencesDataTypeAction;
import ghidra.app.context.ListingActionContext;
import ghidra.app.context.ListingContextAction;
import ghidra.framework.options.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.ToolConstants;
import ghidra.program.model.address.Address;
import ghidra.program.util.ProgramLocation;
/**
* {@link LocationReferencesPlugin}'s action for finding references to a thing.
*/
public class FindReferencesToAction extends ListingContextAction implements OptionsChangeListener {
public class FindReferencesToAction extends ListingContextAction {
private LocationReferencesPlugin plugin;
private int subGroupPosition;
@ -44,37 +42,22 @@ public class FindReferencesToAction extends ListingContextAction implements Opti
setDescription("Shows references to the item under the cursor");
//
// Shared keybinding setup
//
KeyStroke defaultkeyStroke = AbstractFindReferencesDataTypeAction.DEFAULT_KEY_STROKE;
PluginTool tool = plugin.getTool();
DockingAction action = new DummyKeyBindingsOptionsAction(
AbstractFindReferencesDataTypeAction.NAME, defaultkeyStroke);
tool.addAction(action);
initKeyStroke(defaultkeyStroke);
}
// setup options to know when the dummy key binding is changed
ToolOptions options = tool.getOptions(ToolConstants.KEY_BINDINGS);
KeyStroke optionsKeyStroke = options.getKeyStroke(action.getFullName(), defaultkeyStroke);
if (!defaultkeyStroke.equals(optionsKeyStroke)) {
// user-defined keystroke
setUnvalidatedKeyBindingData(new KeyBindingData(optionsKeyStroke));
}
else {
setKeyBindingData(new KeyBindingData(optionsKeyStroke));
private void initKeyStroke(KeyStroke keyStroke) {
if (keyStroke == null) {
return;
}
options.addOptionsChangeListener(this);
// we don't have a default keybinding, so any value implies user-defined
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
@Override
public void optionsChanged(ToolOptions options, String name, Object oldValue, Object newValue) {
KeyStroke keyStroke = (KeyStroke) newValue;
String actionName = getName();
if (name.startsWith(actionName)) {
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
public boolean usesSharedKeyBinding() {
return true;
}
@Override

View file

@ -35,7 +35,7 @@ import ghidra.program.model.listing.Program;
import ghidra.program.util.ProgramLocation;
import ghidra.util.HelpLocation;
import ghidra.util.Msg;
import ghidra.util.table.DeleteTableRowAction;
import ghidra.util.table.actions.DeleteTableRowAction;
/**
* Plugin to show a list of references to the item represented by the location of the cursor.

View file

@ -39,6 +39,7 @@ import ghidra.program.model.listing.Program;
import ghidra.program.util.ProgramLocation;
import ghidra.util.HelpLocation;
import ghidra.util.table.*;
import ghidra.util.table.actions.DeleteTableRowAction;
import ghidra.util.task.SwingUpdateManager;
import resources.Icons;
import resources.ResourceManager;
@ -441,7 +442,7 @@ public class LocationReferencesProvider extends ComponentProviderAdapter
private class DeleteAction extends DeleteTableRowAction {
DeleteAction(PluginTool tool, GTable table) {
super(tool, table, locationReferencesPlugin.getName());
super(table, locationReferencesPlugin.getName());
}
@Override

View file

@ -33,7 +33,7 @@ import ghidra.framework.plugintool.util.ToolConstants;
import ghidra.program.model.listing.Program;
import ghidra.program.util.ChangeManager;
import ghidra.util.HelpLocation;
import ghidra.util.table.DeleteTableRowAction;
import ghidra.util.table.actions.DeleteTableRowAction;
import ghidra.util.task.SwingUpdateManager;
/**

View file

@ -23,16 +23,14 @@ import javax.swing.*;
import javax.swing.border.Border;
import docking.*;
import docking.action.*;
import docking.action.DockingAction;
import docking.help.HelpService;
import docking.tool.util.DockingToolConstants;
import docking.widgets.label.GLabel;
import docking.widgets.table.GTableFilterPanel;
import docking.widgets.table.TableFilter;
import ghidra.app.events.ProgramSelectionPluginEvent;
import ghidra.app.plugin.core.scalartable.RangeFilterTextField.FilterType;
import ghidra.app.services.GoToService;
import ghidra.framework.options.*;
import ghidra.framework.plugintool.ComponentProviderAdapter;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program;
@ -40,6 +38,8 @@ import ghidra.program.model.scalar.Scalar;
import ghidra.program.util.ProgramSelection;
import ghidra.util.HelpLocation;
import ghidra.util.table.*;
import ghidra.util.table.actions.DeleteTableRowAction;
import ghidra.util.table.actions.MakeProgramSelectionAction;
import resources.ResourceManager;
/**
@ -49,8 +49,7 @@ import resources.ResourceManager;
* <li>The range filter that allows the user to filter the scalar table via a min and max value.
* </ul>
*/
public class ScalarSearchProvider extends ComponentProviderAdapter
implements OptionsChangeListener {
public class ScalarSearchProvider extends ComponentProviderAdapter {
public static final ImageIcon ICON = ResourceManager.loadImage("images/dataW.gif");
@ -143,15 +142,6 @@ public class ScalarSearchProvider extends ComponentProviderAdapter
return min.equals(Integer.toString(minValue)) && max.equals(Integer.toString(maxValue));
}
@Override
public void optionsChanged(ToolOptions options, String optionName, Object oldValue,
Object newValue) {
if (optionName.startsWith(selectAction.getName())) {
KeyStroke keyStroke = (KeyStroke) newValue;
selectAction.setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
}
private void selectDataInProgramFromTable(ProgramSelection selection) {
ProgramSelectionPluginEvent pspe =
new ProgramSelectionPluginEvent("Selection", selection, plugin.getCurrentProgram());
@ -268,30 +258,12 @@ public class ScalarSearchProvider extends ComponentProviderAdapter
private void createActions() {
selectAction = new DockingAction("Make Selection", getName(), false) {
selectAction = new MakeProgramSelectionAction(getName(), getTable()) {
@Override
public void actionPerformed(ActionContext context) {
protected void makeSelection(ActionContext context) {
selectDataInProgramFromTable(getSelection());
}
@Override
public boolean isEnabledForContext(ActionContext context) {
if (!(context instanceof ScalarSearchContext)) {
return false;
}
ScalarSearchContext scalarWindowContext = (ScalarSearchContext) context;
GhidraTable table = scalarWindowContext.getScalarTable();
return table.getSelectedRows().length > 0;
}
};
selectAction.setEnabled(false);
ImageIcon icon = ResourceManager.loadImage("images/text_align_justify.png");
selectAction.setPopupMenuData(new MenuData(new String[] { "Make Selection" }, icon));
selectAction.setDescription("Selects currently selected scalar(s) in table");
selectAction.setToolBarData(new ToolBarData(icon));
selectAction.setHelpLocation(new HelpLocation(plugin.getName(), "Make_Selection"));
installDummyAction(selectAction);
tool.addLocalAction(this, selectAction);
@ -299,24 +271,10 @@ public class ScalarSearchProvider extends ComponentProviderAdapter
tool.addLocalAction(this, selectionAction);
GhidraTable table = threadedTablePanel.getTable();
DockingAction removeItemsAction = new DeleteTableRowAction(tool, table, plugin.getName());
DockingAction removeItemsAction = new DeleteTableRowAction(table, plugin.getName());
tool.addLocalAction(this, removeItemsAction);
}
private void installDummyAction(DockingAction action) {
DummyKeyBindingsOptionsAction dummyAction =
new DummyKeyBindingsOptionsAction(action.getName(), null);
tool.addAction(dummyAction);
ToolOptions options = tool.getOptions(DockingToolConstants.KEY_BINDINGS);
options.addOptionsChangeListener(this);
KeyStroke keyStroke = options.getKeyStroke(dummyAction.getFullName(), null);
if (keyStroke != null) {
action.setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
}
//==================================================================================================
// TODO Delete - the custom filtering code below this line needs to be deleted, as it is now
// replaced by the column filtering

View file

@ -33,8 +33,7 @@ import generic.jar.ResourceFile;
import ghidra.app.script.GhidraScriptUtil;
import ghidra.app.script.ScriptInfo;
import ghidra.framework.Application;
import ghidra.framework.options.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.options.SaveState;
import ghidra.framework.plugintool.util.ToolConstants;
import ghidra.util.*;
import ghidra.util.task.*;
@ -120,6 +119,7 @@ class GhidraScriptActionManager {
/**
* This saves bindings that users have changed. These will overwrite those that may
* be defined in the script.
* @param saveState the state into which bindings are saved
*/
void saveUserDefinedKeybindings(SaveState saveState) {
Collection<ScriptAction> actions = actionMap.values();
@ -147,6 +147,7 @@ class GhidraScriptActionManager {
/**
* This saves scripts that not only have keybindings, but that are also marked as "In Tool"
* from the GUI.
* @param saveState the state into which the script info is saved
*/
void saveScriptsThatAreInTool(SaveState saveState) {
Set<ResourceFile> actionScriptFiles = actionMap.keySet();
@ -194,10 +195,9 @@ class GhidraScriptActionManager {
runAction.setEnabled(false);
plugin.getTool().addLocalAction(provider, runAction);
runLastAction = new RerunLastScriptAction(RERUN_LAST_SHARED_ACTION_NAME, runGroup);
runLastAction = new RerunLastScriptAction(runGroup);
plugin.getTool().addLocalAction(provider, runLastAction);
globalRunLastAction =
new RerunLastScriptAction(GLOBAL_RERUN_LAST_SHARED_ACTION_NAME, "Xtra");
globalRunLastAction = new RerunLastScriptAction("Xtra");
plugin.getTool().addAction(globalRunLastAction);
//
@ -626,41 +626,33 @@ class GhidraScriptActionManager {
}
private class RerunLastScriptAction extends DockingAction implements OptionsChangeListener {
private class RerunLastScriptAction extends DockingAction {
RerunLastScriptAction(String actionName, String toolbarGroup) {
super(actionName, plugin.getName(), false);
RerunLastScriptAction(String toolbarGroup) {
super(RERUN_LAST_SHARED_ACTION_NAME, plugin.getName(), false);
setToolBarData(
new ToolBarData(ResourceManager.loadImage("images/play_again.png"), toolbarGroup));
setDescription("Rerun the last run script");
setEnabled(false);
DockingAction action = new DummyKeyBindingsOptionsAction(RERUN_LAST_SHARED_ACTION_NAME,
RERUN_LAST_SCRIPT_KEYSTROKE);
PluginTool tool = plugin.getTool();
tool.addAction(action);
// setup options to know when the dummy key binding is changed
ToolOptions options = tool.getOptions(ToolConstants.KEY_BINDINGS);
KeyStroke keyStroke =
options.getKeyStroke(getFullSharedActionName(), RERUN_LAST_SCRIPT_KEYSTROKE);
if (!RERUN_LAST_SCRIPT_KEYSTROKE.equals(keyStroke)) {
// user-defined keystroke
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
else {
setKeyBindingData(new KeyBindingData(keyStroke));
}
options.addOptionsChangeListener(this);
setHelpLocation(new HelpLocation(plugin.getName(), "Run_Last"));
initKeyStroke(RERUN_LAST_SCRIPT_KEYSTROKE);
}
private String getFullSharedActionName() {
return RERUN_LAST_SHARED_ACTION_NAME + " (Tool)";
private void initKeyStroke(KeyStroke keyStroke) {
if (keyStroke == null) {
return;
}
// we don't have a default keybinding, so any value implies user-defined
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
@Override
public boolean usesSharedKeyBinding() {
return true;
}
@Override
@ -672,15 +664,5 @@ class GhidraScriptActionManager {
public boolean isEnabledForContext(ActionContext context) {
return provider.getLastRunScript() != null;
}
@Override
public void optionsChanged(ToolOptions options, String name, Object oldValue,
Object newValue) {
KeyStroke keyStroke = (KeyStroke) newValue;
if (name.startsWith(RERUN_LAST_SHARED_ACTION_NAME)) {
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
}
}
}

View file

@ -16,11 +16,9 @@
package ghidra.app.plugin.core.strings;
import javax.swing.ImageIcon;
import javax.swing.KeyStroke;
import docking.ActionContext;
import docking.action.*;
import docking.tool.util.DockingToolConstants;
import ghidra.app.CorePluginPackage;
import ghidra.app.events.ProgramSelectionPluginEvent;
import ghidra.app.plugin.PluginCategoryNames;
@ -28,7 +26,6 @@ import ghidra.app.plugin.ProgramPlugin;
import ghidra.app.plugin.core.data.DataSettingsDialog;
import ghidra.app.services.GoToService;
import ghidra.framework.model.*;
import ghidra.framework.options.*;
import ghidra.framework.plugintool.PluginInfo;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.PluginStatus;
@ -38,9 +35,9 @@ import ghidra.program.util.*;
import ghidra.util.HelpLocation;
import ghidra.util.exception.CancelledException;
import ghidra.util.table.SelectionNavigationAction;
import ghidra.util.table.actions.MakeProgramSelectionAction;
import ghidra.util.task.SwingUpdateManager;
import resources.Icons;
import resources.ResourceManager;
/**
* Plugin that provides the "Defined Strings" table, where all the currently defined
@ -58,8 +55,7 @@ import resources.ResourceManager;
servicesRequired = { GoToService.class }
)
//@formatter:on
public class ViewStringsPlugin extends ProgramPlugin
implements DomainObjectListener, OptionsChangeListener {
public class ViewStringsPlugin extends ProgramPlugin implements DomainObjectListener {
private DockingAction selectAction;
private DockingAction showSettingsAction;
@ -104,24 +100,13 @@ public class ViewStringsPlugin extends ProgramPlugin
refreshAction.setHelpLocation(new HelpLocation("ViewStringsPlugin", "Refresh"));
tool.addLocalAction(provider, refreshAction);
selectAction = new DockingAction("Make Selection", getName(), false) {
selectAction = new MakeProgramSelectionAction(getName(), provider.getTable()) {
@Override
public void actionPerformed(ActionContext context) {
protected void makeSelection(ActionContext context) {
selectData(provider.selectData());
}
@Override
public boolean isEnabledForContext(ActionContext context) {
return provider.getSelectedRowCount() > 0;
}
};
ImageIcon selectActionIcon = ResourceManager.loadImage("images/text_align_justify.png");
selectAction.setPopupMenuData(
new MenuData(new String[] { "Make Selection" }, selectActionIcon));
selectAction.setDescription("Selects currently selected data in table");
selectAction.setToolBarData(new ToolBarData(selectActionIcon));
installDummyAction(selectAction);
tool.addLocalAction(provider, selectAction);
@ -175,29 +160,6 @@ public class ViewStringsPlugin extends ProgramPlugin
}
private void installDummyAction(DockingAction action) {
DummyKeyBindingsOptionsAction dummyAction =
new DummyKeyBindingsOptionsAction(action.getName(), null);
tool.addAction(dummyAction);
ToolOptions options = tool.getOptions(DockingToolConstants.KEY_BINDINGS);
options.addOptionsChangeListener(this);
KeyStroke keyStroke = options.getKeyStroke(dummyAction.getFullName(), null);
if (keyStroke != null) {
action.setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
}
@Override
public void optionsChanged(ToolOptions options, String optionName, Object oldValue,
Object newValue) {
if (optionName.startsWith(selectAction.getName())) {
KeyStroke keyStroke = (KeyStroke) newValue;
selectAction.setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
}
private void selectData(ProgramSelection selection) {
ProgramSelectionPluginEvent pspe =
new ProgramSelectionPluginEvent("Selection", selection, currentProgram);
@ -245,7 +207,6 @@ public class ViewStringsPlugin extends ProgramPlugin
else if (ev.containsEvent(ChangeManager.DOCR_CODE_ADDED)) {
for (int i = 0; i < ev.numRecords(); ++i) {
DomainObjectChangeRecord doRecord = ev.getChangeRecord(i);
Object oldValue = doRecord.getOldValue();
Object newValue = doRecord.getNewValue();
switch (doRecord.getEventType()) {
case ChangeManager.DOCR_CODE_REMOVED:

View file

@ -16,28 +16,26 @@
package ghidra.app.plugin.core.symboltree.actions;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.tree.TreePath;
import docking.action.*;
import docking.action.KeyBindingData;
import docking.action.MenuData;
import ghidra.app.actions.AbstractFindReferencesDataTypeAction;
import ghidra.app.nav.Navigatable;
import ghidra.app.plugin.core.navigation.locationreferences.LocationReferencesService;
import ghidra.app.plugin.core.symboltree.SymbolTreeActionContext;
import ghidra.app.plugin.core.symboltree.nodes.*;
import ghidra.app.services.CodeViewerService;
import ghidra.framework.options.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.ServiceListener;
import ghidra.framework.plugintool.util.ToolConstants;
import ghidra.program.database.symbol.FunctionSymbol;
import ghidra.program.model.symbol.Symbol;
import ghidra.program.util.FunctionSignatureFieldLocation;
import ghidra.program.util.ProgramLocation;
import ghidra.util.Msg;
import ghidra.util.Swing;
public class ShowSymbolReferencesAction extends SymbolTreeContextAction
implements OptionsChangeListener {
public class ShowSymbolReferencesAction extends SymbolTreeContextAction {
private PluginTool tool;
@ -53,7 +51,7 @@ public class ShowSymbolReferencesAction extends SymbolTreeContextAction
public void serviceAdded(Class<?> interfaceClass, Object service) {
if (interfaceClass.equals(LocationReferencesService.class)) {
setHelpLocation(((LocationReferencesService) service).getHelpLocation());
SwingUtilities.invokeLater(() -> tool.removeServiceListener(this));
Swing.runLater(() -> tool.removeServiceListener(this));
}
}
};
@ -66,27 +64,22 @@ public class ShowSymbolReferencesAction extends SymbolTreeContextAction
installHelpLocation();
//
// Shared keybinding setup
//
KeyStroke defaultkeyStroke = AbstractFindReferencesDataTypeAction.DEFAULT_KEY_STROKE;
DockingAction action = new DummyKeyBindingsOptionsAction(
AbstractFindReferencesDataTypeAction.NAME, defaultkeyStroke);
tool.addAction(action);
initKeyStroke(defaultkeyStroke);
}
// setup options to know when the dummy key binding is changed
ToolOptions options = tool.getOptions(ToolConstants.KEY_BINDINGS);
KeyStroke optionsKeyStroke = options.getKeyStroke(action.getFullName(), defaultkeyStroke);
if (!defaultkeyStroke.equals(optionsKeyStroke)) {
// user-defined keystroke
setUnvalidatedKeyBindingData(new KeyBindingData(optionsKeyStroke));
}
else {
setKeyBindingData(new KeyBindingData(optionsKeyStroke));
private void initKeyStroke(KeyStroke keyStroke) {
if (keyStroke == null) {
return;
}
options.addOptionsChangeListener(this);
// we don't have a default keybinding, so any value implies user-defined
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
@Override
public boolean usesSharedKeyBinding() {
return true;
}
private void installHelpLocation() {
@ -102,15 +95,6 @@ public class ShowSymbolReferencesAction extends SymbolTreeContextAction
setHelpLocation(locationReferencesService.getHelpLocation());
}
@Override
public void optionsChanged(ToolOptions options, String name, Object oldValue, Object newValue) {
KeyStroke keyStroke = (KeyStroke) newValue;
String actionName = getName();
if (name.startsWith(actionName)) {
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
}
@Override
protected boolean isEnabledForContext(SymbolTreeActionContext context) {

View file

@ -69,7 +69,7 @@ class SymbolProvider extends ComponentProviderAdapter {
for (SymbolRowObject obj : rowObjects) {
symbolIDs[index++] = obj.getKey();
}
return new ProgramSymbolActionContext(this, program, symbolIDs);
return new ProgramSymbolActionContext(this, program, symbolIDs, getTable());
}
void deleteSymbols() {

View file

@ -20,7 +20,6 @@ import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.KeyStroke;
import docking.ActionContext;
import docking.action.*;
@ -33,9 +32,9 @@ import ghidra.app.services.BlockModelService;
import ghidra.app.services.GoToService;
import ghidra.app.util.SymbolInspector;
import ghidra.framework.model.*;
import ghidra.framework.options.*;
import ghidra.framework.options.SaveState;
import ghidra.framework.plugintool.*;
import ghidra.framework.plugintool.util.*;
import ghidra.framework.plugintool.util.PluginStatus;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Data;
import ghidra.program.model.listing.Program;
@ -45,6 +44,7 @@ import ghidra.program.util.ChangeManager;
import ghidra.program.util.ProgramChangeRecord;
import ghidra.util.table.GhidraTable;
import ghidra.util.table.SelectionNavigationAction;
import ghidra.util.table.actions.MakeProgramSelectionAction;
import ghidra.util.task.SwingUpdateManager;
import resources.Icons;
import resources.ResourceManager;
@ -69,10 +69,7 @@ import resources.ResourceManager;
eventsConsumed = { ProgramActivatedPluginEvent.class }
)
//@formatter:on
public class SymbolTablePlugin extends Plugin
implements DomainObjectListener, OptionsChangeListener {
private static final String PLUGIN_NAME = "SymbolTablePlugin";
public class SymbolTablePlugin extends Plugin implements DomainObjectListener {
final static Cursor WAIT_CURSOR = new Cursor(Cursor.WAIT_CURSOR);
final static Cursor NORM_CURSOR = new Cursor(Cursor.DEFAULT_CURSOR);
@ -437,32 +434,14 @@ public class SymbolTablePlugin extends Plugin
DockingAction editExternalLocationAction = new EditExternalLocationAction(this);
tool.addLocalAction(symProvider, editExternalLocationAction);
makeSelectionAction = new DockingAction("Make Selection", getName(), false) {
makeSelectionAction = new MakeProgramSelectionAction(getName(), symProvider.getTable()) {
@Override
public void actionPerformed(ActionContext context) {
protected void makeSelection(ActionContext context) {
symProvider.makeSelection();
}
@Override
public boolean isEnabledForContext(ActionContext context) {
GhidraTable table = symProvider.getTable();
return table.getSelectedRowCount() > 0;
}
@Override
public boolean isAddToPopup(ActionContext context) {
return true;
}
};
icon = ResourceManager.loadImage("images/text_align_justify.png");
makeSelectionAction.setPopupMenuData(
new MenuData(new String[] { "Make Selection" }, icon, popupGroup));
makeSelectionAction.setToolBarData(new ToolBarData(icon));
makeSelectionAction.setDescription("Make a selection using selected Symbol addresses");
makeSelectionAction.setEnabled(false);
installDummyAction(makeSelectionAction);
makeSelectionAction.getPopupMenuData().setMenuGroup(popupGroup);
tool.addLocalAction(symProvider, makeSelectionAction);
@ -478,8 +457,6 @@ public class SymbolTablePlugin extends Plugin
}
};
icon = Icons.CONFIGURE_FILTER_ICON;
setFilterAction.setPopupMenuData(
new MenuData(new String[] { "Configure Symbol Filter" }, icon, popupGroup));
setFilterAction.setToolBarData(new ToolBarData(icon));
setFilterAction.setDescription("Configure Symbol Filter");
@ -505,29 +482,6 @@ public class SymbolTablePlugin extends Plugin
tool.addAction(clearPinnedAction);
}
private void installDummyAction(DockingAction action) {
DummyKeyBindingsOptionsAction dummyAction =
new DummyKeyBindingsOptionsAction(action.getName(), null);
tool.addAction(dummyAction);
ToolOptions options = tool.getOptions(ToolConstants.KEY_BINDINGS);
options.addOptionsChangeListener(this);
KeyStroke keyStroke = options.getKeyStroke(dummyAction.getFullName(), null);
if (keyStroke != null) {
action.setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
}
@Override
public void optionsChanged(ToolOptions options, String optionName, Object oldValue,
Object newValue) {
if (optionName.startsWith(makeSelectionAction.getName())) {
KeyStroke keyStroke = (KeyStroke) newValue;
makeSelectionAction.setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
}
private void createRefActions() {
referencesToAction = new ToggleDockingAction("References To", getName()) {
@Override

View file

@ -27,7 +27,8 @@ import javax.swing.event.TableModelListener;
import docking.ActionContext;
import docking.ComponentProviderActivationListener;
import docking.action.*;
import docking.action.DockingAction;
import docking.action.MenuData;
import docking.widgets.table.AbstractSortedTableModel;
import docking.widgets.table.GTable;
import docking.widgets.table.threaded.GThreadedTablePanel;
@ -35,21 +36,19 @@ import ghidra.app.nav.Navigatable;
import ghidra.app.nav.NavigatableRemovalListener;
import ghidra.app.services.*;
import ghidra.app.util.HelpTopics;
import ghidra.framework.options.OptionsChangeListener;
import ghidra.framework.options.ToolOptions;
import ghidra.framework.plugintool.ComponentProviderAdapter;
import ghidra.framework.plugintool.Plugin;
import ghidra.framework.plugintool.util.ToolConstants;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program;
import ghidra.program.util.*;
import ghidra.util.HelpLocation;
import ghidra.util.SystemUtilities;
import ghidra.util.table.*;
import ghidra.util.table.actions.DeleteTableRowAction;
import ghidra.util.table.actions.MakeProgramSelectionAction;
import resources.ResourceManager;
public class TableComponentProvider<T> extends ComponentProviderAdapter
implements TableModelListener, NavigatableRemovalListener, OptionsChangeListener {
implements TableModelListener, NavigatableRemovalListener {
private JPanel componentPanel;
private GhidraThreadedTablePanel<T> threadedPanel;
@ -158,28 +157,17 @@ public class TableComponentProvider<T> extends ComponentProviderAdapter
}
private void createActions(final Plugin plugin) {
selectAction = new DockingAction(TableServicePlugin.MAKE_SELECTION_ACTION_NAME,
tableServicePlugin.getName(), false) {
@Override
public void actionPerformed(ActionContext context) {
makeSelection(plugin);
}
GhidraTable table = threadedPanel.getTable();
selectAction = new MakeProgramSelectionAction(tableServicePlugin.getName(), table) {
@Override
public boolean isEnabledForContext(ActionContext context) {
GhidraTable table = threadedPanel.getTable();
return table.getSelectedRowCount() > 0;
protected void makeSelection(ActionContext context) {
doMakeSelection(plugin);
}
};
selectAction.setDescription("Make a selection using selected rows");
selectAction.setEnabled(false);
ImageIcon icon = ResourceManager.loadImage("images/text_align_justify.png");
selectAction.setToolBarData(new ToolBarData(icon, null));
selectAction.setPopupMenuData(new MenuData(new String[] { "Make Selection" }, icon, null));
selectAction.setHelpLocation(new HelpLocation(HelpTopics.SEARCH, "Make_Selection"));
selectionNavigationAction = new SelectionNavigationAction(plugin, threadedPanel.getTable());
selectionNavigationAction = new SelectionNavigationAction(plugin, table);
selectionNavigationAction.setHelpLocation(
new HelpLocation(HelpTopics.SEARCH, "Selection_Navigation"));
@ -187,21 +175,20 @@ public class TableComponentProvider<T> extends ComponentProviderAdapter
new DockingAction("Go to External Location", getName(), false) {
@Override
public void actionPerformed(ActionContext context) {
gotoExternalAddress(getSlectedExternalAddress());
gotoExternalAddress(getSelectedExternalAddress());
}
@Override
public boolean isEnabledForContext(ActionContext context) {
return getSlectedExternalAddress() != null &&
return getSelectedExternalAddress() != null &&
tool.getService(GoToService.class) != null;
}
private Address getSlectedExternalAddress() {
GhidraTable table = threadedPanel.getTable();
private Address getSelectedExternalAddress() {
if (table.getSelectedRowCount() != 1) {
return null;
}
ProgramSelection selection = threadedPanel.getTable().getProgramSelection();
ProgramSelection selection = table.getProgramSelection();
Program modelProgram = model.getProgram();
if (modelProgram == null || selection.getNumAddresses() != 1) {
return null;
@ -213,17 +200,14 @@ public class TableComponentProvider<T> extends ComponentProviderAdapter
externalGotoAction.setDescription("Go to an external location");
externalGotoAction.setEnabled(false);
icon = ResourceManager.loadImage("images/searchm_obj.gif");
Icon icon = ResourceManager.loadImage("images/searchm_obj.gif");
externalGotoAction.setPopupMenuData(
new MenuData(new String[] { "GoTo External Location" }, icon, null));
externalGotoAction.setHelpLocation(new HelpLocation(HelpTopics.SEARCH, "Navigation"));
configureKeybinding(selectAction, null);
plugin.getTool().addLocalAction(this, selectAction);
plugin.getTool().addLocalAction(this, selectionNavigationAction);
plugin.getTool().addLocalAction(this, externalGotoAction);
}
public void installRemoveItemsAction() {
@ -232,38 +216,11 @@ public class TableComponentProvider<T> extends ComponentProviderAdapter
}
GhidraTable table = threadedPanel.getTable();
removeItemsAction = new DeleteTableRowAction(tool, table, tableServicePlugin.getName());
removeItemsAction = new DeleteTableRowAction(table, tableServicePlugin.getName());
tool.addLocalAction(this, removeItemsAction);
}
private void configureKeybinding(DockingAction action, KeyStroke keyBinding) {
// setup options to know when the dummy key binding is changed
ToolOptions options = tool.getOptions(ToolConstants.KEY_BINDINGS);
KeyStroke keyStroke = options.getKeyStroke(
action.getName() + TableServicePlugin.SHARED_ACTION_OWNER_SUFFIX, keyBinding);
if (!SystemUtilities.isEqual(keyBinding, keyStroke)) {
// user-defined keystroke
action.setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
else {
action.setKeyBindingData(new KeyBindingData(keyStroke));
}
options.removeOptionsChangeListener(this); // don't double add
options.addOptionsChangeListener(this);
}
@Override
public void optionsChanged(ToolOptions options, String optionName, Object oldValue,
Object newValue) {
if (optionName.startsWith(TableServicePlugin.MAKE_SELECTION_ACTION_NAME)) {
KeyStroke keyStroke = (KeyStroke) newValue;
selectAction.setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
}
private JPanel createFilterFieldPanel(JTable table, AbstractSortedTableModel<T> sortedModel) {
tableFilterPanel = new GhidraTableFilterPanel<>(table, sortedModel);
tableFilterPanel.setToolTipText("Filter search results");
@ -309,7 +266,7 @@ public class TableComponentProvider<T> extends ComponentProviderAdapter
}
}
private void makeSelection(Plugin plugin) {
private void doMakeSelection(Plugin plugin) {
ProgramSelection selection = threadedPanel.getTable().getProgramSelection();
Program modelProgram = model.getProgram();
if (modelProgram == null || selection.getNumAddresses() == 0) {

View file

@ -33,12 +33,11 @@ import ghidra.app.tablechooser.TableChooserExecutor;
import ghidra.app.util.query.TableService;
import ghidra.framework.model.DomainObjectChangedEvent;
import ghidra.framework.model.DomainObjectListener;
import ghidra.framework.options.DummyKeyBindingsOptionsAction;
import ghidra.framework.plugintool.*;
import ghidra.framework.plugintool.util.PluginStatus;
import ghidra.program.model.listing.Program;
import ghidra.util.table.DeleteTableRowAction;
import ghidra.util.table.GhidraProgramTableModel;
import ghidra.util.table.actions.DeleteTableRowAction;
import ghidra.util.task.SwingUpdateManager;
//@formatter:off
@ -62,21 +61,14 @@ public class TableServicePlugin extends ProgramPlugin
static final String SHARED_ACTION_OWNER_SUFFIX = " (Tool)";
private SwingUpdateManager updateMgr;
private Map<Program, List<TableComponentProvider<?>>> programMap =
new HashMap<Program, List<TableComponentProvider<?>>>();
private Map<Program, List<TableComponentProvider<?>>> programMap = new HashMap<>();
private Map<Program, List<TableChooserDialog>> programToDialogMap =
new HashMap<Program, List<TableChooserDialog>>();
private Map<Program, List<TableChooserDialog>> programToDialogMap = new HashMap<>();
public TableServicePlugin(PluginTool tool) {
super(tool, false, false);
updateMgr = new SwingUpdateManager(1000, new Runnable() {
@Override
public void run() {
updateProviders();
}
});
updateMgr = new SwingUpdateManager(1000, () -> updateProviders());
createActions();
}
@ -89,12 +81,6 @@ public class TableServicePlugin extends ProgramPlugin
// providers are created, as they would only appear in the options at
// that point.
//
DummyKeyBindingsOptionsAction dummyMakeSelectionAction =
new DummyKeyBindingsOptionsAction(MAKE_SELECTION_ACTION_NAME, null);
tool.addAction(dummyMakeSelectionAction);
DeleteTableRowAction.registerDummy(tool);
}
@ -105,9 +91,6 @@ public class TableServicePlugin extends ProgramPlugin
super.dispose();
}
/* (non-Javadoc)
* @see ghidra.framework.plugintool.Plugin#processEvent(ghidra.framework.plugintool.PluginEvent)
*/
@Override
public void processEvent(PluginEvent event) {
if (event instanceof ProgramClosedPluginEvent) {
@ -140,7 +123,7 @@ public class TableServicePlugin extends ProgramPlugin
return;
}
// make a copy of the list because the provider updates the list
List<TableComponentProvider<?>> list = new ArrayList<TableComponentProvider<?>>(plist);
List<TableComponentProvider<?>> list = new ArrayList<>(plist);
for (int i = 0; i < list.size(); i++) {
ComponentProvider provider = list.get(i);
provider.closeComponent();
@ -154,7 +137,7 @@ public class TableServicePlugin extends ProgramPlugin
return;
}
// make a copy of the list because the dialog updates the list
List<TableChooserDialog> list = new ArrayList<TableChooserDialog>(dlist);
List<TableChooserDialog> list = new ArrayList<>(dlist);
for (int i = 0; i < list.size(); i++) {
TableChooserDialog dialog = list.get(i);
dialog.close();
@ -174,9 +157,8 @@ public class TableServicePlugin extends ProgramPlugin
Program program = model.getProgram();
TableComponentProvider<T> cp =
new TableComponentProvider<T>(this, title, tableTypeName, model,
program.getDomainFile().getName(), gotoService, windowSubMenu, navigatable);
TableComponentProvider<T> cp = new TableComponentProvider<>(this, title, tableTypeName,
model, program.getDomainFile().getName(), gotoService, windowSubMenu, navigatable);
addProvider(program, cp);
return cp;
}
@ -195,10 +177,9 @@ public class TableServicePlugin extends ProgramPlugin
MarkerService markerService = tool.getService(MarkerService.class);
Program program = model.getProgram();
TableComponentProvider<T> cp =
new TableComponentProvider<T>(this, title, tableTypeName, model,
program.getDomainFile().getName(), gotoService, markerService, markerColor,
markerIcon, windowSubMenu, navigatable);
TableComponentProvider<T> cp = new TableComponentProvider<>(this, title, tableTypeName,
model, program.getDomainFile().getName(), gotoService, markerService, markerColor,
markerIcon, windowSubMenu, navigatable);
addProvider(program, cp);
return cp;
}
@ -206,7 +187,7 @@ public class TableServicePlugin extends ProgramPlugin
private void addProvider(Program program, TableComponentProvider<?> provider) {
List<TableComponentProvider<?>> list = programMap.get(program);
if (list == null) {
list = new ArrayList<TableComponentProvider<?>>();
list = new ArrayList<>();
programMap.put(program, list);
}
list.add(provider);
@ -241,7 +222,7 @@ public class TableServicePlugin extends ProgramPlugin
}
private List<TableComponentProvider<?>> getProviders() {
List<TableComponentProvider<?>> clist = new ArrayList<TableComponentProvider<?>>();
List<TableComponentProvider<?>> clist = new ArrayList<>();
Iterator<List<TableComponentProvider<?>>> iter = programMap.values().iterator();
while (iter.hasNext()) {
List<TableComponentProvider<?>> list = iter.next();
@ -280,7 +261,7 @@ public class TableServicePlugin extends ProgramPlugin
List<TableChooserDialog> list = programToDialogMap.get(program);
if (list == null) {
list = new ArrayList<TableChooserDialog>();
list = new ArrayList<>();
programToDialogMap.put(program, list);
}
list.add(dialog);

View file

@ -25,12 +25,12 @@ import javax.swing.JButton;
import docking.*;
import docking.action.DockingAction;
import docking.action.MenuData;
import docking.actions.SharedStubKeyBindingAction;
import docking.help.*;
import ghidra.app.DeveloperPluginPackage;
import ghidra.app.plugin.PluginCategoryNames;
import ghidra.framework.main.FrontEndable;
import ghidra.framework.model.Project;
import ghidra.framework.options.DummyKeyBindingsOptionsAction;
import ghidra.framework.plugintool.*;
import ghidra.framework.plugintool.util.PluginStatus;
import ghidra.framework.plugintool.util.ToolConstants;
@ -191,7 +191,7 @@ public class JavaHelpPlugin extends Plugin implements FrontEndable {
private boolean shouldSkipHelpCheck(DockingAction action) {
String actionName = action.getOwner() + " - " + action.getName();
if (action instanceof DummyKeyBindingsOptionsAction) {
if (action instanceof SharedStubKeyBindingAction) {
return true;
}
if (noHelpActions.contains(actionName)) {

View file

@ -13,27 +13,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.util.table;
package ghidra.util.table.actions;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.ImageIcon;
import javax.swing.KeyStroke;
import javax.swing.table.TableModel;
import docking.ActionContext;
import docking.action.MenuData;
import docking.action.ToolBarData;
import docking.action.*;
import docking.widgets.table.GTable;
import docking.widgets.table.RowObjectTableModel;
import docking.widgets.table.threaded.ThreadedTableModel;
import ghidra.app.actions.AbstractSharedKeybindingAction;
import ghidra.app.util.HelpTopics;
import ghidra.framework.options.DummyKeyBindingsOptionsAction;
import ghidra.framework.plugintool.PluginTool;
import ghidra.util.HelpLocation;
import ghidra.util.Msg;
import ghidra.util.*;
import ghidra.util.exception.AssertException;
import ghidra.util.timer.GTimer;
import resources.ResourceManager;
@ -52,7 +49,7 @@ import resources.ResourceManager;
* this action in the Tool's options so that user's can update keybindings, regardless of whether
* they have ever shown one of your transient providers.
*/
public class DeleteTableRowAction extends AbstractSharedKeybindingAction {
public class DeleteTableRowAction extends DockingAction {
private static final KeyStroke DEFAULT_KEYSTROKE =
KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0);
@ -72,28 +69,34 @@ public class DeleteTableRowAction extends AbstractSharedKeybindingAction {
new DummyDeleteAction(tool);
}
/**
* Constructor for stubs only.
*
* @param tool the tool needed to access options
*/
private DeleteTableRowAction(PluginTool tool) {
super(tool, NAME, DummyKeyBindingsOptionsAction.DEFAULT_OWNER, DEFAULT_KEYSTROKE);
}
public DeleteTableRowAction(PluginTool tool, GTable table, String owner) {
this(tool, NAME, owner, DEFAULT_KEYSTROKE);
public DeleteTableRowAction(GTable table, String owner) {
this(NAME, owner, DEFAULT_KEYSTROKE);
this.table = table;
}
private DeleteTableRowAction(PluginTool tool, String name, String owner,
KeyStroke defaultkeyStroke) {
super(tool, name, owner, defaultkeyStroke);
private DeleteTableRowAction(String name, String owner, KeyStroke defaultkeyStroke) {
super(name, owner);
setDescription("Remove the selected rows from the table");
setHelpLocation(new HelpLocation(HelpTopics.SEARCH, "Remove_Items"));
setToolBarData(new ToolBarData(ICON, null));
setPopupMenuData(new MenuData(new String[] { "Remove Items" }, ICON, null));
initKeyStroke(defaultkeyStroke);
}
private void initKeyStroke(KeyStroke keyStroke) {
if (keyStroke == null) {
return;
}
// we don't have a default keybinding, so any value implies user-defined
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
@Override
public boolean usesSharedKeyBinding() {
return true;
}
@Override
@ -122,7 +125,7 @@ public class DeleteTableRowAction extends AbstractSharedKeybindingAction {
@SuppressWarnings("unchecked")
RowObjectTableModel<Object> rowObjectModel = (RowObjectTableModel<Object>) model;
int[] rows = table.getSelectedRows();
List<Object> itemsToRemove = new ArrayList<Object>();
List<Object> itemsToRemove = new ArrayList<>();
for (int row : rows) {
itemsToRemove.add(rowObjectModel.getRowObject(row));
}
@ -163,7 +166,7 @@ public class DeleteTableRowAction extends AbstractSharedKeybindingAction {
}
private void selectRow(TableModel model, final int row) {
SwingUtilities.invokeLater(() -> {
Swing.runLater(() -> {
if (checkForBusy(model)) {
// Selecting rows whilst the model is processing deletes will cause the
@ -195,13 +198,20 @@ public class DeleteTableRowAction extends AbstractSharedKeybindingAction {
//==================================================================================================
private static class DummyDeleteAction extends DeleteTableRowAction {
DummyDeleteAction(PluginTool tool) {
super(tool);
public DummyDeleteAction(PluginTool tool) {
super(NAME, "Tool", DEFAULT_KEYSTROKE);
tool.addAction(this);
}
@Override
public void actionPerformed(ActionContext context) {
// stub
}
@Override
public boolean isEnabledForContext(ActionContext context) {
return false; // stub
}
}
}

View file

@ -0,0 +1,89 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.util.table.actions;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import docking.ActionContext;
import docking.action.*;
import ghidra.util.HelpLocation;
import resources.Icons;
/**
* An action to make a program selection based on the given table's selection. The clients
* must implement the make selection code, as they know their own data. Also, for the context to
* work, the provider using this action must create an {@link ActionContext} that returns a
* context object that is the table passed to this action's constructor.
*/
public abstract class MakeProgramSelectionAction extends DockingAction {
private JTable table;
public MakeProgramSelectionAction(String owner, JTable table) {
super("Make Selection", owner);
this.table = table;
setPopupMenuData(
new MenuData(new String[] { "Make Selection" }, Icons.MAKE_SELECTION_ICON));
setToolBarData(new ToolBarData(Icons.MAKE_SELECTION_ICON));
setDescription("Make a program selection from the seleted rows");
// this help location provides generic help; clients can override to point to their help
setHelpLocation(new HelpLocation("Search", "Make_Selection"));
// null for now, but we may want a default binding in the future
initKeyStroke(null);
}
private void initKeyStroke(KeyStroke keyStroke) {
if (keyStroke == null) {
return;
}
// we don't have a default keybinding, so any value implies user-defined
setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
}
@Override
public boolean usesSharedKeyBinding() {
return true;
}
@Override
public boolean isAddToPopup(ActionContext context) {
return true;
}
@Override
public boolean isEnabledForContext(ActionContext context) {
Object contextObject = context.getContextObject();
if (contextObject != table) {
return false;
}
int n = table.getSelectedRowCount();
return n > 0;
}
@Override
public void actionPerformed(ActionContext context) {
makeSelection(context);
}
protected abstract void makeSelection(ActionContext context);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 B

View file

@ -854,6 +854,22 @@
</P>
</BLOCKQUOTE>
<H3><A name="Graph_AST_Control_Flow"></A>Graph AST Control Flow</H3>
<BLOCKQUOTE>
<P>Selecting <B><IMG alt="" src="../../shared/menu16.gif">Graph AST Control Flow</B>,
from the decompiler provider window toolbar, will generate an abstract syntax tree (AST)
control flow graph based upon the decompiler results and render the graph within the
current Graph Service.</P>
<BLOCKQUOTE>
<P><IMG alt="" src="../../shared/note.yellow.png" border="0">If no Graph Service is
available then this action will not be present.
</P>
</BLOCKQUOTE>
</BLOCKQUOTE>
<H3><A name="Export_to_C"></A>Export to C <IMG alt="" src="images/page_edit.png" border=
"0"></H3>

View file

@ -33,7 +33,6 @@ src/main/help/help/topics/VersionTrackingPlugin/images/DataRefCorr_ExactSelectAl
src/main/help/help/topics/VersionTrackingPlugin/images/DataRefCorr_options.png||GHIDRA||||END|
src/main/help/help/topics/VersionTrackingPlugin/images/DataRefCorr_refined.png||GHIDRA||||END|
src/main/help/help/topics/VersionTrackingPlugin/images/DataRefCorrelator_Setup.png||GHIDRA||||END|
src/main/help/help/topics/VersionTrackingPlugin/images/FuncRefCorr_MatchTableFilters.png||GHIDRA||||END|
src/main/help/help/topics/VersionTrackingPlugin/images/FuncRefCorr_MatchTableFilters_AssocStatus.png||GHIDRA||||END|
src/main/help/help/topics/VersionTrackingPlugin/images/FuncRefCorr_defaultOptions_results.png||GHIDRA||||END|
src/main/help/help/topics/VersionTrackingPlugin/images/FuncRefCorr_lowerScoreThresh.png||GHIDRA||||END|
@ -67,7 +66,6 @@ src/main/help/help/topics/VersionTrackingPlugin/images/VersionTrackingTool.png||
src/main/help/help/topics/VersionTrackingPlugin/images/accepted_fully_applied.png||GHIDRA||reviewed||END|
src/main/help/help/topics/VersionTrackingPlugin/images/accepted_fully_considered.png||GHIDRA||reviewed||END|
src/main/help/help/topics/VersionTrackingPlugin/images/accepted_warning.png||GHIDRA||reviewed||END|
src/main/help/help/topics/VersionTrackingPlugin/images/add.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/help/help/topics/VersionTrackingPlugin/images/application_tile_horizontal.png||FAMFAMFAM Icons - CC 2.5|||fam fam|END|
src/main/help/help/topics/VersionTrackingPlugin/images/asterisk_orange.png||FAMFAMFAM Icons - CC 2.5||||END|
src/main/help/help/topics/VersionTrackingPlugin/images/cache.png||Nuvola Icons - LGPL 2.1|||Nuvola icon set. LGPL 2.1. Copied from nuvola/16x16/cache.png.|END|
@ -94,7 +92,6 @@ src/main/help/help/topics/VersionTrackingPlugin/images/table_go.png||FAMFAMFAM I
src/main/help/help/topics/VersionTrackingPlugin/images/tag_blue.png||FAMFAMFAM Icons - CC 2.5|||fam fam|END|
src/main/help/help/topics/VersionTrackingPlugin/images/tag_blue_delete.png||FAMFAMFAM Icons - CC 2.5|||famfam|END|
src/main/help/help/topics/VersionTrackingPlugin/images/tag_blue_edit.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set - Copied from famfamfam_silk/icons/tag_blue_edit.png|END|
src/main/help/help/topics/VersionTrackingPlugin/images/text_align_justify.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/help/help/topics/VersionTrackingPlugin/images/undo-apply.png||Nuvola Icons - LGPL 2.1|||originally named undo.png|END|
src/main/help/help/topics/VersionTrackingPlugin/images/unknown.gif||GHIDRA||reviewed|Copied from GhidraIcons/unknown.gif|END|
src/main/help/help/topics/VersionTrackingPlugin/images/view-filter.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END|

View file

@ -124,7 +124,7 @@
<h3><a name="Select_Existing_Match"></a>Select Existing Match</h3>
<BLOCKQUOTE>
<p align="left">The
<b>Select Existing Match</b> action (<img src="../images/text_align_justify.png"/>) will
<b>Select Existing Match</b> action (<img src="Icons.MAKE_SELECTION_ICON"/>) will
select the existing match in the matches table. To use this action you must have
one function selected in source table and one function selected in the destination
table. Further, the action will only be enabled if a match exists for the two

View file

@ -319,7 +319,7 @@
<P align="left"><A name="Remove_Match"></A>The <b>Remove Match</b> <IMG src="../images/edit-delete.png" border="0">
action will remove a manually created match from the matches table.</P>
<P align="left"><A name="Make_Selections"></A>The <b>Make Selections</b> <IMG src="../images/text_align_justify.png" border="0">
<P align="left"><A name="Make_Selections"></A>The <b>Make Selections</b> <IMG src="Icons.MAKE_SELECTION_ICON" border="0">
action will create selections in the source and destination tools for all matches selected in the table.</P>

View file

@ -112,7 +112,7 @@
<BLOCKQUOTE>
<H3><A name="Select_Same_Match_In_Version_Tracking_Matches_Table">Select Match in VT
Matches Table</A> <IMG alt="" border="0" src="../images/text_align_justify.png"></H3>
Matches Table</A> <IMG alt="" border="0" src="Icons.MAKE_SELECTION_ICON"></H3>
<BLOCKQUOTE>
<P>As you select various matches in either <B>Related Matches</B> table, the other
@ -128,7 +128,7 @@
<UL>
<LI>Click the toolbar button, <IMG alt="" border="0" src=
"../images/text_align_justify.png">.</LI>
"Icons.MAKE_SELECTION_ICON">.</LI>
<LI>Right-click on a row in the <B>Related Matches</B> table to get a popup menu.
From the popup menu choose <B>Select Match in VT Matches Table</B>.</LI>

View file

@ -113,21 +113,6 @@ public abstract class DockingAction implements DockingActionIf {
return getName() + " (" + getOwner() + ")";
}
@Override
public KeyBindingData getKeyBindingData() {
return keyBindingData;
}
@Override
public KeyBindingData getDefaultKeyBindingData() {
return defaultKeyBindingData;
}
@Override
public KeyStroke getKeyBinding() {
return keyBindingData == null ? null : keyBindingData.getKeyBinding();
}
@Override
public MenuData getMenuBarData() {
return menuBarData;
@ -273,6 +258,40 @@ public abstract class DockingAction implements DockingActionIf {
return menuItem;
}
@Override
public KeyStroke getKeyBinding() {
return keyBindingData == null ? null : keyBindingData.getKeyBinding();
}
@Override
public KeyBindingData getKeyBindingData() {
return keyBindingData;
}
@Override
public KeyBindingData getDefaultKeyBindingData() {
return defaultKeyBindingData;
}
@Override
public void setKeyBindingData(KeyBindingData newKeyBindingData) {
KeyBindingData oldData = keyBindingData;
keyBindingData = KeyBindingData.validateKeyBindingData(newKeyBindingData);
if (defaultKeyBindingData == null) {
defaultKeyBindingData = keyBindingData;
}
firePropertyChanged(KEYBINDING_DATA_PROPERTY, oldData, keyBindingData);
}
@Override
public void setUnvalidatedKeyBindingData(KeyBindingData newKeyBindingData) {
KeyBindingData oldData = keyBindingData;
keyBindingData = newKeyBindingData;
firePropertyChanged(KEYBINDING_DATA_PROPERTY, oldData, keyBindingData);
}
//==================================================================================================
// Non interface methods
//==================================================================================================
@ -315,34 +334,6 @@ public abstract class DockingAction implements DockingActionIf {
firePropertyChanged(TOOLBAR_DATA_PROPERTY, oldData, newToolBarDataCopy);
}
/**
* Sets the {@link 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.
*/
@Override
public void setKeyBindingData(KeyBindingData newKeyBindingData) {
KeyBindingData oldData = keyBindingData;
keyBindingData = KeyBindingData.validateKeyBindingData(newKeyBindingData);
if (defaultKeyBindingData == null) {
defaultKeyBindingData = keyBindingData;
}
firePropertyChanged(KEYBINDING_DATA_PROPERTY, oldData, keyBindingData);
}
/**
* <b>Users creating actions should not call this method, but should instead call
* {@link #setKeyBindingData(KeyBindingData)}.</b>
* @param newKeyBindingData the KeyBindingData to be used to assign this action to a keybinding
*/
@Override
public void setUnvalidatedKeyBindingData(KeyBindingData newKeyBindingData) {
KeyBindingData oldData = keyBindingData;
keyBindingData = newKeyBindingData;
firePropertyChanged(KEYBINDING_DATA_PROPERTY, oldData, keyBindingData);
}
/**
* Creates a reserved keybinding for this action. Reserved keybindings cannot be changed by
* the user and have a special high precedence for being process before other actions. Also,

View file

@ -114,6 +114,9 @@ public interface DockingActionIf extends HelpDescriptor {
/**
* Returns the default {@link KeyBindingData} to be used to assign this action to a
* key binding. The KeyBindingData will be null if the action is not set to have a keyBinding.
* The value of this method is that which is set from a call to
* {@link #setKeyBindingData(KeyBindingData)}.
*
* @return the {@link KeyBindingData} for the action or null if the action does not have a keyBinding.
*/
public KeyBindingData getDefaultKeyBindingData();
@ -264,7 +267,7 @@ public interface DockingActionIf extends HelpDescriptor {
* <p>
* Call this method when you wish to bypass the validation of
* {@link #setKeyBindingData(KeyBindingData)} so that keybindings are set exactly as they
* are given.
* are given (such as when set by the user and not by the programmer).
*
* @param newKeyBindingData the KeyBindingData to be used to assign this action to a keybinding
*/

View file

@ -35,11 +35,11 @@ import utilities.util.reflection.ReflectionUtilities;
*
* <p>Clients should not be using this class directly.
*/
class SharedStubKeyBindingAction extends DockingAction implements OptionsChangeListener {
public class SharedStubKeyBindingAction extends DockingAction implements OptionsChangeListener {
static final String SHARED_OWNER = "Tool";
/*
/**
* We save the client actions for later validate and options updating. We also need the
* default key binding data, which is stored in the value of this map.
*
@ -57,7 +57,7 @@ class SharedStubKeyBindingAction extends DockingAction implements OptionsChangeL
* key binding's action
* @param options the tool's key binding options
*/
public SharedStubKeyBindingAction(String name, ToolOptions options) {
SharedStubKeyBindingAction(String name, ToolOptions options) {
super(name, SHARED_OWNER);
this.keyBindingOptions = options;
@ -71,19 +71,20 @@ class SharedStubKeyBindingAction extends DockingAction implements OptionsChangeL
void addClientAction(DockingActionIf action) {
// 1) Validate new action keystroke against existing actions
KeyStroke validatedKeyStroke = validateActionsHaveTheSameDefaultKeyStroke(action);
KeyStroke defaultKs = validateActionsHaveTheSameDefaultKeyStroke(action);
// 2) Update the given action with the current option value. This allows clients to
// 2) Add the action and the validated keystroke, as this is the default keystroke
clientActions.put(action, defaultKs);
// 3) Update the given action with the current option value. This allows clients to
// add and remove actions after the tool has been initialized.
validatedKeyStroke = updateKeyStrokeFromOptions(validatedKeyStroke);
clientActions.put(action, validatedKeyStroke);
updateActionKeyStrokeFromOptions(action, defaultKs);
}
private KeyStroke validateActionsHaveTheSameDefaultKeyStroke(DockingActionIf newAction) {
// this value may be null
KeyBindingData defaultBinding = newAction.getKeyBindingData();
KeyBindingData defaultBinding = newAction.getDefaultKeyBindingData();
KeyStroke newDefaultKs = getKeyStroke(defaultBinding);
Set<Entry<DockingActionIf, KeyStroke>> entries = clientActions.entrySet();
@ -116,20 +117,31 @@ class SharedStubKeyBindingAction extends DockingAction implements OptionsChangeL
//@formatter:off
String s = "Shared Key Binding Actions have different deafult values. These " +
"must be the same." +
"\n\tAction name: '"+existingAction.getName()+"'" +
"\n\tAction 1: " + existingAction.getInceptionInformation() +
"\n\t\tKey Binding: " + existingDefaultKs +
"\n\tAction 2: " + newAction.getInceptionInformation() +
"\n\t\tKey Binding: " + newAction.getKeyBinding() +
"\nUsing the " +
"first value set - " + existingDefaultKs
;
"first value set - " + existingDefaultKs;
//@formatter:on
Msg.warn(this, s, ReflectionUtilities.createJavaFilteredThrowable());
}
private KeyStroke updateKeyStrokeFromOptions(KeyStroke validatedKeyStroke) {
return keyBindingOptions.getKeyStroke(getFullName(), validatedKeyStroke);
private void updateActionKeyStrokeFromOptions(DockingActionIf action, KeyStroke defaultKs) {
KeyStroke optionsKs = getKeyStrokeFromOptions(defaultKs);
if (!Objects.equals(defaultKs, optionsKs)) {
// we use the 'unvalidated' call since this value is provided by the user--we assume
// that user input is correct; we only validate programmer input
action.setUnvalidatedKeyBindingData(new KeyBindingData(optionsKs));
}
}
private KeyStroke getKeyStrokeFromOptions(KeyStroke validatedKeyStroke) {
KeyStroke ks = keyBindingOptions.getKeyStroke(getFullName(), validatedKeyStroke);
return ks;
}
private KeyStroke getKeyStroke(KeyBindingData data) {
@ -149,9 +161,8 @@ class SharedStubKeyBindingAction extends DockingAction implements OptionsChangeL
KeyStroke newKs = (KeyStroke) newValue;
for (DockingActionIf action : clientActions.keySet()) {
// Note: update this to say why we are using the 'unvalidated' call instead of the
// setKeyBindingData() call
// we use the 'unvalidated' call since this value is provided by the user--we assume
// that user input is correct; we only validate programmer input
action.setUnvalidatedKeyBindingData(new KeyBindingData(newKs));
}
}

View file

@ -208,7 +208,33 @@ public class SharedKeybindingDockingActionTest extends AbstractDockingTest {
// verify the newly added keybinding gets the newly changed option
tool.addAction(action2);
assertKeyBinding(action2, newKs);
assertNoLoggedMessages();
}
@Test
public void testSharedKeyBinding_AddActionAfterOptionHasChanged_RepeatAddRemove() {
TestAction action1 = new TestAction(OWNER_1, DEFAULT_KS_1);
TestAction action2 = new TestAction(OWNER_2, DEFAULT_KS_1);
tool.addAction(action1);
KeyStroke newKs = KeyStroke.getKeyStroke(KeyEvent.VK_Z, 0);
setSharedKeyBinding(newKs);
assertKeyBinding(action1, newKs);
// verify the newly added keybinding gets the newly changed option
tool.addAction(action2);
assertKeyBinding(action2, newKs);
assertNoLoggedMessages();
tool.removeAction(action2);
assertActionNotInTool(action2);
tool.addAction(action2);
assertKeyBinding(action2, newKs);
assertNoLoggedMessages();
}
@Test

View file

@ -61,6 +61,7 @@ src/main/resources/images/redDragon24.png||GHIDRA||||END|
src/main/resources/images/redDragon32.png||GHIDRA||||END|
src/main/resources/images/reload3.png||Crystal Clear Icons - LGPL 2.1||||END|
src/main/resources/images/software-update-urgent.png||Tango Icons - Public Domain|||tango icon set|END|
src/main/resources/images/text_align_justify.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/resources/images/video-x-generic16.png||Tango Icons - Public Domain|||tango|END|
src/main/resources/log4j-appender-console-with-links.xml||GHIDRA||||END|
src/main/resources/log4j-appender-console.xml||GHIDRA||||END|

View file

@ -79,6 +79,9 @@ public class Icons {
public static final ImageIcon SAVE_AS = ResourceManager.getImageIcon(
new DotDotDotIcon(ResourceManager.loadImage("images/Disk.png")));
public static final ImageIcon MAKE_SELECTION_ICON =
ResourceManager.getImageIcon(ResourceManager.loadImage("images/text_align_justify.png"));
// Not necessarily re-usable, but this is needed for the help system; these should
// probably be moved to the client that uses them, while updating the
// help system to use them there.

View file

@ -1,109 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.framework.options;
import javax.swing.KeyStroke;
import docking.ActionContext;
import docking.DockingWindowManager;
import docking.action.DockingAction;
import docking.action.KeyBindingData;
/**
* A dummy action that allows key bindings to be edited through the key bindings options
* <b>without</b> requiring the user to implement a system action that will be added to the tool.
* Without this class the only editable tool key bindings are those that have corresponding
* {@link DockingAction}s added to the tool.
* <p>
* A typical usage of this class: Suppose a plugin has an action that it adds to the tool,
* which is logically the same action (with the same name) that a second plugin adds to the tool.
* Both of these actions are
* logically equivalent and share the same default key binding. Since these actions are
* logically the same, then they should share the same key binding and only have one entry
* in the key binding options, instead of two. This class enables both actions to have key
* bindings assigned via one dummy action. <b>To do this each of the above primary actions will set
* themselves to not manage key bindings</b>, so they don't appear in the key bindings options,
* and will then create an instance of this class and register it with the tool. Then, each of
* those primary actions will listen for options changes to know when the user has edited
* the key binding of the dummy action. The following snippet is an example of this usage,
* taken from the constructor of a DockingAction:
* <pre>
* // setup key binding management
* setKeyBindingManaged( false ); // our dummy will handle this task, not us
* KeyStroke keyStroke = ...;
* PluginTool tool = plugin.getTool();
* tool.addAction( new DummyKeyBindingsOptionsAction( ACTION_NAME, keyStroke ) );
*
* // setup options to know when the dummy key binding is changed
* Options options = tool.getOptions(ToolConstants.KEY_BINDINGS);
* KeyStroke optionsKeyStroke = options.getKeyStroke( "Tool", ACTION_NAME, keyStroke );
*
* if (!keyStroke(optionsKeyStroke)) {
* // user-defined keystroke
* setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
* }
* else {
* setKeyBindingData(new KeyBindingData(keyStroke));
* }
*
* options.addOptionsChangeListener( ... );
* </pre>
*
* And for changes to the options keybinding value:
* <pre>
* public void optionsChanged(Options options, String name, Object oldValue, Object newValue) {
* KeyStroke keyStroke = (KeyStroke) newValue;
* if (name.startsWith(KEY_BINDING_NAME)) {
* setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
* }
* }
* </pre>
*/
public class DummyKeyBindingsOptionsAction extends DockingAction {
public static final String DEFAULT_OWNER = "Tool";
/**
* Creates a new dummy action by the given name and default keystroke value.
* @param name The name of the action--this will be displayed in the options as the name of
* key binding's action.
* @param defaultKeyStroke The default keystroke value for this action. This value may be null.
*/
public DummyKeyBindingsOptionsAction(String name, KeyStroke defaultKeyStroke) {
super(name, DEFAULT_OWNER);
if (defaultKeyStroke != null) {
setKeyBindingData(new KeyBindingData(defaultKeyStroke));
}
// Dummy keybinding actions don't have help--the real action does
DockingWindowManager.getHelpService().excludeFromHelp(this);
}
@Override
public void actionPerformed(ActionContext context) {
// no-op; this is a dummy!
}
@Override
public boolean isAddToPopup(ActionContext context) {
return false;
}
@Override
public boolean isEnabledForContext(ActionContext context) {
return false;
}
}

View file

@ -176,7 +176,7 @@ public class KeyBindingsPanel extends JPanel {
List<DockingActionIf> actions = tool.getAllActions();
for (DockingActionIf action : actions) {
if (!action.isKeyBindingManaged()) {
if (isIgnored(action)) {
continue;
}
@ -206,6 +206,12 @@ public class KeyBindingsPanel extends JPanel {
tableModel.fireTableDataChanged();
}
private boolean isIgnored(DockingActionIf action) {
// not keybinding managed; a shared keybinding implies that this action should not be in
// the UI, as there will be a single proxy in place of all actions sharing that binding
return !action.isKeyBindingManaged() || action.usesSharedKeyBinding();
}
/**
* Create the components in this panel.
*/