diff --git a/Ghidra/Features/Base/src/main/help/help/topics/FunctionWindowPlugin/function_window.htm b/Ghidra/Features/Base/src/main/help/help/topics/FunctionWindowPlugin/function_window.htm index 8062da9017..38b521876c 100644 --- a/Ghidra/Features/Base/src/main/help/help/topics/FunctionWindowPlugin/function_window.htm +++ b/Ghidra/Features/Base/src/main/help/help/topics/FunctionWindowPlugin/function_window.htm @@ -28,17 +28,27 @@ function's signature. Click on the top of a column to sort the list by that col
Click on a function to navigate to that function in the Code Browser.
--+ +The Functions window has an icon (
-) -on the tool bar to make a selection in the Code Browser. To make a selection,
-
-- Select the functions in the Functions window.
-- Right mouse click and select the
-Make - Selection option, OR select the
button on - the tool bar.
++ +When selected, the Function Table will select the row in the table that corresponds to the + symbol selected in the Listing. +
+
+The Functions window has an icon (
+) + on the tool bar to make a selection in the Code Browser. To make a selection,
+
+- Select the functions in the Functions window.
+- Right mouse click and select the
+Make + Selection option, OR select the
button on + the tool bar.
diff --git a/Ghidra/Features/Base/src/main/help/help/topics/FunctionWindowPlugin/images/FunctionWindow.png b/Ghidra/Features/Base/src/main/help/help/topics/FunctionWindowPlugin/images/FunctionWindow.png index b66a38580e..7de7fe11d0 100644 Binary files a/Ghidra/Features/Base/src/main/help/help/topics/FunctionWindowPlugin/images/FunctionWindow.png and b/Ghidra/Features/Base/src/main/help/help/topics/FunctionWindowPlugin/images/FunctionWindow.png differ diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functionwindow/FunctionWindowPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functionwindow/FunctionWindowPlugin.java index ac975645b6..99bab92395 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functionwindow/FunctionWindowPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functionwindow/FunctionWindowPlugin.java @@ -4,9 +4,9 @@ * 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. @@ -25,6 +25,7 @@ import ghidra.app.plugin.ProgramPlugin; import ghidra.app.services.FunctionComparisonService; import ghidra.framework.model.DomainObjectListener; import ghidra.framework.model.DomainObjectListenerBuilder; +import ghidra.framework.options.SaveState; import ghidra.framework.plugintool.PluginInfo; import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.util.PluginStatus; @@ -33,6 +34,7 @@ import ghidra.program.model.listing.Function; import ghidra.program.model.listing.Program; import ghidra.program.model.symbol.Symbol; import ghidra.program.util.ProgramChangeRecord; +import ghidra.program.util.ProgramLocation; import ghidra.util.task.SwingUpdateManager; //@formatter:off @@ -98,6 +100,16 @@ public class FunctionWindowPlugin extends ProgramPlugin { } } + @Override + public void readConfigState(SaveState saveState) { + provider.readConfigState(saveState); + } + + @Override + public void writeConfigState(SaveState saveState) { + provider.writeConfigState(saveState); + } + private DomainObjectListener createDomainObjectListener() { // @formatter:off return new DomainObjectListenerBuilder(this) @@ -161,6 +173,11 @@ public class FunctionWindowPlugin extends ProgramPlugin { provider.programClosed(); } + @Override + protected void locationChanged(ProgramLocation loc) { + provider.locationChanged(loc); + } + Program getProgram() { return currentProgram; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functionwindow/FunctionWindowProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functionwindow/FunctionWindowProvider.java index d81c440e4d..c5a41b2f7b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functionwindow/FunctionWindowProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functionwindow/FunctionWindowProvider.java @@ -25,12 +25,13 @@ import javax.swing.table.*; import docking.ActionContext; import docking.DefaultActionContext; -import docking.action.DockingAction; +import docking.action.*; import docking.action.builder.ActionBuilder; import generic.theme.GIcon; import ghidra.app.context.FunctionSupplierContext; import ghidra.app.context.ProgramLocationSupplierContext; import ghidra.app.services.FunctionComparisonService; +import ghidra.framework.options.SaveState; import ghidra.framework.plugintool.ComponentProviderAdapter; import ghidra.program.model.address.Address; import ghidra.program.model.listing.*; @@ -39,6 +40,7 @@ import ghidra.program.util.ProgramLocation; import ghidra.util.HelpLocation; import ghidra.util.table.*; import ghidra.util.table.actions.MakeProgramSelectionAction; +import resources.Icons; /** * Provider that displays all functions in the selected program @@ -48,6 +50,9 @@ public class FunctionWindowProvider extends ComponentProviderAdapter { public static final Icon ICON = new GIcon("icon.plugin.functionwindow.provider"); private static final Icon COMPARISON_ICON = new GIcon("icon.plugin.functioncompare.new"); + private static final String NAVIGATE_ON_INCOMING_EVENT_KEY = "NAVIGATE_ON_INCOMING_EVENT"; + private static final String NAVIGATE_ON_OUTGOING_EVENT_KEY = "NAVIGATE_ON_OUTGOING_EVENT"; + private FunctionWindowPlugin plugin; private GhidraTable functionTable; private FunctionTableModel functionModel; @@ -57,6 +62,8 @@ public class FunctionWindowProvider extends ComponentProviderAdapter { private GhidraThreadedTablePanelthreadedTablePanel; private DockingAction compareAction; + private ToggleDockingAction navigateIncomingAction; + private SelectionNavigationAction navigateOutgoingAction; /** * Constructor @@ -76,7 +83,22 @@ public class FunctionWindowProvider extends ComponentProviderAdapter { } private void createActions() { - addLocalAction(new SelectionNavigationAction(plugin.getName(), getTable())); + String navGroup = "A"; + + navigateIncomingAction = + new ToggleDockingAction("Navigate on Incoming Location Changes", plugin.getName(), + KeyBindingType.SHARED) { + // stub + }; + navigateIncomingAction + .setToolBarData(new ToolBarData(Icons.NAVIGATE_ON_INCOMING_EVENT_ICON, navGroup)); + addLocalAction(navigateIncomingAction); + + navigateOutgoingAction = new SelectionNavigationAction(plugin.getName(), getTable()); + ToolBarData tbData = navigateOutgoingAction.getToolBarData(); + tbData.setToolBarGroup(navGroup); + addLocalAction(navigateOutgoingAction); + addLocalAction(new MakeProgramSelectionAction(plugin, getTable())); } @@ -109,6 +131,20 @@ public class FunctionWindowProvider extends ComponentProviderAdapter { service.createComparison(functions); } + void readConfigState(SaveState saveState) { + boolean navigateIncoming = saveState.getBoolean(NAVIGATE_ON_INCOMING_EVENT_KEY, false); + boolean navigateOutgoing = saveState.getBoolean(NAVIGATE_ON_OUTGOING_EVENT_KEY, false); + navigateIncomingAction.setSelected(navigateIncoming); + navigateOutgoingAction.setSelected(navigateOutgoing); + } + + void writeConfigState(SaveState saveState) { + boolean navigateIncoming = navigateIncomingAction.isSelected(); + boolean navigateOutgoing = navigateOutgoingAction.isSelected(); + saveState.putBoolean(NAVIGATE_ON_INCOMING_EVENT_KEY, navigateIncoming); + saveState.putBoolean(NAVIGATE_ON_OUTGOING_EVENT_KEY, navigateOutgoing); + } + @Override public void componentHidden() { functionModel.reload(null); @@ -217,6 +253,27 @@ public class FunctionWindowProvider extends ComponentProviderAdapter { } } + public void locationChanged(ProgramLocation loc) { + if (!navigateIncomingAction.isSelected()) { + return; + } + + if (loc == null) { + return; + } + + Program p = loc.getProgram(); + FunctionManager fm = p.getFunctionManager(); + Address address = loc.getAddress(); + Function function = fm.getFunctionContaining(address); + if (function == null) { + return; + } + + FunctionRowObject ro = new FunctionRowObject(function); + tableFilterPanel.setSelectedItem(ro); + } + /** * Gathers this function and any functions that thunk it * @param f the function @@ -311,4 +368,5 @@ public class FunctionWindowProvider extends ComponentProviderAdapter { return s.getProgramLocation(); } } + }