GT-2229: added action to issue a goto when new function selected

GT-2229: added support for multiple programs
GT-2229: Updated icons/help/screenshots for function new comparison
features
GT-2229: minor fixes after code review
GT-2229: minor code review fix
This commit is contained in:
adamopolous 2020-01-17 14:43:51 -05:00
parent b9531416c0
commit cc44d0c952
10 changed files with 230 additions and 10 deletions

View file

@ -377,6 +377,7 @@ src/main/help/help/topics/FunctionComparison/images/ListingCodeComparisonOptions
src/main/help/help/topics/FunctionComparison/images/MultiFunctionComparisonWindow.png||GHIDRA||||END|
src/main/help/help/topics/FunctionComparison/images/NavNextIcon.png||GHIDRA||||END|
src/main/help/help/topics/FunctionComparison/images/NavPreviousIcon.png||GHIDRA||||END|
src/main/help/help/topics/FunctionComparison/images/NavSelectedIcon.png||GHIDRA||||END|
src/main/help/help/topics/FunctionComparison/images/RemoveFromComparisonIcon.png||GHIDRA||||END|
src/main/help/help/topics/FunctionComparison/images/binaryData.gif||GHIDRA||||END|
src/main/help/help/topics/FunctionComparison/images/class.png||GHIDRA||||END|

View file

@ -428,16 +428,22 @@
sides of the comparison window.
</p>
<h3><IMG src="images/RemoveFromComparisonIcon.png" border="0"> <a name="Remove_From_Comparison"></a>Remove Function From Comparison</h3>
<h3><IMG src="images/RemoveFromComparisonIcon.png" border="0"> <a name="Remove_From_Comparison"></a>&nbsp;Remove Function From Comparison</h3>
<p>Removes the function in the focused panel from the comparison. This
will remove the function from both the source and target selection pulldowns.</p>
<h3><IMG src="images/NavNextIcon.png" border="0"> <a name="Navigate_Next"></a>Go To Next Function</h3>
<h3><IMG src="images/NavNextIcon.png" border="0"> <a name="Navigate_Next"></a>&nbsp;Go To Next Function</h3>
<p>Navigates to the next available function in the selection pulldown</p>
<h3><IMG src="images/NavPreviousIcon.png" border="0"> <a name="Navigate_Previous"></a>Go To Previous Function</h3>
<h3><IMG src="images/NavPreviousIcon.png" border="0"> <a name="Navigate_Previous"></a>&nbsp;Go To Previous Function</h3>
<p>Navigates to the previous available function in the selection pulldown</p>
<h3><IMG src="Icons.NAVIGATE_ON_INCOMING_EVENT_ICON" border="0"> <a name="Navigate_To_Function"></a>&nbsp;Navigate To Selected Function</h3>
<p>When toggled <b>on</b>, the function comparison panels become navigable,
meaning a mouse click on the panel or change in the function being viewed
will result in a GoTo event being generated. This allows other panels
(eg: the listing) to update their views accordingly.</p>
<p><IMG src="../../shared/note.png"> The Remove and Go To actions described
above will operate on the comparison panel that has focus, identified by the
pink border.</p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 99 KiB

Before After
Before After

View file

