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/MultiFunctionComparisonWindow.png||GHIDRA||||END|
src/main/help/help/topics/FunctionComparison/images/NavNextIcon.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/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/RemoveFromComparisonIcon.png||GHIDRA||||END|
src/main/help/help/topics/FunctionComparison/images/binaryData.gif||GHIDRA||||END| src/main/help/help/topics/FunctionComparison/images/binaryData.gif||GHIDRA||||END|
src/main/help/help/topics/FunctionComparison/images/class.png||GHIDRA||||END| src/main/help/help/topics/FunctionComparison/images/class.png||GHIDRA||||END|

View file

@ -428,16 +428,22 @@
sides of the comparison window. sides of the comparison window.
</p> </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 <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> 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> <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> <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 <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 above will operate on the comparison panel that has focus, identified by the
pink border.</p> 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; 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 * Clears out and reloads the source function list. Any selection currently
* made on the list will be reestablished. * made on the list will be reestablished.

View file

@ -56,11 +56,13 @@ public class MultiFunctionComparisonProvider extends FunctionComparisonProvider
DockingAction previousFunctionAction = new PreviousFunctionAction(this); DockingAction previousFunctionAction = new PreviousFunctionAction(this);
DockingAction removeFunctionsAction = new RemoveFunctionsAction(this); DockingAction removeFunctionsAction = new RemoveFunctionsAction(this);
DockingAction openFunctionTableAction = getOpenFunctionTableAction(); DockingAction openFunctionTableAction = getOpenFunctionTableAction();
DockingAction navigateToAction = new NavigateToFunctionAction(this);
addLocalAction(nextFunctionAction); addLocalAction(nextFunctionAction);
addLocalAction(previousFunctionAction); addLocalAction(previousFunctionAction);
addLocalAction(removeFunctionsAction); addLocalAction(removeFunctionsAction);
addLocalAction(openFunctionTableAction); 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 @Override
protected FieldPanel getLeftFieldPanel() { public FieldPanel getLeftFieldPanel() {
return getLeftPanel().getFieldPanel(); return getLeftPanel().getFieldPanel();
} }
@Override @Override
protected FieldPanel getRightFieldPanel() { public FieldPanel getRightFieldPanel() {
return getRightPanel().getFieldPanel(); 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. * Gets the left field panel for this CodeComparisonPanel.
* @return the left FieldPanel. * @return the left FieldPanel.
*/ */
protected abstract FieldPanel getLeftFieldPanel(); public abstract FieldPanel getLeftFieldPanel();
/** /**
* Gets the right field panel for this CodeComparisonPanel. * Gets the right field panel for this CodeComparisonPanel.
* @return the right FieldPanel. * @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 * Determines if the layouts of the views are synchronized with respect to scrolling and

View file

@ -15,7 +15,7 @@
*/ */
package help.screenshot; package help.screenshot;
import static org.junit.Assert.*; import static org.junit.Assert.assertNotNull;
import java.awt.*; import java.awt.*;
import java.awt.geom.GeneralPath; import java.awt.geom.GeneralPath;
@ -604,6 +604,12 @@ public abstract class AbstractScreenShotGenerator extends AbstractGhidraHeadedIn
runSwing(() -> { runSwing(() -> {
ImageIcon imageIcon = ResourceManager.getImageIcon(icon); ImageIcon imageIcon = ResourceManager.getImageIcon(icon);
image = imageIcon.getImage(); 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 @Override
protected FieldPanel getLeftFieldPanel() { public FieldPanel getLeftFieldPanel() {
return getLeftDecompilerPanel().getFieldPanel(); return getLeftDecompilerPanel().getFieldPanel();
} }
@Override @Override
protected FieldPanel getRightFieldPanel() { public FieldPanel getRightFieldPanel() {
return getRightDecompilerPanel().getFieldPanel(); return getRightDecompilerPanel().getFieldPanel();
} }