Merge remote-tracking branch

'origin/GP-3683-dragonmacher-function-tags-nav-2' into patch
(Closes #5613)
This commit is contained in:
Ryan Kurtz 2023-08-04 13:15:54 -04:00
commit d39caa5f44
3 changed files with 45 additions and 77 deletions

View File

@ -26,21 +26,21 @@ import ghidra.program.util.ProgramLocation;
import ghidra.util.HelpLocation; import ghidra.util.HelpLocation;
/** /**
* Presents the user with a {@link ComponentProvider} showing all function tags available, * Presents the user with a {@link ComponentProvider} showing all function tags available,along with
* along with all those currently assigned to the selected function. * all those currently assigned to the selected function.
* <p>
* Users may select, deselect, edit or delete tags. * Users may select, deselect, edit or delete tags.
*/ */
public class EditFunctionTagsAction extends ListingContextAction { public class EditFunctionTagsAction extends ListingContextAction {
private FunctionTagPlugin plugin; private FunctionTagPlugin plugin;
// Menu option that will show up when right-clicking on a function in // Menu option that will show up when right-clicking on a function in the listing
// the listing.
private final String MENU_LABEL = "Edit Tags..."; private final String MENU_LABEL = "Edit Tags...";
/** /**
* Constructor. * Constructor.
* *
* @param name the name for this action. * @param name the name for this action.
* @param plugin the plugin this action is associated with. * @param plugin the plugin this action is associated with.
*/ */
@ -57,10 +57,6 @@ public class EditFunctionTagsAction extends ListingContextAction {
setEnabled(true); setEnabled(true);
} }
/******************************************************************************
* PUBLIC METHODS
******************************************************************************/
@Override @Override
public void actionPerformed(ListingActionContext context) { public void actionPerformed(ListingActionContext context) {
@ -74,25 +70,22 @@ public class EditFunctionTagsAction extends ListingContextAction {
showProvider(context); showProvider(context);
} }
/******************************************************************************
* PROTECTED METHODS
******************************************************************************/
/** /**
* Overridden to only allow this menu option when clicking in a function. * Overridden to only allow this menu option when clicking in a function.
* Note that we do not allow external functions to have tags. * Note that we do not allow external functions to have tags.
* *
* @param context the listing context * @param context the listing context
* @return * @return true if enabled
*/ */
@Override @Override
protected boolean isEnabledForContext(ListingActionContext context) { protected boolean isEnabledForContext(ListingActionContext context) {
if (context.hasSelection() || context.getAddress() == null) { Address address = context.getAddress();
if (context.hasSelection() || address == null) {
return false; return false;
} }
if (context.getLocation().getAddress().isExternalAddress()) { if (address.isExternalAddress()) {
return false; return false;
} }
@ -104,12 +97,9 @@ public class EditFunctionTagsAction extends ListingContextAction {
return !funcAddress.isExternalAddress(); return !funcAddress.isExternalAddress();
} }
/******************************************************************************
* PRIVATE METHODS
******************************************************************************/
/** /**
* Retrieves the address of the function associated with the given program location. * Retrieves the address of the function associated with the given program location.
* *
* @param loc the program location * @param loc the program location
* @return the entry point of the function, or null if not valid * @return the entry point of the function, or null if not valid
*/ */
@ -126,7 +116,7 @@ public class EditFunctionTagsAction extends ListingContextAction {
/** /**
* Displays the provider. * Displays the provider.
* *
* @param context the listing context * @param context the listing context
*/ */
private void showProvider(ListingActionContext context) { private void showProvider(ListingActionContext context) {

View File

@ -26,9 +26,9 @@ import ghidra.program.util.ProgramLocation;
/** /**
* Plugin for managing function tags. This works with the associated * Plugin for managing function tags. This works with the associated
* {@link FunctionTagProvider} to allow users to view and * {@link FunctionTagProvider} to allow users to view and
* edit function tags both globally and for individual functions. * edit function tags both globally and for individual functions.
* *
*/ */
//@formatter:off //@formatter:off
@PluginInfo( @PluginInfo(
@ -51,17 +51,11 @@ public class FunctionTagPlugin extends ProgramPlugin {
public FunctionTagPlugin(PluginTool tool) { public FunctionTagPlugin(PluginTool tool) {
super(tool); super(tool);
provider = new FunctionTagProvider(this, getCurrentProgram());
createActions();
} }
/******************************************************************************
* PUBLIC METHODS
******************************************************************************/
/** /**
* Returns the component provider for this plugin * Returns the component provider for this plugin
* *
* @return the component provider * @return the component provider
*/ */
public FunctionTagProvider getProvider() { public FunctionTagProvider getProvider() {
@ -71,11 +65,10 @@ public class FunctionTagPlugin extends ProgramPlugin {
@Override @Override
public void init() { public void init() {
super.init(); super.init();
}
/****************************************************************************** provider = new FunctionTagProvider(this, getCurrentProgram());
* PROTECTED METHODS createActions();
******************************************************************************/ }
@Override @Override
protected void programDeactivated(Program program) { protected void programDeactivated(Program program) {
@ -92,10 +85,6 @@ public class FunctionTagPlugin extends ProgramPlugin {
provider.locationChanged(loc); provider.locationChanged(loc);
} }
/******************************************************************************
* PRIVATE METHODS
******************************************************************************/
private void createActions() { private void createActions() {
editFunctionTagsAction = new EditFunctionTagsAction("Edit Function Tags", this); editFunctionTagsAction = new EditFunctionTagsAction("Edit Function Tags", this);
tool.addAction(editFunctionTagsAction); tool.addAction(editFunctionTagsAction);

View File

@ -50,14 +50,13 @@ import resources.ResourceManager;
* <LI>Edit tags (both name and comment)</LI> * <LI>Edit tags (both name and comment)</LI>
* <LI>Delete tags</LI> * <LI>Delete tags</LI>
* <LI>Assign tags to the currently selected function</LI> * <LI>Assign tags to the currently selected function</LI>
* <LI>Remove tags from the currently selected function</LI> * <LI>Remove tags from the currently selected function</LI>
* </UL> * </UL>
* This provider can be shown by right-clicking on a function and selecting the * This provider can be shown by right-clicking on a function and selecting the
* "Edit Tags" option, or by selecting the "Edit Function Tags" option from the * "Edit Tags" option, or by selecting the "Edit Function Tags" option from the
* "Window" menu. * "Window" menu.
*/ */
public class FunctionTagProvider extends ComponentProviderAdapter public class FunctionTagProvider extends ComponentProviderAdapter implements DomainObjectListener {
implements DomainObjectListener {
private SourceTagsPanel sourcePanel; private SourceTagsPanel sourcePanel;
private TargetTagsPanel targetPanel; private TargetTagsPanel targetPanel;
@ -75,37 +74,37 @@ public class FunctionTagProvider extends ComponentProviderAdapter
private SwingUpdateManager updater = new SwingUpdateManager(this::doUpdate); private SwingUpdateManager updater = new SwingUpdateManager(this::doUpdate);
// The current program location selected in the listing. // The current program location selected in the listing.
private ProgramLocation currentLocation = null; private ProgramLocation currentLocation = null;
// Character used as a separator when entering multiple tags in // Character used as a separator when entering multiple tags in
// the create tag entry field. // the create tag entry field.
private static final String INPUT_DELIMITER = ","; private static final String INPUT_DELIMITER = ",";
/** /**
* Optional! If there is a file with this name which can be found by the * Optional! If there is a file with this name which can be found by the
* {@link ResourceManager}, and it contains a valid list of tag names, * {@link ResourceManager}, and it contains a valid list of tag names,
* they will be loaded. The file must be XML with the following * they will be loaded. The file must be XML with the following
* structure: * structure:
* *
* <tags> * <tags>
* <tag> * <tag>
* <name>TAG1</name> * <name>TAG1</name>
* <comment>tag comment</comment> * <comment>tag comment</comment>
* </tag> * </tag>
* </tags> * </tags>
* *
*/ */
private static String TAG_FILE = "functionTags.xml"; private static String TAG_FILE = "functionTags.xml";
// Keeps a list of the original tags as loaded from file. This is necessary when switching // Keeps a list of the original tags as loaded from file. This is necessary when switching
// between programs where we need to know the original state of the disabled tags. Without // between programs where we need to know the original state of the disabled tags. Without
// this we would need to reload from file on each new program activation. // this we would need to reload from file on each new program activation.
private Set<FunctionTag> tagsFromFile; private Set<FunctionTag> tagsFromFile;
/** /**
* Constructor * Constructor
* *
* @param plugin the function tag plugin * @param plugin the function tag plugin
* @param program the current program * @param program the current program
*/ */
@ -118,10 +117,6 @@ public class FunctionTagProvider extends ComponentProviderAdapter
addToTool(); addToTool();
} }
/******************************************************************************
* PUBLIC METHODS
******************************************************************************/
@Override @Override
public void componentShown() { public void componentShown() {
updateView(); updateView();
@ -133,10 +128,10 @@ public class FunctionTagProvider extends ComponentProviderAdapter
} }
/** /**
* Invoked when a new location has been detected in the listing. When * Invoked when a new location has been detected in the listing. When
* this happens we need to update the tag list to show what tags are assigned * this happens we need to update the tag list to show what tags are assigned
* at the current location. * at the current location.
* *
* @param loc the address selected in the listing * @param loc the address selected in the listing
*/ */
public void locationChanged(ProgramLocation loc) { public void locationChanged(ProgramLocation loc) {
@ -158,12 +153,6 @@ public class FunctionTagProvider extends ComponentProviderAdapter
this.program = null; this.program = null;
} }
/**
* This class needs to listen for changes to the domain object (tag create, delete, etc...)
* so it can update the display accordingly.
*
* @param ev the change event
*/
@Override @Override
public void domainObjectChanged(DomainObjectChangedEvent ev) { public void domainObjectChanged(DomainObjectChangedEvent ev) {
@ -244,8 +233,8 @@ public class FunctionTagProvider extends ComponentProviderAdapter
allFunctionsPanel.setBorder(BorderFactory.createLineBorder(Colors.BORDER)); allFunctionsPanel.setBorder(BorderFactory.createLineBorder(Colors.BORDER));
// If we don't set this, then the splitter won't be able to shrink the // If we don't set this, then the splitter won't be able to shrink the
// target panels below the size required by its header, which can be large // target panels below the size required by its header, which can be large
// because of the amount of text displayed. Keep the minimum size setting on // because of the amount of text displayed. Keep the minimum size setting on
// the source panel, however. That is generally small. // the source panel, however. That is generally small.
targetPanel.setMinimumSize(new Dimension(0, 0)); targetPanel.setMinimumSize(new Dimension(0, 0));
@ -270,7 +259,7 @@ public class FunctionTagProvider extends ComponentProviderAdapter
* Updates the button panel depending on the selection state of the * Updates the button panel depending on the selection state of the
* tag lists. Also updates the {@link AllFunctionsPanel} so it can update * tag lists. Also updates the {@link AllFunctionsPanel} so it can update
* its list. * its list.
* *
* @param panel the panel that generated the selection event * @param panel the panel that generated the selection event
*/ */
public void selectionChanged(TagListPanel panel) { public void selectionChanged(TagListPanel panel) {
@ -330,7 +319,7 @@ public class FunctionTagProvider extends ComponentProviderAdapter
/** /**
* Loads tags from the external file specified. * Loads tags from the external file specified.
* *
* @return the loaded tags * @return the loaded tags
*/ */
private Set<FunctionTag> getFileTags() { private Set<FunctionTag> getFileTags() {
@ -342,7 +331,7 @@ public class FunctionTagProvider extends ComponentProviderAdapter
/** /**
* Returns an array of all tags stored in the database. * Returns an array of all tags stored in the database.
* *
* @return list of tags * @return list of tags
*/ */
private List<? extends FunctionTag> getAllTagsFromDatabase() { private List<? extends FunctionTag> getAllTagsFromDatabase() {
@ -355,7 +344,7 @@ public class FunctionTagProvider extends ComponentProviderAdapter
/** /**
* Returns the {@link Function} for the given program location * Returns the {@link Function} for the given program location
* *
* @param loc the program location * @param loc the program location
* @return function containing the location, or null if not applicable * @return function containing the location, or null if not applicable
*/ */
@ -371,7 +360,7 @@ public class FunctionTagProvider extends ComponentProviderAdapter
/** /**
* Retrieves the address of the function associated with the given program location. * Retrieves the address of the function associated with the given program location.
* *
* @param loc the program location * @param loc the program location
* @return the entry point of the function, or null if not valid * @return the entry point of the function, or null if not valid
*/ */
@ -408,7 +397,7 @@ public class FunctionTagProvider extends ComponentProviderAdapter
targetPanel.setProgram(program); targetPanel.setProgram(program);
allFunctionsPanel.setProgram(program); allFunctionsPanel.setProgram(program);
// Get the currently selected tags and use them to update the all functions panel. If // Get the currently selected tags and use them to update the all functions panel. If
// there is no current selection, leave the table as-is. // there is no current selection, leave the table as-is.
Set<FunctionTag> sTags = sourcePanel.getSelectedTags(); Set<FunctionTag> sTags = sourcePanel.getSelectedTags();
Set<FunctionTag> tTags = targetPanel.getSelectedTags(); Set<FunctionTag> tTags = targetPanel.getSelectedTags();
@ -423,7 +412,7 @@ public class FunctionTagProvider extends ComponentProviderAdapter
} }
/** /**
* Parses all items in the text input field and adds them as new tags. * Parses all items in the text input field and adds them as new tags.
*/ */
private void processCreates() { private void processCreates() {
@ -462,7 +451,7 @@ public class FunctionTagProvider extends ComponentProviderAdapter
/** /**
* Returns a list of tag names the user has entered in the input` field. * Returns a list of tag names the user has entered in the input` field.
* Note: This assumes that multiple entries are comma-delimited. * Note: This assumes that multiple entries are comma-delimited.
* *
* @return the list of tag names to create * @return the list of tag names to create
*/ */
private List<String> getInputNames() { private List<String> getInputNames() {
@ -470,7 +459,7 @@ public class FunctionTagProvider extends ComponentProviderAdapter
// first split the string on the delimiter to get all the entries // first split the string on the delimiter to get all the entries
String[] names = tagInputField.getText().split(INPUT_DELIMITER); String[] names = tagInputField.getText().split(INPUT_DELIMITER);
// trim each item to remove any leading/trailing whitespace and add to the return list // trim each item to remove any leading/trailing whitespace and add to the return list
List<String> nameList = new ArrayList<>(); List<String> nameList = new ArrayList<>();
for (String name : names) { for (String name : names) {
if (!StringUtils.isBlank(name)) { if (!StringUtils.isBlank(name)) {
@ -483,7 +472,7 @@ public class FunctionTagProvider extends ComponentProviderAdapter
/** /**
* Creates the text-entry panel for adding new tag names. * Creates the text-entry panel for adding new tag names.
* *
* @return the new text input panel * @return the new text input panel
*/ */
private JPanel createInputPanel() { private JPanel createInputPanel() {