@ -116,6 +116,24 @@ public class MultiFunctionComparisonPanel extends FunctionComparisonPanel {
return sourceHasFocus ? sourceFunctionsCB : targetFunctionsCB;
}
/**
* Returns the source combo box
*
* @return the source combo box
*/
public JComboBox<Function> getSourceComponent() {
return sourceFunctionsCB;
}
/**
* Returns the target combo box
*
* @return the target combo box
*/
public JComboBox<Function> getTargetComponent() {
return targetFunctionsCB;
}
/**
* Clears out and reloads the source function list. Any selection currently
* made on the list will be reestablished.

View file

@ -56,11 +56,13 @@ public class MultiFunctionComparisonProvider extends FunctionComparisonProvider
DockingAction previousFunctionAction = new PreviousFunctionAction(this);
DockingAction removeFunctionsAction = new RemoveFunctionsAction(this);
DockingAction openFunctionTableAction = getOpenFunctionTableAction();
DockingAction navigateToAction = new NavigateToFunctionAction(this);
addLocalAction(nextFunctionAction);
addLocalAction(previousFunctionAction);
addLocalAction(removeFunctionsAction);
addLocalAction(openFunctionTableAction);
addLocalAction(navigateToAction);
}
/**

View file

@ -0,0 +1,187 @@
/* ###
* 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.plugin.core.functioncompare.actions;
import java.awt.event.*;
import java.util.List;
import javax.swing.ImageIcon;
import docking.action.ToggleDockingAction;
import docking.action.ToolBarData;
import docking.widgets.fieldpanel.internal.FieldPanelCoordinator;
import ghidra.app.plugin.core.functioncompare.*;
import ghidra.app.services.GoToService;
import ghidra.app.util.viewer.util.CodeComparisonPanel;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Function;
import ghidra.util.HTMLUtilities;
import ghidra.util.HelpLocation;
import resources.Icons;
/**
* Toggle Action designed to be used with a {@link MultiFunctionComparisonProvider}.
* When toggled on, a GoTo event will be issued for the function displayed in
* the comparison panel after the following events:
* <ul>
* <li>focus is gained on either the left or right panels</li>
* <li>the function displayed in a comparison panel changes</li>
* </ul>
* Note that the GoTo will only operate on the comparison panel that
* <b>has focus</b>. eg: If the left panel has focus but the user changes the
* function being viewed in the right panel, no GoTo will be issued.
*/
public class NavigateToFunctionAction extends ToggleDockingAction {
private GoToService goToService;
private static final ImageIcon NAV_FUNCTION_ICON = Icons.NAVIGATE_ON_INCOMING_EVENT_ICON;
/**
* Constructor
*
* @param provider the function comparison provider containing this action
*/
public NavigateToFunctionAction(MultiFunctionComparisonProvider provider) {
super("Navigate To Selected Function", provider.getName());
goToService = provider.getTool().getService(GoToService.class);
setEnabled(true);
setSelected(false);
ToolBarData newToolBarData = new ToolBarData(NAV_FUNCTION_ICON);
setToolBarData(newToolBarData);
setDescription(
HTMLUtilities.toHTML("Toggle <b>On</b> means to navigate to whatever " +
"function is selected in the comparison panel, when focus changes or" +
"a new function is selected."));
setHelpLocation(
new HelpLocation(MultiFunctionComparisonPanel.HELP_TOPIC, "Navigate_To_Function"));
addFocusListeners(provider);
addChangeListeners(provider);
}
/**
* Adds a listener to each of the function selection widgets in the
* comparison provider. When a new function is selected, a GoTo event
* is generated for the entry point of the function.
*
* @param provider the function comparison provider
*/
private void addChangeListeners(MultiFunctionComparisonProvider provider) {
MultiFunctionComparisonPanel panel = (MultiFunctionComparisonPanel) provider.getComponent();
panel.getSourceComponent().addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() != ItemEvent.SELECTED) {
return;
}
if (panel.getFocusedComponent() != panel.getSourceComponent()) {
return;
}
if (NavigateToFunctionAction.this.isSelected()) {
Function f = (Function) panel.getSourceComponent().getSelectedItem();
goToService.goTo(f.getEntryPoint(), f.getProgram());
}
}
});
panel.getTargetComponent().addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() != ItemEvent.SELECTED) {
return;
}
if (panel.getFocusedComponent() != panel.getTargetComponent()) {
return;
}
if (NavigateToFunctionAction.this.isSelected()) {
Function f = (Function) panel.getTargetComponent().getSelectedItem();
goToService.goTo(f.getEntryPoint(), f.getProgram());
}
}
});
}
/**
* Adds a listener to each panel in the function comparison provider,
* triggered when focus has been changed. If focused is gained in a panel,
* a GoTo event is issued containing the function start address.
*
* @param provider the function comparison provider
*/
private void addFocusListeners(MultiFunctionComparisonProvider provider) {
FunctionComparisonPanel mainPanel = provider.getComponent();
List<CodeComparisonPanel<? extends FieldPanelCoordinator>> panels =
mainPanel.getComparisonPanels();
for (CodeComparisonPanel<? extends FieldPanelCoordinator> panel : panels) {
panel.getRightFieldPanel().addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
if (NavigateToFunctionAction.this.isSelected()) {
Address addr = null;
if (panel.getRightFunction() != null) {
addr = panel.getRightFunction().getBody().getMinAddress();
}
else if (panel.getRightData() != null) {
addr = panel.getRightData().getAddress();
}
else if (panel.getRightAddresses() != null) {
addr = panel.getRightAddresses().getMinAddress();
}
goToService.goTo(addr, panel.getRightProgram());
}
}
});
panel.getRightFieldPanel().addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
if (NavigateToFunctionAction.this.isSelected()) {
Address addr = null;
if (panel.getLeftFunction() != null) {
addr = panel.getLeftFunction().getBody().getMinAddress();
}
else if (panel.getLeftData() != null) {
addr = panel.getLeftData().getAddress();
}
else if (panel.getLeftAddresses() != null) {
addr = panel.getLeftAddresses().getMinAddress();
}
goToService.goTo(addr, panel.getLeftProgram());
}
}
});
}
}
}

View file

@ -2713,12 +2713,12 @@ public class ListingCodeComparisonPanel
}
@Override
protected FieldPanel getLeftFieldPanel() {
public FieldPanel getLeftFieldPanel() {
return getLeftPanel().getFieldPanel();
}
@Override
protected FieldPanel getRightFieldPanel() {
public FieldPanel getRightFieldPanel() {
return getRightPanel().getFieldPanel();
}

View file

@ -326,13 +326,13 @@ public abstract class CodeComparisonPanel<T extends FieldPanelCoordinator> exten
* Gets the left field panel for this CodeComparisonPanel.
* @return the left FieldPanel.
*/
protected abstract FieldPanel getLeftFieldPanel();
public abstract FieldPanel getLeftFieldPanel();
/**
* Gets the right field panel for this CodeComparisonPanel.
* @return the right FieldPanel.
*/
protected abstract FieldPanel getRightFieldPanel();
public abstract FieldPanel getRightFieldPanel();
/**
* Determines if the layouts of the views are synchronized with respect to scrolling and

View file

@ -15,7 +15,7 @@
*/
package help.screenshot;
import static org.junit.Assert.*;
import static org.junit.Assert.assertNotNull;
import java.awt.*;
import java.awt.geom.GeneralPath;
@ -604,6 +604,12 @@ public abstract class AbstractScreenShotGenerator extends AbstractGhidraHeadedIn
runSwing(() -> {
ImageIcon imageIcon = ResourceManager.getImageIcon(icon);
image = imageIcon.getImage();
// The image returned here must be a BufferedImage, so create one
// if not. It may be a ToolkitImage (eg: if the icon in question
// is retrieved from Icons.java), which would fail on a cast to
// BufferedImage during the save operation.
image = ImageUtils.getBufferedImage(image);
});
}

View file

@ -688,12 +688,12 @@ public abstract class DecompilerCodeComparisonPanel<T extends DualDecompilerFiel
}
@Override
protected FieldPanel getLeftFieldPanel() {
public FieldPanel getLeftFieldPanel() {
return getLeftDecompilerPanel().getFieldPanel();
}
@Override
protected FieldPanel getRightFieldPanel() {
public FieldPanel getRightFieldPanel() {
return getRightDecompilerPanel().getFieldPanel();
}