GP-1981 Added IconModifiers for sizing,translating, disabling, and

creating overlayed icons in the theme files. Also some VT icon
externalization
This commit is contained in:
ghidragon 2022-09-21 16:28:28 -04:00
parent b2d16ab982
commit dd31ff47a2
80 changed files with 1555 additions and 525 deletions

View file

@ -51,19 +51,19 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
private boolean isForward = true;
private boolean isInverted;
private static final ImageIcon BOOKMARK_ICON = ResourceManager.getScaledIcon(
private static final Icon BOOKMARK_ICON = ResourceManager.getScaledIcon(
ResourceManager.loadImage("images/B.gif"), 16, 16);
private static final ImageIcon BOOKMARK_ANALYSIS_ICON =
private static final Icon BOOKMARK_ANALYSIS_ICON =
ResourceManager.loadImage("images/applications-system.png");
private static final ImageIcon BOOKMARK_ERROR_ICON =
ResourceManager.loadImage("images/edit-delete.png");
private static final ImageIcon BOOKMARK_INFO_ICON =
private static final Icon BOOKMARK_INFO_ICON =
ResourceManager.loadImage("images/information.png");
private static final ImageIcon BOOKMARK_NOTE_ICON =
private static final Icon BOOKMARK_NOTE_ICON =
ResourceManager.loadImage("images/notes.gif");
private static final ImageIcon BOOKMARK_WARNING_ICON =
private static final Icon BOOKMARK_WARNING_ICON =
ResourceManager.loadImage("images/warning.png");
private static final ImageIcon BOOKMARK_UNKNOWN_ICON =
private static final Icon BOOKMARK_UNKNOWN_ICON =
ResourceManager.loadImage("images/unknown.gif");
public NextPreviousBookmarkAction(PluginTool tool, String owner, String subGroup) {

View file

@ -23,8 +23,7 @@ import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.ImageIcon;
import javax.swing.KeyStroke;
import javax.swing.*;
import org.apache.commons.lang3.StringUtils;
@ -465,7 +464,7 @@ public class ScriptInfo {
* @param scaled true if the icon should be scaled to 16x16.
* @return the script tool bar icon
*/
public ImageIcon getToolBarImage(boolean scaled) {
public Icon getToolBarImage(boolean scaled) {
parseHeader();
if (toolbar == null) {
return null;

View file

@ -749,7 +749,7 @@ public class FrontEndPluginActionsTest extends AbstractGhidraHeadedIntegrationTe
performAction(readOnlyAction, getTreeActionContext(), true);
assertTrue(((DomainFileNode) npNode).getDomainFile().isReadOnly());
ImageIcon icon = ResourceManager.loadImage("fileIcons/ProgramReadOnly.gif");
Icon icon = ResourceManager.loadImage("fileIcons/ProgramReadOnly.gif");
icon = ResourceManager.getScaledIcon(icon, 16, 16);
assertTrue(npNode.getIcon(false) instanceof MultiIcon);

View file

@ -58,8 +58,8 @@ public class SetVertexMostRecentColorAction extends MultiActionDockingAction {
Icon blankIcon = new EmptyIcon(16, 16);
MultiIcon multiIcon = new MultiIcon(blankIcon);
ImageIcon paintBrushImage = ResourceManager.loadImage("images/paintbrush.png");
ImageIcon scaledBrush = ResourceManager.getScaledIcon(paintBrushImage, 16, 16);
Icon paintBrushImage = ResourceManager.loadImage("images/paintbrush.png");
Icon scaledBrush = ResourceManager.getScaledIcon(paintBrushImage, 16, 16);
Point point = getLowerLeftIconOffset(blankIcon, colorIcon);
Icon translateIcon = new TranslateIcon(colorIcon, point.x, point.y);

View file

@ -32,6 +32,105 @@ color.bg.version.tracking.related.matches.table.bad = red
color.fg.version.tracking.function.match.local.info = green
icon.version.tracking.session.content.type = start-here_16.png
icon.version.tracking.package = start-here_16.png
icon.version.tracking.provider.function = functions.gif
icon.version.tracking.provider.implied.match = application_view_detail.png
icon.version.tracking.provider.markup = application_view_detail.png
icon.version.tracking.provider.one.to.many = text_list_bullets.png
icon.version.tracking.provider.related.matches = user-online.png
icon.version.tracking.unfiltered = lightbulb_off.png
icon.version.tracking.filtered = lightbulb.png
icon.version.tracking.replaced = sync_enabled.png
icon.version.tracking.unignored = EMPTY_ICON{dialog-cancel.png[size(13,13)][move(3,4)]}{undo.png[move(0,-4)]}
icon.version.tracking.accept.match = flag.png
icon.version.tracking.add = Plus.png
icon.version.tracking.substract = list-remove.png
icon.version.tracking.replace = sync_enabled.png
icon.version.tracking.auto = wizard.png
icon.version.tracking.action.clear.match = undo-apply.png
icon.version.tracking.action.create.implied.match = flag.png
icon.version.tracking.action.create.manual.match = Plus.png
icon.version.tracking.action.create.and.accept.manual.match = flag.png
icon.version.tracking.action.create.accept.and.apply.manual.match = checkmark_green.gif
icon.version.tracking.action.create.selection = text_align_justify.png
icon.version.tracking.action.create.session = start-here_16.png
icon.version.tracking.action.choose.tag = tag_blue.png
icon.version.tracking.action.edit.all.tags = tag_blue_edit.png
icon.version.tracking.action.accept.match = icon.version.tracking.accept.match
icon.version.tracking.action.add.to.session = Plus.png
icon.version.tracking.action.save.session = disk.png
icon.version.tracking.action.match.reject = dialog-cancel.png
icon.version.tracking.action.match.remove = edit-delete.png
icon.version.tracking.action.match.select.existing = text_align_justify.png
icon.version.tracking.action.match.tag.remove = tag_blue_delete.png
icon.version.tracking.action.markup.reset = undo-apply.png
icon.version.tracking.action.match.one.to.many = text_align_justify.png
icon.version.tracking.action.show.listings = application_tile_horizontal.png
icon.version.tracking.action.show.settings = settings16.gif
icon.version.tracking.action.edit.markup.address = edit-rename.png
icon.version.tracking.tag.status.new = tag_blue_add.png
icon.version.tracking.tag.status.deleted = tag_blue_delete.png
icon.version.tracking.tag.status.existing = tag_blue.png
icon.version.tracking.tag.button.undo = undo-apply.png
icon.version.tracking.filter.status.changed = bullet_black.png
icon.version.tracking.filter.status.invalid = no_small.png
icon.version.tracking.filter.status.applied = bullet_green.png
icon.version.tracking.markup.status.applied = checkmark_green.gif
icon.version.tracking.markup.status.rejected = dialog-cancel.png
icon.version.tracking.markup.status.dont.care = asterisk_orange.png
icon.version.tracking.markup.status.dont.know = unknown.gif
icon.version.tracking.markup.status.failed = edit-delete.png
icon.version.tracking.markup.status.conflict = cache.png
icon.version.tracking.filter = view-filter.png
icon.version.tracking.empty = EmptyIcon16.gif
icon.version.tracking.function.filter.all = function.png
icon.version.tracking.function.filter.unmatched = filter_matched.png
icon.version.tracking.match.table.status.accepted.some.unexamined = flag.png {bullet_error.png[move(10,8)]}
icon.version.tracking.match.table.status.accepted.error = flag.png {edit-delete.png[size(8,8)][move(10,8)]}
icon.version.tracking.match.table.status.accepted.fully.applied = flag.png {checkmark_green.gif[size(8,8)][move(10,8)]}
icon.version.tracking.match.table.status.accepted.fully.considered = flag.png {checkmark_yellow.gif[size(8,8)][move(10,8)]}
icon.version.tracking.match.table.status.rejected = dialog-cancel.png
icon.version.tracking.match.table.status.blocked = kgpg.png
icon.version.tracking.match.table.markup.status.disabled = ledgreen.png[size(8,8)][disabled]
icon.version.tracking.match.table.markup.status.not.applied = ledorange.png[size(8,8)][move(0,4)]
icon.version.tracking.match.table.markup.status.applied = ledgreen.png[size(8,8)][move(9,4)]
icon.version.tracking.match.table.markup.status.rejected = ledpurple.png[size(8,8)][move(18,4)]
icon.version.tracking.match.table.markup.status.ignored = ledblue.png[size(8,8)][move(27,4)]
icon.version.tracking.match.table.markup.status.error = ledred.png[size(8,8)][move(36,4)]
icon.version.tracking.related.match.target = user-online.png
icon.version.tracking.related.match.caller = go-down.png
icon.version.tracking.related.match.callee = go-next.png
icon.version.tracking.related.match.unrelated = user-busy.png
icon.version.tracking.related.match.accepted = accept.png
icon.version.tracking.related.match.available = media-playback-stop.png
icon.version.tracking.related.match.locked.out = edit-delete.png
icon.version.tracking.match.table.selection.track.row = table_gear.png
icon.version.tracking.match.table.selection.track.match = table_go.png
icon.version.tracking.match.table.selection.track.none = table_delete.png
icon.version.tracking.table.renderer.multiple.symbols = application_view_detail.png
icon.version.tracking.new.session.swap = doubleArrowUpDown.png
icon.version.tracking.new.session.info = information.png
icon.version.tracking.correlator.status.already.run = flag-green.png
[Dark Defaults]

View file

@ -18,11 +18,11 @@ package ghidra.feature.vt.api.impl;
import java.io.IOException;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import db.DBHandle;
import db.OpenMode;
import db.buffers.BufferFile;
import generic.theme.GIcon;
import ghidra.feature.vt.api.db.VTSessionDB;
import ghidra.framework.data.*;
import ghidra.framework.model.ChangeSet;
@ -33,11 +33,9 @@ import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.VersionException;
import ghidra.util.task.TaskMonitor;
import resources.ResourceManager;
public class VTSessionContentHandler extends DBContentHandler {
private static ImageIcon ICON = ResourceManager
.getScaledIcon(ResourceManager.loadImage("images/start-here_16.png"), 16, 16);
private static Icon ICON = new GIcon("icon.version.tracking.session.content.type");
public final static String CONTENT_TYPE = "VersionTracking";

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,6 +15,14 @@
*/
package ghidra.feature.vt.gui.actions;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Icon;
import docking.ActionContext;
import docking.action.*;
import generic.theme.GIcon;
import ghidra.feature.vt.api.main.VTMatch;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
@ -24,15 +31,6 @@ import ghidra.feature.vt.gui.provider.onetomany.VTMatchOneToManyContext;
import ghidra.feature.vt.gui.task.AcceptMatchTask;
import ghidra.util.HelpLocation;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Icon;
import resources.ResourceManager;
import docking.ActionContext;
import docking.action.*;
public class AcceptMatchAction extends DockingAction {
private static final String MENU_GROUP = VTPlugin.EDIT_MENU_GROUP;
@ -43,7 +41,7 @@ public class AcceptMatchAction extends DockingAction {
super("Accept", VTPlugin.OWNER);
this.controller = controller;
Icon icon = ResourceManager.loadImage("images/flag.png");
Icon icon = new GIcon("icon.version.tracking.action.accept.match");
setToolBarData(new ToolBarData(icon, MENU_GROUP));
setPopupMenuData(new MenuData(new String[] { "Accept" }, icon, MENU_GROUP));
setEnabled(false);

View file

@ -15,18 +15,17 @@
*/
package ghidra.feature.vt.gui.actions;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
import ghidra.feature.vt.gui.wizard.VTAddToSessionWizardManager;
import ghidra.util.HelpLocation;
import javax.swing.Icon;
import resources.ResourceManager;
import docking.ActionContext;
import docking.action.*;
import docking.tool.ToolConstants;
import docking.wizard.WizardManager;
import generic.theme.GIcon;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
import ghidra.feature.vt.gui.wizard.VTAddToSessionWizardManager;
import ghidra.util.HelpLocation;
public class AddToVersionTrackingSessionAction extends DockingAction {
@ -37,13 +36,8 @@ public class AddToVersionTrackingSessionAction extends DockingAction {
super("Add To Session", VTPlugin.OWNER);
this.controller = controller;
String[] menuPath = { ToolConstants.MENU_FILE, "Add to Session..." };
Icon plusIcon = ResourceManager.loadImage("images/Plus.png");
Icon plusIcon = new GIcon("icon.version.tracking.action.add.to.session");
setMenuBarData(new MenuData(menuPath, plusIcon, "AAA"));
// Icon baseNewIcon = ResourceManager.loadImage("images/start-here_16.png");
// MultiIcon addToIcon = new MultiIcon(baseNewIcon, false);
// addToIcon.addIcon(plusIcon);
setToolBarData(new ToolBarData(plusIcon, "View"));
setDescription("Add additional correlations to the current version tracking session");
setHelpLocation(new HelpLocation("VersionTrackingPlugin", "Add_To_Session"));

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,20 +15,19 @@
*/
package ghidra.feature.vt.gui.actions;
import ghidra.feature.vt.api.main.VTMatch;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
import ghidra.feature.vt.gui.provider.matchtable.VTMatchContext;
import ghidra.feature.vt.gui.task.ApplyMatchTask;
import ghidra.util.HelpLocation;
import java.util.List;
import javax.swing.Icon;
import resources.ResourceManager;
import docking.ActionContext;
import docking.action.*;
import ghidra.feature.vt.api.main.VTMatch;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
import ghidra.feature.vt.gui.provider.markuptable.MarkupStatusIcons;
import ghidra.feature.vt.gui.provider.matchtable.VTMatchContext;
import ghidra.feature.vt.gui.task.ApplyMatchTask;
import ghidra.util.HelpLocation;
public class ApplyMatchAction extends DockingAction {
@ -42,7 +40,7 @@ public class ApplyMatchAction extends DockingAction {
super(NAME, VTPlugin.OWNER);
this.controller = controller;
Icon icon = ResourceManager.loadImage("images/checkmark_green.gif");
Icon icon = MarkupStatusIcons.APPLIED_ICON;
setToolBarData(new ToolBarData(icon, MENU_GROUP));
setPopupMenuData(new MenuData(new String[] { NAME }, icon, MENU_GROUP));
setEnabled(false);

View file

@ -20,19 +20,19 @@ import javax.swing.Icon;
import docking.ActionContext;
import docking.action.*;
import docking.tool.ToolConstants;
import generic.theme.GIcon;
import ghidra.feature.vt.api.main.VTSession;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
import ghidra.util.HTMLUtilities;
import ghidra.util.HelpLocation;
import ghidra.util.task.TaskLauncher;
import resources.ResourceManager;
/**
* This action runs the {@link AutoVersionTrackingTask}
*/
public class AutoVersionTrackingAction extends DockingAction {
public static Icon AUTO_VT_ICON = ResourceManager.loadImage("images/wizard.png");
public static Icon AUTO_VT_ICON = new GIcon("icon.version.tracking.auto");
private final VTController controller;
public AutoVersionTrackingAction(VTController controller) {

View file

@ -24,18 +24,18 @@ import javax.swing.*;
import docking.ActionContext;
import docking.DialogComponentProvider;
import docking.action.*;
import generic.theme.GIcon;
import ghidra.feature.vt.api.main.*;
import ghidra.feature.vt.gui.editors.MatchTagComboBox;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
import ghidra.feature.vt.gui.provider.matchtable.VTMatchContext;
import ghidra.util.HelpLocation;
import resources.ResourceManager;
public class ChooseMatchTagAction extends DockingAction {
private static final String MENU_GROUP = VTPlugin.TAG_MENU_GROUP;
private static final Icon EDIT_TAG_ICON = ResourceManager.loadImage("images/tag_blue.png");
private static final Icon EDIT_TAG_ICON = new GIcon("icon.version.tracking.action.choose.tag");
private static final String ACTION_NAME = "Choose Match Tag";
private final VTController controller;

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,6 +15,14 @@
*/
package ghidra.feature.vt.gui.actions;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Icon;
import docking.ActionContext;
import docking.action.*;
import generic.theme.GIcon;
import ghidra.feature.vt.api.main.VTMatch;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
@ -24,19 +31,10 @@ import ghidra.feature.vt.gui.provider.onetomany.VTMatchOneToManyContext;
import ghidra.feature.vt.gui.task.ClearMatchTask;
import ghidra.util.HelpLocation;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Icon;
import resources.ResourceManager;
import docking.ActionContext;
import docking.action.*;
public class ClearMatchAction extends DockingAction {
private static final String MENU_GROUP = VTPlugin.UNEDIT_MENU_GROUP;
private static final Icon ICON = ResourceManager.loadImage("images/undo-apply.png");
private static final Icon ICON = new GIcon("icon.version.tracking.action.clear.match");
private final VTController controller;
public ClearMatchAction(VTController controller) {

View file

@ -17,10 +17,11 @@ package ghidra.feature.vt.gui.actions;
import java.util.List;
import javax.swing.ImageIcon;
import javax.swing.Icon;
import docking.ActionContext;
import docking.action.*;
import generic.theme.GIcon;
import ghidra.feature.vt.api.main.VTMatch;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
@ -30,7 +31,6 @@ import ghidra.feature.vt.gui.task.*;
import ghidra.util.HelpLocation;
import ghidra.util.task.Task;
import ghidra.util.task.TaskListener;
import resources.ResourceManager;
public class CreateImpliedMatchAction extends DockingAction {
@ -43,7 +43,7 @@ public class CreateImpliedMatchAction extends DockingAction {
this.controller = controller;
this.provider = provider;
ImageIcon icon = ResourceManager.loadImage("images/flag.png");
Icon icon = new GIcon("icon.version.tracking.action.create.implied.match");
setToolBarData(new ToolBarData(icon, "1"));
setPopupMenuData(new MenuData(new String[] { "Accept Implied Match" }, icon, "1"));
setHelpLocation(new HelpLocation("VersionTrackingPlugin", "Accept_Implied_Match"));

View file

@ -15,6 +15,12 @@
*/
package ghidra.feature.vt.gui.actions;
import javax.swing.Icon;
import docking.ActionContext;
import docking.action.MenuData;
import docking.action.ToolBarData;
import generic.theme.GIcon;
import ghidra.feature.vt.api.main.VTSession;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
@ -25,19 +31,13 @@ import ghidra.util.HelpLocation;
import ghidra.util.task.Task;
import ghidra.util.task.TaskListener;
import javax.swing.Icon;
import resources.ResourceManager;
import docking.ActionContext;
import docking.action.*;
/**
* Action that creates a manual match for the currently selected source and destination functions
* in the function association tables.
*/
public class CreateManualMatchAction extends AbstractCreateManualMatchAction {
public static final Icon ICON = ResourceManager.loadImage("images/Plus.png");
public static final Icon ICON = new GIcon("icon.version.tracking.action.create.manual.match");
/**
* Creates a manual match action.

View file

@ -15,6 +15,12 @@
*/
package ghidra.feature.vt.gui.actions;
import javax.swing.Icon;
import docking.ActionContext;
import docking.action.MenuData;
import docking.action.ToolBarData;
import generic.theme.GIcon;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
import ghidra.feature.vt.gui.provider.functionassociation.FunctionAssociationContext;
@ -24,19 +30,14 @@ import ghidra.util.HelpLocation;
import ghidra.util.task.Task;
import ghidra.util.task.TaskListener;
import javax.swing.Icon;
import resources.ResourceManager;
import docking.ActionContext;
import docking.action.*;
/**
* Action that creates a manual match for the currently selected source and destination functions
* in the function association tables and then accepts the match.
*/
public class CreateManualMatchAndAcceptAction extends AbstractCreateManualMatchAction {
public static final Icon ICON = ResourceManager.loadImage("images/flag.png");
public static final Icon ICON =
new GIcon("icon.version.tracking.action.create.and.accept.manual.match");
/**
* Creates a manual match action that also does an accept of that match.
@ -48,7 +49,8 @@ public class CreateManualMatchAndAcceptAction extends AbstractCreateManualMatchA
setToolBarData(new ToolBarData(ICON, MENU_GROUP));
setPopupMenuData(new MenuData(new String[] { "Create And Accept Manual Match" }, ICON));
setEnabled(false);
setHelpLocation(new HelpLocation("VersionTrackingPlugin", "Create_And_Accept_Manual_Match"));
setHelpLocation(
new HelpLocation("VersionTrackingPlugin", "Create_And_Accept_Manual_Match"));
}
@Override

View file

@ -15,6 +15,12 @@
*/
package ghidra.feature.vt.gui.actions;
import javax.swing.Icon;
import docking.ActionContext;
import docking.action.MenuData;
import docking.action.ToolBarData;
import generic.theme.GIcon;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
import ghidra.feature.vt.gui.provider.functionassociation.FunctionAssociationContext;
@ -24,19 +30,14 @@ import ghidra.util.HelpLocation;
import ghidra.util.task.Task;
import ghidra.util.task.TaskListener;
import javax.swing.Icon;
import resources.ResourceManager;
import docking.ActionContext;
import docking.action.*;
/**
* Action that creates a manual match for the currently selected source and destination functions
* in the function association tables and then applies the match.
*/
public class CreateManualMatchAndAcceptAndApplyAction extends AbstractCreateManualMatchAction {
public static final Icon ICON = ResourceManager.loadImage("images/checkmark_green.gif");
public static final Icon ICON =
new GIcon("icon.version.tracking.action.create.accept.and.apply.manual.match");
/**
* Creates a manual match action that also does an apply of that match.

View file

@ -21,6 +21,7 @@ import javax.swing.Icon;
import docking.ActionContext;
import docking.action.*;
import generic.theme.GIcon;
import ghidra.feature.vt.api.main.VTAssociation;
import ghidra.feature.vt.api.main.VTMatch;
import ghidra.feature.vt.gui.plugin.VTController;
@ -29,12 +30,11 @@ import ghidra.feature.vt.gui.provider.matchtable.VTMatchContext;
import ghidra.program.model.address.AddressSet;
import ghidra.program.model.listing.Program;
import ghidra.util.HelpLocation;
import resources.ResourceManager;
public class CreateSelectionAction extends DockingAction {
public static final String NAME = "Create Match Table Selection";
private static final String MENU_GROUP = "Selection";
private static final Icon ICON = ResourceManager.loadImage("images/text_align_justify.png");
private static final Icon ICON = new GIcon("icon.version.tracking.action.create.selection");
private final VTController controller;
public CreateSelectionAction(VTController controller) {
@ -44,7 +44,8 @@ public class CreateSelectionAction extends DockingAction {
setPopupMenuData(new MenuData(new String[] { "Make Selections" }, ICON, MENU_GROUP));
setEnabled(false);
setHelpLocation(new HelpLocation("VersionTrackingPlugin", "Make Selections"));
setDescription("Makes selections in both the source and destination tools for the selected matches.");
setDescription(
"Makes selections in both the source and destination tools for the selected matches.");
}
@Override

View file

@ -15,22 +15,21 @@
*/
package ghidra.feature.vt.gui.actions;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
import ghidra.feature.vt.gui.wizard.VTNewSessionWizardManager;
import ghidra.util.HelpLocation;
import javax.swing.Icon;
import resources.ResourceManager;
import docking.ActionContext;
import docking.action.*;
import docking.tool.ToolConstants;
import docking.widgets.OptionDialog;
import docking.wizard.WizardManager;
import generic.theme.GIcon;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
import ghidra.feature.vt.gui.wizard.VTNewSessionWizardManager;
import ghidra.util.HelpLocation;
public class CreateVersionTrackingSessionAction extends DockingAction {
public static Icon NEW_ICON = ResourceManager.loadImage("images/start-here_16.png");
public static Icon NEW_ICON = new GIcon("icon.version.tracking.action.create.session");
private final VTController controller;
public CreateVersionTrackingSessionAction(VTController controller) {

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,22 +15,22 @@
*/
package ghidra.feature.vt.gui.actions;
import javax.swing.Icon;
import docking.ActionContext;
import docking.action.*;
import generic.theme.GIcon;
import ghidra.feature.vt.gui.editors.TagEditorDialog;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
import ghidra.feature.vt.gui.provider.matchtable.VTMatchContext;
import ghidra.util.HelpLocation;
import javax.swing.Icon;
import resources.ResourceManager;
import docking.ActionContext;
import docking.action.*;
public class EditAllTagsAction extends DockingAction {
private static final String MENU_GROUP = VTPlugin.TAG_MENU_GROUP;
private static final Icon EDIT_TAG_ICON = ResourceManager.loadImage("images/tag_blue_edit.png");
private static final Icon EDIT_TAG_ICON =
new GIcon("icon.version.tracking.action.edit.all.tags");
private static final String ACTION_NAME = "Edit VTMatch Tags";
private final VTController controller;

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,6 +15,15 @@
*/
package ghidra.feature.vt.gui.actions;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import docking.ActionContext;
import docking.DialogComponentProvider;
import docking.action.*;
import generic.theme.GIcon;
import ghidra.feature.vt.api.main.VTMarkupItem;
import ghidra.feature.vt.api.main.VTMarkupItemDestinationAddressEditStatus;
import ghidra.feature.vt.gui.editors.*;
@ -28,21 +36,11 @@ import ghidra.program.model.listing.Program;
import ghidra.util.*;
import ghidra.util.exception.InvalidInputException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import resources.ResourceManager;
import docking.ActionContext;
import docking.DialogComponentProvider;
import docking.action.*;
public class EditMarkupAddressAction extends DockingAction {
private static final String MENU_GROUP = VTPlugin.ADDRESS_EDIT_MENU_GROUP;
private static final Icon EDIT_ADDRESS_ICON =
ResourceManager.loadImage("images/edit-rename.png");
new GIcon("icon.version.tracking.action.edit.markup.address");
private static final String ACTION_NAME = "Edit Markup Destination Address";
final VTController controller;
@ -55,7 +53,8 @@ public class EditMarkupAddressAction extends DockingAction {
setToolBarData(new ToolBarData(EDIT_ADDRESS_ICON, MENU_GROUP));
}
MenuData menuData =
new MenuData(new String[] { "Edit Destination Address" }, EDIT_ADDRESS_ICON, MENU_GROUP);
new MenuData(new String[] { "Edit Destination Address" }, EDIT_ADDRESS_ICON,
MENU_GROUP);
setPopupMenuData(menuData);
setEnabled(false);
setHelpLocation(new HelpLocation("VersionTrackingPlugin",

View file

@ -27,11 +27,12 @@ import ghidra.util.HelpLocation;
import ghidra.util.Msg;
import help.Help;
import help.HelpService;
import resources.Icons;
import resources.ResourceManager;
public class HelpAction extends DockingAction {
private static Icon ICON = ResourceManager.loadImage("images/help-browser.png");
private static Icon ICON = Icons.HELP_ICON;
public HelpAction() {
super("Version Tracking Help Action", VTPlugin.OWNER);

View file

@ -23,10 +23,10 @@ import docking.action.ToolBarData;
import docking.menu.ActionState;
import docking.menu.MultiStateDockingAction;
import docking.widgets.EventTrigger;
import generic.theme.GIcon;
import ghidra.feature.vt.gui.plugin.VTPlugin;
import ghidra.feature.vt.gui.provider.matchtable.VTMatchTableProvider;
import ghidra.util.HelpLocation;
import resources.ResourceManager;
public class MatchTableSelectionAction
extends MultiStateDockingAction<TableSelectionTrackingState> {
@ -49,9 +49,12 @@ public class MatchTableSelectionAction
new HelpLocation("VersionTrackingPlugin", "Match_Table_Selection");
setHelpLocation(helpLocation);
Icon noSelectionTrackingIcon = ResourceManager.loadImage("images/table_delete.png");
Icon trackMatchSelectionIcon = ResourceManager.loadImage("images/table_go.png");
Icon trackRowIndexSelectionIcon = ResourceManager.loadImage("images/table_gear.png");
Icon noSelectionTrackingIcon =
new GIcon("icon.version.tracking.match.table.selection.track.none");
Icon trackMatchSelectionIcon =
new GIcon("icon.version.tracking.match.table.selection.track.match");
Icon trackRowIndexSelectionIcon =
new GIcon("icon.version.tracking.match.table.selection.track.row");
ActionState<TableSelectionTrackingState> trackSelectedIndexActionState =
new ActionState<>("Track Selected Index",

View file

@ -23,12 +23,12 @@ import javax.swing.Icon;
import docking.ActionContext;
import docking.action.*;
import docking.tool.ToolConstants;
import generic.theme.GIcon;
import ghidra.feature.vt.api.db.VTSessionDB;
import ghidra.feature.vt.api.main.VTSession;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
import ghidra.util.*;
import resources.ResourceManager;
public class RedoAction extends DockingAction {
private final VTController controller;
@ -39,7 +39,7 @@ public class RedoAction extends DockingAction {
setHelpLocation(new HelpLocation(ToolConstants.TOOL_HELP_TOPIC, "Redo"));
String[] menuPath = { ToolConstants.MENU_EDIT, "&Redo" };
String group = "ZZUndo";
Icon icon = ResourceManager.loadImage("images/redo.png");
Icon icon = new GIcon("icon.redo");
MenuData menuData = new MenuData(menuPath, icon, group);
menuData.setMenuSubGroup("2Redo"); // make this appear below the undo menu item
setMenuBarData(menuData);

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,6 +15,13 @@
*/
package ghidra.feature.vt.gui.actions;
import java.util.List;
import javax.swing.Icon;
import docking.ActionContext;
import docking.action.*;
import generic.theme.GIcon;
import ghidra.feature.vt.api.main.VTMatch;
import ghidra.feature.vt.api.main.VTSession;
import ghidra.feature.vt.gui.plugin.VTController;
@ -24,18 +30,10 @@ import ghidra.feature.vt.gui.provider.matchtable.VTMatchContext;
import ghidra.feature.vt.gui.task.RejectMatchTask;
import ghidra.util.HelpLocation;
import java.util.List;
import javax.swing.Icon;
import resources.ResourceManager;
import docking.ActionContext;
import docking.action.*;
public class RejectMatchAction extends DockingAction {
private static final String MENU_GROUP = VTPlugin.EDIT_MENU_GROUP;
private static final Icon ICON = ResourceManager.loadImage("images/dialog-cancel.png");
private static final Icon ICON = new GIcon("icon.version.tracking.action.match.reject");
private final VTController controller;
public RejectMatchAction(VTController controller) {

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,6 +15,14 @@
*/
package ghidra.feature.vt.gui.actions;
import java.util.List;
import javax.swing.Icon;
import docking.ActionContext;
import docking.action.DockingAction;
import docking.action.MenuData;
import generic.theme.GIcon;
import ghidra.feature.vt.api.main.VTMatch;
import ghidra.feature.vt.api.main.VTSession;
import ghidra.feature.vt.gui.plugin.VTController;
@ -24,19 +31,10 @@ import ghidra.feature.vt.gui.provider.matchtable.VTMatchContext;
import ghidra.feature.vt.gui.task.RemoveMatchTask;
import ghidra.util.HelpLocation;
import java.util.List;
import javax.swing.Icon;
import resources.ResourceManager;
import docking.ActionContext;
import docking.action.DockingAction;
import docking.action.MenuData;
public class RemoveMatchAction extends DockingAction {
private static final String MENU_GROUP = VTPlugin.UNEDIT_MENU_GROUP;
private static final Icon ICON = ResourceManager.loadImage("images/edit-delete.png");
private static final Icon ICON = new GIcon("icon.version.tracking.action.match.remove");
private final VTController controller;
public RemoveMatchAction(VTController controller) {

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,6 +15,16 @@
*/
package ghidra.feature.vt.gui.actions;
import java.util.List;
import javax.swing.Icon;
import javax.swing.JComponent;
import docking.ActionContext;
import docking.ComponentProvider;
import docking.action.*;
import docking.widgets.OptionDialog;
import generic.theme.GIcon;
import ghidra.feature.vt.api.main.VTMatch;
import ghidra.feature.vt.api.main.VTMatchTag;
import ghidra.feature.vt.gui.plugin.VTPlugin;
@ -24,22 +33,11 @@ import ghidra.feature.vt.gui.task.ClearMatchTagTask;
import ghidra.util.HelpLocation;
import ghidra.util.task.TaskLauncher;
import java.util.List;
import javax.swing.Icon;
import javax.swing.JComponent;
import resources.ResourceManager;
import docking.ActionContext;
import docking.ComponentProvider;
import docking.action.*;
import docking.widgets.OptionDialog;
public class RemoveMatchTagAction extends DockingAction {
private static final String MENU_GROUP = VTPlugin.TAG_MENU_GROUP;
private static final Icon EDIT_TAG_ICON =
ResourceManager.loadImage("images/tag_blue_delete.png");
new GIcon("icon.version.tracking.action.match.tag.remove");
private static final String ACTION_NAME = "Remove VTMatch Tags";
private int tagCount = 0;

View file

@ -18,10 +18,10 @@ package ghidra.feature.vt.gui.actions;
import static ghidra.feature.vt.gui.util.VTOptionDefines.*;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import docking.action.MenuData;
import docking.action.ToolBarData;
import generic.theme.GIcon;
import ghidra.feature.vt.api.main.VTMarkupItemApplyActionType;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
@ -40,7 +40,7 @@ public class ReplaceDefaultMarkupItemAction extends AbstractMarkupItemAction {
super(controller, "Apply (Replace Default Only)");
Icon replacedIcon = VTPlugin.REPLACED_ICON;
ImageIcon warningIcon = ResourceManager.loadImage("images/warning.png");
Icon warningIcon = new GIcon("icon.warning");
warningIcon = ResourceManager.getScaledIcon(warningIcon, 12, 12);
int warningIconWidth = warningIcon.getIconWidth();
int warningIconHeight = warningIcon.getIconHeight();

View file

@ -15,10 +15,9 @@
*/
package ghidra.feature.vt.gui.actions;
import static ghidra.feature.vt.gui.util.VTOptionDefines.DATA_MATCH_DATA_TYPE;
import static ghidra.feature.vt.gui.util.VTOptionDefines.*;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import docking.action.MenuData;
import docking.action.ToolBarData;
@ -28,9 +27,6 @@ import ghidra.feature.vt.gui.plugin.VTPlugin;
import ghidra.feature.vt.gui.util.VTMatchApplyChoices.ReplaceDataChoices;
import ghidra.framework.options.ToolOptions;
import ghidra.util.HelpLocation;
import resources.MultiIcon;
import resources.ResourceManager;
import resources.icons.TranslateIcon;
/**
* Action that replaces Data for a version tracking data match, but only if no defined data
@ -54,22 +50,9 @@ public class ReplaceFirstMarkupItemAction extends AbstractMarkupItemAction {
super(controller, "Apply (Replace First Only)");
Icon replacedIcon = VTPlugin.REPLACED_ICON;
ImageIcon warningIcon = ResourceManager.loadImage("images/warning_obj.png");
warningIcon = ResourceManager.getScaledIcon(warningIcon, 12, 12);
MultiIcon multiIcon = new MultiIcon(replacedIcon, false);
int refreshIconWidth = replacedIcon.getIconWidth();
int refreshIconHeight = replacedIcon.getIconHeight();
int warningIconWidth = warningIcon.getIconWidth();
int warningIconHeight = warningIcon.getIconHeight();
int x = refreshIconWidth - warningIconWidth;
int y = refreshIconHeight - warningIconHeight;
TranslateIcon translateIcon = new TranslateIcon(warningIcon, x, y);
multiIcon.addIcon(translateIcon);
if (addToToolbar) {
setToolBarData(new ToolBarData(multiIcon, MENU_GROUP));
setToolBarData(new ToolBarData(replacedIcon, MENU_GROUP));
}
MenuData menuData =
new MenuData(new String[] { "Apply (Replace First Only)" }, replacedIcon, MENU_GROUP);

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,6 +15,13 @@
*/
package ghidra.feature.vt.gui.actions;
import java.util.List;
import javax.swing.Icon;
import docking.ActionContext;
import docking.action.*;
import generic.theme.GIcon;
import ghidra.feature.vt.api.main.*;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
@ -26,17 +32,9 @@ import ghidra.util.HelpLocation;
import ghidra.util.task.Task;
import ghidra.util.task.TaskListener;
import java.util.List;
import javax.swing.Icon;
import resources.ResourceManager;
import docking.ActionContext;
import docking.action.*;
public class ResetMarkupItemAction extends DockingAction {
public static final Icon RESET_ICON = ResourceManager.loadImage("images/undo-apply.png");
public static final Icon RESET_ICON = new GIcon("icon.version.tracking.action.markup.reset");
private static final String MENU_GROUP = VTPlugin.UNEDIT_MENU_GROUP;
final VTController controller;

View file

@ -15,13 +15,14 @@
*/
package ghidra.feature.vt.gui.actions;
import static ghidra.feature.vt.gui.plugin.VTPlugin.VT_MAIN_MENU_GROUP;
import static ghidra.feature.vt.gui.plugin.VTPlugin.*;
import javax.swing.Icon;
import docking.ActionContext;
import docking.action.*;
import docking.tool.ToolConstants;
import generic.theme.GIcon;
import ghidra.feature.vt.api.db.VTSessionDB;
import ghidra.feature.vt.api.main.VTSession;
import ghidra.feature.vt.gui.plugin.VTController;
@ -31,11 +32,10 @@ import ghidra.framework.model.DomainFile;
import ghidra.program.model.listing.Program;
import ghidra.util.HelpLocation;
import ghidra.util.task.TaskLauncher;
import resources.ResourceManager;
public class SaveVersionTrackingSessionAction extends DockingAction {
static final Icon ICON = ResourceManager.loadImage("images/disk.png");
static final Icon ICON = new GIcon("icon.version.tracking.action.save.session");
private final VTController controller;

View file

@ -19,12 +19,12 @@ import javax.swing.Icon;
import docking.ActionContext;
import docking.action.*;
import generic.theme.GIcon;
import ghidra.feature.vt.api.main.VTMatch;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
import ghidra.feature.vt.gui.provider.functionassociation.FunctionAssociationContext;
import ghidra.util.HelpLocation;
import resources.ResourceManager;
/**
* Action that selects the function match, if it exists, for the currently selected source and
@ -32,7 +32,8 @@ import resources.ResourceManager;
*/
public class SelectExistingMatchAction extends DockingAction {
private static final Icon ICON = ResourceManager.loadImage("images/text_align_justify.png");
private static final Icon ICON =
new GIcon("icon.version.tracking.action.match.select.existing");
private static final String MENU_GROUP = "Create";

View file

@ -21,18 +21,18 @@ import javax.swing.Icon;
import docking.ActionContext;
import docking.action.*;
import generic.theme.GIcon;
import ghidra.feature.vt.api.main.VTMatch;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
import ghidra.feature.vt.gui.provider.onetomany.VTMatchOneToManyContext;
import ghidra.util.HelpLocation;
import resources.ResourceManager;
public class SetVTMatchFromOneToManyAction extends DockingAction {
private static final String MENU_GROUP = VTPlugin.VT_MAIN_MENU_GROUP;
public static final Icon SET_MATCH_ICON =
ResourceManager.loadImage("images/text_align_justify.png");
new GIcon("icon.version.tracking.action.match.one.to.many");
final VTController controller;

View file

@ -23,11 +23,11 @@ import javax.swing.Icon;
import docking.ActionContext;
import docking.action.*;
import docking.tool.ToolConstants;
import generic.theme.GIcon;
import ghidra.feature.vt.api.db.VTSessionDB;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
import ghidra.util.*;
import resources.ResourceManager;
public class UndoAction extends DockingAction {
private final VTController controller;
@ -38,7 +38,7 @@ public class UndoAction extends DockingAction {
setHelpLocation(new HelpLocation(ToolConstants.TOOL_HELP_TOPIC, "Undo"));
String[] menuPath = { ToolConstants.MENU_EDIT, "&Undo" };
String group = "ZZUndo";
Icon icon = ResourceManager.loadImage("images/undo.png");
Icon icon = new GIcon("icon.undo");
MenuData menuData = new MenuData(menuPath, icon, group);
menuData.setMenuSubGroup("1Undo"); // make this appear above the redo menu item
setMenuBarData(menuData);

View file

@ -15,7 +15,7 @@
*/
package ghidra.feature.vt.gui.editors;
import static ghidra.feature.vt.gui.editors.TagEditorDialog.TagState.Action.ADD;
import static ghidra.feature.vt.gui.editors.TagEditorDialog.TagState.Action.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
@ -25,18 +25,19 @@ import javax.swing.*;
import docking.widgets.label.GDLabel;
import docking.widgets.list.GListCellRenderer;
import generic.theme.GIcon;
import ghidra.feature.vt.gui.editors.TagEditorDialog.TagState;
import ghidra.feature.vt.gui.editors.TagEditorDialog.TagStateListModel;
import ghidra.util.exception.AssertException;
import resources.ResourceManager;
public class TagEditorRenderer extends GListCellRenderer<TagState> {
private static final Icon NEW_TAG_ICON = ResourceManager.loadImage("images/tag_blue_add.png");
private static final Icon NEW_TAG_ICON = new GIcon("icon.version.tracking.tag.status.new");
private static final Icon DELETED_TAG_ICON =
ResourceManager.loadImage("images/tag_blue_delete.png");
private static final Icon EXISTING_TAG_ICON = ResourceManager.loadImage("images/tag_blue.png");
private static final Icon UNDO_ICON = ResourceManager.loadImage("images/undo-apply.png");
new GIcon("icon.version.tracking.tag.status.deleted");
private static final Icon EXISTING_TAG_ICON =
new GIcon("icon.version.tracking.tag.status.existing");
private static final Icon UNDO_ICON = new GIcon("icon.version.tracking.tag.button.undo");
private final JList<TagState> list;
private final TagStateListModel listModel;

View file

@ -22,9 +22,9 @@ import java.util.Set;
import javax.swing.Icon;
import javax.swing.JComponent;
import generic.theme.GIcon;
import ghidra.framework.options.SaveState;
import ghidra.util.exception.AssertException;
import resources.ResourceManager;
/**
* An interface to allow clients to provide a mechanism for filtering objects and to notify
@ -74,10 +74,11 @@ public abstract class Filter<T> {
public enum FilterEditingStatus {
NONE("", null),
DIRTY("Filter contents have changed, but are not yet applied", ResourceManager.loadImage(
"images/bullet_black.png")),
ERROR("Filter contents are not valid", ResourceManager.loadImage("images/no_small.png")),
APPLIED("Filter applied", ResourceManager.loadImage("images/bullet_green.png"));
DIRTY("Filter contents have changed, but are not yet applied", new GIcon(
"icon.version.tracking.filter.status.changed")),
ERROR("Filter contents are not valid", new GIcon(
"icon.version.tracking.filter.status.invalid")),
APPLIED("Filter applied", new GIcon("icon.version.tracking.filter.status.applied"));
private final String description;
private final Icon icon;

View file

@ -19,11 +19,13 @@ import java.net.URL;
import java.util.List;
import java.util.Set;
import javax.swing.*;
import javax.swing.Icon;
import javax.swing.JFrame;
import docking.action.DockingActionIf;
import docking.tool.ToolConstants;
import docking.wizard.WizardManager;
import generic.theme.GIcon;
import ghidra.GhidraOptions;
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
import ghidra.app.plugin.core.colorizer.ColorizingService;
@ -48,9 +50,7 @@ import ghidra.program.util.ProgramLocation;
import ghidra.util.*;
import help.Help;
import help.HelpService;
import resources.MultiIcon;
import resources.ResourceManager;
import resources.icons.*;
//@formatter:off
@PluginInfo(
@ -80,25 +80,10 @@ public class VTPlugin extends Plugin {
public static final String UNEDIT_MENU_GROUP = "A_VT_UnEdit";
public static final String VT_SETTINGS_MENU_GROUP = "ZZ_VT_SETTINGS";
public static final Icon UNFILTERED_ICON =
ResourceManager.loadImage("images/lightbulb_off.png");
public static final Icon FILTERED_ICON = ResourceManager.loadImage("images/lightbulb.png");
public static final Icon REPLACED_ICON = ResourceManager.loadImage("images/sync_enabled.png");
public static final Icon UNIGNORED_ICON = new IconWrapper() {
@Override
protected Icon createIcon() {
MultiIcon icon = new MultiIcon(new EmptyIcon(16, 16));
ImageIcon cancelIcon = ResourceManager.loadImage("images/dialog-cancel.png");
ScaledImageIcon scaledCancelIcon =
new ScaledImageIcon(cancelIcon, 13, 13);
TranslateIcon translatedCancelIcon = new TranslateIcon(scaledCancelIcon, 3, 4);
ImageIcon undoIcon = ResourceManager.loadImage("images/undo.png");
TranslateIcon translatedUndoIcon = new TranslateIcon(undoIcon, 0, -4);
icon.addIcon(translatedUndoIcon);
icon.addIcon(translatedCancelIcon);
return icon;
}
};
public static final Icon UNFILTERED_ICON = new GIcon("icon.version.tracking.unfiltered");
public static final Icon FILTERED_ICON = new GIcon("icon.version.tracking.filtered");
public static final Icon REPLACED_ICON = new GIcon("icon.version.tracking.replaced");
public static final Icon UNIGNORED_ICON = new GIcon("icon.version.tracking.unignored");
private VTController controller;

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,15 +15,14 @@
*/
package ghidra.feature.vt.gui.plugin;
import ghidra.framework.plugintool.util.PluginPackage;
import javax.swing.Icon;
import resources.ResourceManager;
import generic.theme.GIcon;
import ghidra.framework.plugintool.util.PluginPackage;
public class VersionTrackingPluginPackage extends PluginPackage {
public static final String NAME = "Version Tracking";
public static final Icon ICON = ResourceManager.loadImage("images/start-here.png");
public static final Icon ICON = new GIcon("icon.version.tracking.package");
public VersionTrackingPluginPackage() {
super(NAME, ICON,

View file

@ -38,6 +38,7 @@ import docking.widgets.fieldpanel.FieldPanel;
import docking.widgets.label.GDLabel;
import docking.widgets.table.threaded.ThreadedTableModel;
import generic.theme.GColor;
import generic.theme.GIcon;
import ghidra.app.plugin.core.functioncompare.FunctionComparisonPanel;
import ghidra.app.services.GoToService;
import ghidra.app.util.viewer.listingpanel.ListingCodeComparisonPanel;
@ -61,7 +62,6 @@ import ghidra.util.HelpLocation;
import ghidra.util.SystemUtilities;
import ghidra.util.table.*;
import resources.Icons;
import resources.ResourceManager;
/**
* Provider for the version tracking function association table.
@ -71,13 +71,12 @@ public class VTFunctionAssociationProvider extends ComponentProviderAdapter
private static final String FILTER_SETTINGS_KEY = "FUNCTION_FILTER_SETTINGS";
private static final String BASE_TITLE = "Version Tracking Functions";
private static final ImageIcon PROVIDER_ICON =
ResourceManager.loadImage("images/functions.gif");
private static final Icon PROVIDER_ICON = new GIcon("icon.version.tracking.provider.function");
private static final String SOURCE_TITLE = "Source";
private static final String DESTINATION_TITLE = "Destination";
private static final String NO_SESSION = "None";
private static final Icon SHOW_LISTINGS_ICON =
ResourceManager.loadImage("images/application_tile_horizontal.png");
new GIcon("icon.version.tracking.action.show.listings");
private static final String SHOW_COMPARE_ACTION_GROUP = "A9_ShowCompare"; // "A9_" forces to right of other dual view actions in toolbar.
private static final Color FG_ERROR = new GColor("color.fg.error");
@ -158,13 +157,13 @@ public class VTFunctionAssociationProvider extends ComponentProviderAdapter
filterAction.setHelpLocation(new HelpLocation("VersionTrackingPlugin", "Functions_Filter"));
Icon allFunctionsIcon = ResourceManager.loadImage("images/function.png");
Icon allFunctionsIcon = new GIcon("icon.version.tracking.function.filter.all");
ActionState<FilterSettings> allFunctionsActionState =
new ActionState<>("Show All Functions", allFunctionsIcon, SHOW_ALL);
allFunctionsActionState.setHelpLocation(
new HelpLocation("VersionTrackingPlugin", "Show_All_Functions"));
Icon unmatchedIcon = ResourceManager.loadImage("images/filter_matched.png");
Icon unmatchedIcon = new GIcon("icon.version.tracking.function.filter.unmatched");
ActionState<FilterSettings> unmatchedOnlyActionState =
new ActionState<>("Show Only Unmatched Functions", unmatchedIcon, SHOW_UNMATCHED);
unmatchedOnlyActionState.setHelpLocation(

View file

@ -30,6 +30,7 @@ import docking.action.*;
import docking.widgets.table.GTable;
import docking.widgets.table.RowObjectTableModel;
import docking.widgets.table.threaded.GThreadedTablePanel;
import generic.theme.GIcon;
import ghidra.feature.vt.api.db.DeletedMatch;
import ghidra.feature.vt.api.impl.VTChangeManager;
import ghidra.feature.vt.api.impl.VersionTrackingChangeRecord;
@ -47,7 +48,6 @@ import ghidra.util.HelpLocation;
import ghidra.util.table.GhidraTableFilterPanel;
import ghidra.util.table.GhidraThreadedTablePanel;
import resources.Icons;
import resources.ResourceManager;
public class VTImpliedMatchesTableProvider extends ComponentProviderAdapter
implements VTControllerListener {
@ -70,7 +70,7 @@ public class VTImpliedMatchesTableProvider extends ComponentProviderAdapter
this.controller = controller;
controller.addListener(this);
setWindowGroup(VTPlugin.WINDOW_GROUP);
setIcon(ResourceManager.loadImage("images/application_view_detail.png"));
setIcon(new GIcon("icon.version.tracking.provider.implied.match"));
setDefaultWindowPosition(WindowPosition.BOTTOM);
setIntraGroupPosition(WindowPosition.STACK);

View file

@ -100,7 +100,7 @@ public class MarkupItemStatusRenderer extends AbstractGhidraColumnRenderer<VTMar
"This markup item conflicts with another item that is already applied");
break;
default:
renderer.setIcon(ResourceManager.loadImage("images/core.png"));
renderer.setIcon(ResourceManager.getDefaultIcon());
renderer.setToolTipText("Unexpected match status state!: " + status);
break;
}

View file

@ -17,31 +17,30 @@ package ghidra.feature.vt.gui.provider.markuptable;
import javax.swing.Icon;
import generic.theme.GIcon;
import resources.MultiIcon;
import resources.ResourceManager;
import resources.icons.TranslateIcon;
public class MarkupStatusIcons {
public static final Icon APPLIED_ICON = ResourceManager.loadImage("images/checkmark_green.gif");
public static final Icon APPLY_ADD_MENU_ICON =
ResourceManager.loadImage("images/Plus.png");
public static final Icon APPLY_REPLACE_MENU_ICON =
ResourceManager.loadImage("images/sync_enabled.png");
private static final Icon SCALED_ADD_ICON =
ResourceManager.getScaledIcon(APPLY_ADD_MENU_ICON, 12, 12);
private static final Icon SCALED_REPLACE_ICON =
ResourceManager.getScaledIcon(APPLY_REPLACE_MENU_ICON, 12, 12);
//@formatter:off
public static final Icon APPLIED_ICON = new GIcon("icon.version.tracking.markup.status.applied");
public static final Icon APPLY_ADD_MENU_ICON = new GIcon("icon.version.tracking.add");
public static final Icon APPLY_REPLACE_MENU_ICON = new GIcon("icon.version.tracking.replace");
private static final Icon SCALED_ADD_ICON = ResourceManager.getScaledIcon(APPLY_ADD_MENU_ICON, 12, 12);
private static final Icon SCALED_REPLACE_ICON =ResourceManager.getScaledIcon(APPLY_REPLACE_MENU_ICON, 12, 12);
private static final Icon ADDED_ICON = new TranslateIcon(SCALED_ADD_ICON, 14, 4);
private static final Icon REPLACED_ICON = new TranslateIcon(SCALED_REPLACE_ICON, 14, 4);
private static final Icon SHIFTED_APPLIED = new TranslateIcon(APPLIED_ICON, 8, 0);
public static final Icon APPLIED_ADDED_ICON = new MultiIcon(APPLIED_ICON, ADDED_ICON);
public static final Icon APPLIED_REPLACED_ICON = new MultiIcon(APPLIED_ICON, REPLACED_ICON);
public static final Icon REJECTED_ICON = ResourceManager.loadImage("images/dialog-cancel.png");
public static final Icon DONT_CARE_ICON =
ResourceManager.loadImage("images/asterisk_orange.png");
public static final Icon DONT_KNOW_ICON = ResourceManager.loadImage("images/unknown.gif");
public static final Icon FAILED_ICON = ResourceManager.loadImage("images/edit-delete.png");
public static final Icon REJECTED_ICON = new GIcon("icon.version.tracking.markup.status.rejected");
public static final Icon DONT_CARE_ICON = new GIcon("icon.version.tracking.markup.status.dont.care");
public static final Icon DONT_KNOW_ICON = new GIcon("icon.version.tracking.markup.status.dont.know");
public static final Icon FAILED_ICON = new GIcon("icon.version.tracking.markup.status.failed");
public static final Icon SAME_ICON = new MultiIcon(APPLIED_ICON, SHIFTED_APPLIED);
public static final Icon CONFLICT_ICON = ResourceManager.loadImage("images/cache.png");
public static final Icon CONFLICT_ICON = new GIcon("icon.version.tracking.markup.status.conflict");
//@formatter:on
}

View file

@ -15,8 +15,7 @@
*/
package ghidra.feature.vt.gui.provider.markuptable;
import static ghidra.feature.vt.gui.plugin.VTPlugin.FILTERED_ICON;
import static ghidra.feature.vt.gui.plugin.VTPlugin.UNFILTERED_ICON;
import static ghidra.feature.vt.gui.plugin.VTPlugin.*;
import java.awt.*;
import java.awt.event.*;
@ -37,6 +36,7 @@ import docking.widgets.fieldpanel.internal.FieldPanelCoordinator;
import docking.widgets.table.GTable;
import docking.widgets.table.RowObjectTableModel;
import docking.widgets.table.threaded.ThreadedTableModel;
import generic.theme.GIcon;
import ghidra.app.plugin.core.functioncompare.FunctionComparisonPanel;
import ghidra.app.util.viewer.listingpanel.*;
import ghidra.app.util.viewer.util.CodeComparisonPanel;
@ -63,7 +63,6 @@ import ghidra.util.HelpLocation;
import ghidra.util.table.GhidraTable;
import ghidra.util.table.GhidraThreadedTablePanel;
import help.HelpService;
import resources.ResourceManager;
/**
* This provides the GUI for displaying and working with version tracking markup items.
@ -74,9 +73,9 @@ public class VTMarkupItemsTableProvider extends ComponentProviderAdapter
private static final String SHOW_COMPARISON_PANEL = "SHOW_COMPARISON_PANEL";
private static final Icon SHOW_LISTINGS_ICON =
ResourceManager.loadImage("images/application_tile_horizontal.png");
new GIcon("icon.version.tracking.action.show.listings");
private static final Icon FILTER_ICON = ResourceManager.loadImage("images/view-filter.png");
private static final Icon FILTER_ICON = new GIcon("icon.version.tracking.filter");
private static final String SHOW_COMPARE_ACTION_GROUP = "A9_ShowCompare"; // "A9_" forces to right of other dual view actions in toolbar.
private final VTController controller;
@ -119,7 +118,7 @@ public class VTMarkupItemsTableProvider extends ComponentProviderAdapter
this.controller = controller;
controller.addListener(this);
setWindowGroup(VTPlugin.WINDOW_GROUP);
setIcon(ResourceManager.loadImage("images/application_view_detail.png"));
setIcon(new GIcon("icon.version.tracking.provider.markup"));
setDefaultWindowPosition(WindowPosition.BOTTOM);
setIntraGroupPosition(WindowPosition.STACK);
@ -328,7 +327,9 @@ public class VTMarkupItemsTableProvider extends ComponentProviderAdapter
buffy.append("[Session: ").append(sessionName).append("] ");
buffy.append('-').append(markupItemsTableModel.getRowCount()).append(" markup items");
if (filteredCount != unfilteredCount) {
buffy.append(" (of ").append(markupItemsTableModel.getUnfilteredRowCount()).append(
buffy.append(" (of ")
.append(markupItemsTableModel.getUnfilteredRowCount())
.append(
')');
}

View file

@ -17,11 +17,13 @@ package ghidra.feature.vt.gui.provider.matchtable;
import java.awt.Color;
import java.awt.Component;
import java.net.URL;
import javax.swing.*;
import docking.widgets.table.GTableCellRenderingData;
import generic.theme.GColor;
import generic.theme.GIcon;
import ghidra.docking.settings.Settings;
import ghidra.feature.vt.api.main.*;
import ghidra.util.HTMLUtilities;
@ -29,8 +31,7 @@ import ghidra.util.WebColors;
import ghidra.util.table.column.AbstractGhidraColumnRenderer;
import resources.MultiIcon;
import resources.ResourceManager;
import resources.icons.EmptyIcon;
import resources.icons.TranslateIcon;
import resources.icons.*;
/**
* A renderer for the {@link VTMatch} to show an icon for its applied status
@ -41,33 +42,25 @@ public class MatchMarkupStatusRenderer extends AbstractGhidraColumnRenderer<VTMa
private static final Color FG_TOOLTIP_UNEXAMINED =
new GColor("color.bg.version.tracking.match.table.markup.status.tooltip.unexamined");
private static ImageIcon DISABLED_ICON =
ResourceManager.getDisabledIcon(ResourceManager.loadImage("images/ledgreen.png"), 50);
private static ImageIcon DISABLED_ICON_SMALL =
ResourceManager.getDisabledIcon(ResourceManager.loadImage("images/ledgreen.png", 8, 8), 50);
private static Icon EMPTY_ICON = ResourceManager.loadImage("EmptyIcon16.gif");
private static Icon DISABLED_ICOL =
new GIcon("icon.version.tracking.match.table.markup.status.disabled");
private static final Icon NOT_APPLIED_ICON =
new GIcon("icon.version.tracking.match.table.markup.status.not.applied");
private static final Icon APPLIED_ICON =
new GIcon("icon.version.tracking.match.table.markup.status.applied");
private static final Icon REJECTED_ICON =
new GIcon("icon.version.tracking.match.table.markup.status.rejected");
private static final Icon IGNORED_ICON =
new GIcon("icon.version.tracking.match.table.markup.status.ignored");
private static final Icon ERROR_ICON =
new GIcon("icon.version.tracking.match.table.markup.status.error");
private static final ImageIcon APPLIED_BASE_ICON =
ResourceManager.loadImage("images/ledgreen.png", 8, 8);
private static final ImageIcon REJECTED_BASE_ICON =
ResourceManager.loadImage("images/ledpurple.png", 8, 8);
private static final ImageIcon NOT_APPLIED_BASE_ICON =
ResourceManager.loadImage("images/ledorange.png", 8, 8);
private static final ImageIcon IGNORED_BASE_ICON =
ResourceManager.loadImage("images/ledblue.png", 8, 8);
private static final ImageIcon ERROR_BASE_ICON =
ResourceManager.loadImage("images/ledred.png", 8, 8);
private static Icon NOT_APPLIED_ICON = new TranslateIcon(NOT_APPLIED_BASE_ICON, 0, 4);
private static Icon APPLIED_ICON = new TranslateIcon(APPLIED_BASE_ICON, 9, 4);
private static Icon REJECTED_ICON = new TranslateIcon(REJECTED_BASE_ICON, 18, 4);
private static Icon IGNORED_ICON = new TranslateIcon(IGNORED_BASE_ICON, 27, 4);
private static Icon ERROR_ICON = new TranslateIcon(ERROR_BASE_ICON, 36, 4);
private static Icon DISABLED_NOT_APPLIED_ICON = new TranslateIcon(DISABLED_ICON_SMALL, 0, 4);
private static Icon DISABLED_APPLIED_ICON = new TranslateIcon(DISABLED_ICON_SMALL, 9, 4);
private static Icon DISABLED_REJECTED_ICON = new TranslateIcon(DISABLED_ICON_SMALL, 18, 4);
private static Icon DISABLED_IGNORED_ICON = new TranslateIcon(DISABLED_ICON_SMALL, 27, 4);
private static Icon DISABLED_ERROR_ICON = new TranslateIcon(DISABLED_ICON_SMALL, 36, 4);
private static Icon DISABLED_NOT_APPLIED_ICON = new TranslateIcon(DISABLED_ICOL, 0, 4);
private static Icon DISABLED_APPLIED_ICON = new TranslateIcon(DISABLED_ICOL, 9, 4);
private static Icon DISABLED_REJECTED_ICON = new TranslateIcon(DISABLED_ICOL, 18, 4);
private static Icon DISABLED_IGNORED_ICON = new TranslateIcon(DISABLED_ICOL, 27, 4);
private static Icon DISABLED_ERROR_ICON = new TranslateIcon(DISABLED_ICOL, 36, 4);
@Override
public Component getTableCellRendererComponent(GTableCellRenderingData data) {
@ -91,7 +84,7 @@ public class MatchMarkupStatusRenderer extends AbstractGhidraColumnRenderer<VTMa
}
VTAssociationMarkupStatus markupStatus = association.getMarkupStatus();
MultiIcon icon = new MultiIcon(new EmptyIcon(36, 16));
MultiIcon icon = new MultiIcon(new EmptyIcon(45, 16));
icon.addIcon(
markupStatus.hasUnexaminedMarkup() ? NOT_APPLIED_ICON : DISABLED_NOT_APPLIED_ICON);
icon.addIcon(markupStatus.hasAppliedMarkup() ? APPLIED_ICON : DISABLED_APPLIED_ICON);
@ -107,78 +100,86 @@ public class MatchMarkupStatusRenderer extends AbstractGhidraColumnRenderer<VTMa
private String getDescription(VTAssociationMarkupStatus status) {
StringBuffer buf = new StringBuffer("<html>");
if (!status.isInitialized()) {
buf.append("Match has not been accepted; unknown markup status");
return buf.toString();
}
ImageIcon icon = DISABLED_ICON;
Icon icon = EMPTY_ICON;
String message = "Has one or more \"Unexamined\" markup items";
Color color = FG_TOOLTIP_DEFAULT;
if (status.hasUnexaminedMarkup()) {
icon = NOT_APPLIED_BASE_ICON;
icon = NOT_APPLIED_ICON;
color = FG_TOOLTIP_UNEXAMINED;
}
String fontColor = WebColors.toString(color, false);
buf.append("<img src=\"").append(icon.getDescription()).append("\" />");
buf.append("<img src=\"").append(getIconSource(icon)).append("\" />");
buf.append("<font color=\"").append(fontColor).append("\">");
buf.append(message).append("</font><br>");
icon = DISABLED_ICON;
icon = ERROR_BASE_ICON;
icon = EMPTY_ICON;
message = "Has one or more \"Applied\" markup items";
fontColor = "gray";
if (status.hasAppliedMarkup()) {
icon = APPLIED_BASE_ICON;
icon = APPLIED_ICON;
fontColor = "black";
}
buf.append("<img src=\"").append(icon.getDescription()).append("\" />");
buf.append("<img src=\"").append(getIconSource(icon)).append("\" />");
buf.append("<font color=\"").append(fontColor).append("\">");
buf.append(message).append("</font><br>");
icon = DISABLED_ICON;
icon = DISABLED_ICON_SMALL;
icon = EMPTY_ICON;
message = "Has one or more \"Rejected\" markup items to apply";
fontColor = "gray";
if (status.hasRejectedMarkup()) {
icon = REJECTED_BASE_ICON;
icon = REJECTED_ICON;
fontColor = "black";
}
buf.append("<img src=\"").append(icon.getDescription()).append("\" />");
buf.append("<img src=\"").append(getIconSource(icon)).append("\" />");
buf.append("<font color=\"").append(fontColor).append("\">");
buf.append(message).append("</font><br>");
icon = DISABLED_ICON;
icon = EMPTY_ICON;
message = "Has one or more \"Ignored (Don't Know or Don't Care)\" markup items";
fontColor = "gray";
if (status.hasDontCareMarkup() || status.hasDontKnowMarkup()) {
icon = IGNORED_BASE_ICON;
icon = IGNORED_ICON;
fontColor = "black";
}
buf.append("<img src=\"").append(icon.getDescription()).append("\" />");
buf.append("<img src=\"").append(getIconSource(icon)).append("\" />");
buf.append("<font color=\"").append(fontColor).append("\">");
buf.append(message).append("</font><br>");
icon = DISABLED_ICON;
icon = EMPTY_ICON;
message = "Has one or more \"Error\" markup items";
fontColor = "gray";
if (status.hasErrors()) {
icon = ERROR_BASE_ICON;
icon = ERROR_ICON;
fontColor = "black";
}
buf.append("<img src=\"").append(icon.getDescription()).append("\" />");
buf.append("<img src=\"").append(getIconSource(icon)).append("\" />");
buf.append("<font color=\"").append(fontColor).append("\">");
buf.append(message).append("</font><br>");
return buf.toString();
}
private String getIconSource(Icon icon) {
if (icon instanceof GIcon gIcon) {
URL url = gIcon.getUrl();
if (url != null) {
return url.toString();
}
}
else if (icon instanceof UrlImageIcon urlIcon) {
return urlIcon.getUrl().toString();
}
return "";
}
@Override
public String getFilterString(VTMatch t, Settings settings) {

View file

@ -20,12 +20,12 @@ import java.awt.Component;
import javax.swing.*;
import docking.widgets.table.GTableCellRenderingData;
import generic.theme.GIcon;
import ghidra.docking.settings.Settings;
import ghidra.program.model.symbol.Symbol;
import ghidra.util.HTMLUtilities;
import ghidra.util.exception.AssertException;
import ghidra.util.table.column.AbstractGhidraColumnRenderer;
import resources.ResourceManager;
/**
* This class provides a field renderer for version tracking tables. It is used for indicating
@ -60,7 +60,7 @@ public class MultipleLabelsRenderer extends AbstractGhidraColumnRenderer<Symbol[
}
private static final Icon MULTIPLE_LABELS_ICON =
ResourceManager.loadImage("images/application_view_detail.png");
new GIcon("icon.version.tracking.table.renderer.multiple.symbols");
private static final String SINGLE_NAME_TOOLTIP = "Doesn't have multiple labels.";
// Uncomment the following if it is needed for the configure... method below.
// private static final String MULTI_NAME_TOOLTIP =

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,23 +15,22 @@
*/
package ghidra.feature.vt.gui.provider.matchtable;
import javax.swing.Icon;
import docking.ActionContext;
import docking.action.*;
import generic.theme.GIcon;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.OptionsService;
import ghidra.util.HelpLocation;
import javax.swing.Icon;
import resources.ResourceManager;
import docking.ActionContext;
import docking.action.*;
public class VTMatchApplySettingsAction extends DockingAction {
public static final String VERSION_TRACKING_OPTIONS_NAME = "Version Tracking";
public static final String VERSION_TRACKING_APPLY_MARKUP_OPTIONS = "Apply Markup Options";
static final Icon ICON = ResourceManager.loadImage("images/settings16.gif");
static final Icon ICON = new GIcon("icon.version.tracking.action.show.settings");
private static final String MENU_GROUP = VTPlugin.VT_SETTINGS_MENU_GROUP;
private static final String TITLE = "Version Tracking Options";

View file

@ -31,6 +31,7 @@ import docking.widgets.table.GTable;
import docking.widgets.table.RowObjectTableModel;
import docking.widgets.table.threaded.ThreadedTableModel;
import generic.theme.GColor;
import generic.theme.GIcon;
import ghidra.feature.vt.api.impl.VTChangeManager;
import ghidra.feature.vt.api.main.*;
import ghidra.feature.vt.gui.actions.*;
@ -55,7 +56,6 @@ import ghidra.util.SystemUtilities;
import ghidra.util.layout.HorizontalLayout;
import ghidra.util.table.GhidraTable;
import ghidra.util.table.GhidraThreadedTablePanel;
import resources.ResourceManager;
/**
* The docking window that provides a table of the other tool's function matches for the function
@ -65,7 +65,7 @@ public abstract class VTMatchOneToManyTableProvider extends ComponentProviderAda
implements FilterDialogModel<VTMatch>, VTControllerListener, VTSubToolManagerListener {
private static final String TITLE_PREFIX = "Version Tracking Matches for ";
private static final Icon ICON = ResourceManager.loadImage("images/text_list_bullets.png");
private static final Icon ICON = new GIcon("icon.version.tracking.provider.one.to.many");
protected static final Color LOCAL_INFO_FOREGROUND_COLOR =
new GColor("color.fg.version.tracking.function.match.local.info");

View file

@ -24,9 +24,9 @@ import javax.swing.*;
import docking.widgets.label.GIconLabel;
import docking.widgets.table.GTableCellRenderingData;
import generic.theme.GColor;
import generic.theme.GIcon;
import ghidra.feature.vt.api.main.VTAssociationStatus;
import ghidra.util.table.GhidraTableCellRenderer;
import resources.ResourceManager;
public class RelatedMatchRenderer extends GhidraTableCellRenderer {
@ -41,14 +41,14 @@ public class RelatedMatchRenderer extends GhidraTableCellRenderer {
static Map<VTRelatedMatchCorrelationType, JLabel> destinationMap;
static Map<VTAssociationStatus, JLabel> statusMap;
static final Icon TARGET_ICON = ResourceManager.loadImage("images/user-online.png");
static final Icon CALLER_ICON = ResourceManager.loadImage("images/go-down.png");
static final Icon CALLEE_ICON = ResourceManager.loadImage("images/go-next.png");
static final Icon UNRELATED_ICON = ResourceManager.loadImage("images/user-busy.png");
static final Icon TARGET_ICON = new GIcon("icon.version.tracking.related.match.target");
static final Icon CALLER_ICON = new GIcon("icon.version.tracking.related.match.caller");
static final Icon CALLEE_ICON = new GIcon("icon.version.tracking.related.match.callee");
static final Icon UNRELATED_ICON = new GIcon("icon.version.tracking.related.match.unrelated");
static final Icon ACCEPTED_ICON = ResourceManager.loadImage("images/accept.png");
static final Icon AVAILABLE_ICON = ResourceManager.loadImage("images/media-playback-stop.png");
static final Icon LOCKED_OUT_ICON = ResourceManager.loadImage("images/edit-delete.png");
static final Icon ACCEPTED_ICON = new GIcon("icon.version.tracking.related.match.accepted");
static final Icon AVAILABLE_ICON = new GIcon("icon.version.tracking.related.match.available");
static final Icon LOCKED_OUT_ICON = new GIcon("icon.version.tracking.related.match.locked.out");
private JPanel relatedMatchColumnComponent;
private GridLayout layout;

View file

@ -29,17 +29,17 @@ import docking.ActionContext;
import docking.widgets.table.GTable;
import docking.widgets.table.RowObjectTableModel;
import docking.widgets.table.threaded.ThreadedTableModel;
import generic.theme.GIcon;
import ghidra.feature.vt.api.util.VTRelatedMatch;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
import ghidra.framework.plugintool.ComponentProviderAdapter;
import ghidra.framework.plugintool.PluginTool;
import ghidra.util.table.*;
import resources.ResourceManager;
public class VTRelatedMatchesTableProvider extends ComponentProviderAdapter {
private static final Icon ICON = ResourceManager.loadImage("images/user-online.png");
private static final Icon ICON = new GIcon("icon.version.tracking.provider.related.matches");
private JComponent component;

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,18 +15,17 @@
*/
package ghidra.feature.vt.gui.util;
import ghidra.feature.vt.gui.filters.AncillaryFilterDialogComponentProvider;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import resources.ResourceManager;
import generic.theme.GIcon;
import ghidra.feature.vt.gui.filters.AncillaryFilterDialogComponentProvider;
public class FilterIconFlashTimer<T> extends Timer implements ActionListener {
private static final Icon EMPTY_ICON = ResourceManager.loadImage("images/EmptyIcon16.gif");
private static final Icon EMPTY_ICON = new GIcon("icon.version.tracking.empty");
private static final long MINIMUM_TIME_BETWEEN_FLASHES = 20000;
private static final int MAX_FLASH_COUNT = 10;

View file

@ -21,32 +21,23 @@ import javax.swing.Icon;
import javax.swing.JLabel;
import docking.widgets.table.GTableCellRenderingData;
import generic.theme.GIcon;
import ghidra.util.table.GhidraTableCellRenderer;
import resources.MultiIcon;
import resources.ResourceManager;
import resources.icons.TranslateIcon;
public class MatchStatusRenderer extends GhidraTableCellRenderer {
// private static final Icon DISABLED_APPLIED_ICON =
// ResourceManager.getDisabledIcon(ResourceManager.loadImage("images/flag.png"));
private static final Icon ACCEPTED_ICON = ResourceManager.loadImage("images/flag.png");
private static final Icon REJECTED_ICON = ResourceManager.loadImage("images/dialog-cancel.png");
// private static final Icon REJECTED_ICON = ResourceManager.loadImage("images/delete.png");
private static final Icon BLOCKED_ICON = ResourceManager.loadImage("images/kgpg.png");
// private static final ImageIcon LOCK_ICON =
// ResourceManager.loadImage("images/lock.png");
private static final Icon WARN_ICON = new TranslateIcon(
ResourceManager.loadImage("images/bullet_error.png"), 10, 8);
private static final Icon FAILURE_ICON = new TranslateIcon(ResourceManager.getScaledIcon(
ResourceManager.loadImage("images/edit-delete.png"), 8, 8), 10, 8);
private static final Icon FULLY_APPLIED_ICON = new TranslateIcon(ResourceManager.getScaledIcon(
ResourceManager.loadImage("images/checkmark_green.gif"), 8, 8), 10, 8);
private static final Icon FULLY_CONSIDERED_ICON = new TranslateIcon(
ResourceManager.getScaledIcon(ResourceManager.loadImage("images/checkmark_yellow.gif"), 8,
8), 10, 8);
private static final Icon ACCEPTED_SOME_UNEXAMINED_ICON =
new GIcon("icon.version.tracking.match.table.status.accepted.some.unexamined");
private static final Icon ACCEPTED_ERROR_ICON =
new GIcon("icon.version.tracking.match.table.status.accepted.error");
private static final Icon ACCEPTED_FULLY_APPLIED_ICON =
new GIcon("icon.version.tracking.match.table.status.accepted.fully.applied");
private static final Icon ACCEPTED_FULLY_CONSIDERED_ICON =
new GIcon("icon.version.tracking.match.table.status.accepted.fully.considered");
private static final Icon REJECTED_ICON =
new GIcon("icon.version.tracking.match.table.status.rejected");
private static final Icon BLOCKED_ICON =
new GIcon("icon.version.tracking.match.table.status.blocked");
@Override
public Component getTableCellRendererComponent(GTableCellRenderingData data) {
@ -74,16 +65,16 @@ public class MatchStatusRenderer extends GhidraTableCellRenderer {
Icon icon = null;
switch (status) {
case ACCEPTED_FULLY_APPLIED:
icon = new MultiIcon(ACCEPTED_ICON, FULLY_APPLIED_ICON);
icon = ACCEPTED_FULLY_APPLIED_ICON;
break;
case ACCEPTED_HAS_ERRORS:
icon = new MultiIcon(ACCEPTED_ICON, FAILURE_ICON);
icon = ACCEPTED_ERROR_ICON;
break;
case ACCEPTED_NO_UNEXAMINED:
icon = new MultiIcon(ACCEPTED_ICON, FULLY_CONSIDERED_ICON);
icon = ACCEPTED_FULLY_CONSIDERED_ICON;
break;
case ACCEPTED_SOME_UNEXAMINED:
icon = new MultiIcon(ACCEPTED_ICON, WARN_ICON);
icon = ACCEPTED_SOME_UNEXAMINED_ICON;
break;
case AVAILABLE:
// no icon

View file

@ -27,12 +27,12 @@ import javax.swing.event.*;
import docking.widgets.button.GRadioButton;
import docking.widgets.label.GLabel;
import docking.widgets.list.GList;
import generic.theme.GIcon;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.*;
import ghidra.program.model.listing.Program;
import ghidra.util.layout.MiddleLayout;
import ghidra.util.layout.VerticalLayout;
import resources.ResourceManager;
public class ChooseAddressSetEditorPanel extends JPanel {
@ -40,8 +40,8 @@ public class ChooseAddressSetEditorPanel extends JPanel {
ENTIRE_PROGRAM, SELECTION, MANUALLY_DEFINED
}
private static Icon ADD_ICON = ResourceManager.loadImage("images/Plus.png");
private static Icon SUBTRACT_ICON = ResourceManager.loadImage("images/list-remove.png");
private static Icon ADD_ICON = new GIcon("icon.version.tracking.add");
private static Icon SUBTRACT_ICON = new GIcon("icon.version.tracking.subtract");
private PluginTool tool;
private final String name;

View file

@ -27,6 +27,7 @@ import org.apache.commons.lang3.StringUtils;
import docking.options.editor.ButtonPanelFactory;
import docking.widgets.label.GDLabel;
import docking.wizard.*;
import generic.theme.*;
import ghidra.app.util.task.OpenProgramTask;
import ghidra.framework.main.DataTreeDialog;
import ghidra.framework.model.DomainFile;
@ -36,7 +37,6 @@ import ghidra.program.model.listing.Program;
import ghidra.util.HelpLocation;
import ghidra.util.InvalidNameException;
import ghidra.util.task.TaskLauncher;
import resources.ResourceManager;
/**
* Version tracking wizard panel to create a new session.
@ -44,8 +44,8 @@ import resources.ResourceManager;
public class NewSessionPanel extends AbstractMageJPanel<VTWizardStateKey> {
private static final int MAX_LENGTH_FOR_VT_SESSION_NAME = 20;
private static final Icon SWAP_ICON = ResourceManager.loadImage("images/doubleArrowUpDown.png");
private static final Icon INFO_ICON = ResourceManager.loadImage("images/information.png");
private static final Icon SWAP_ICON = new GIcon("icon.version.tracking.new.session.swap");
private static final Icon INFO_ICON = new GIcon("icon.version.tracking.new.session.info");
private JTextField sourceField;
private JTextField destinationField;
@ -73,7 +73,7 @@ public class NewSessionPanel extends AbstractMageJPanel<VTWizardStateKey> {
folderLabel.setHorizontalAlignment(SwingConstants.RIGHT);
folderLabel.setToolTipText("The folder to store the new Version Tracking Session");
folderNameField = new JTextField();
folderNameField.setFont(new Font("Monospaced", Font.PLAIN, 12));
Gui.registerFont(folderNameField, GThemeDefaults.Fonts.MONOSPACED);
folderNameField.setEditable(false); // force user to browse to choose
JButton browseFolderButton =

View file

@ -20,11 +20,11 @@ import java.util.*;
import javax.swing.Icon;
import docking.widgets.table.AbstractGTableModel;
import generic.theme.GIcon;
import ghidra.feature.vt.api.main.VTProgramCorrelatorFactory;
import ghidra.feature.vt.api.util.VTAbstractProgramCorrelatorFactory;
import ghidra.util.classfinder.ClassSearcher;
import ghidra.util.exception.AssertException;
import resources.ResourceManager;
public class VTProgramTableCorrelatorModel extends AbstractGTableModel<VTProgramCorrelatorFactory> {
@ -40,7 +40,8 @@ public class VTProgramTableCorrelatorModel extends AbstractGTableModel<VTProgram
return o1.getPriority() - o2.getPriority();
}
};
private static final Icon ALREADY_RUN_ICON = ResourceManager.loadImage("images/flag-green.png");
private static final Icon ALREADY_RUN_ICON =
new GIcon("icon.version.tracking.correlator.status.already.run");
private List<VTProgramCorrelatorFactory> list;
private Set<String> previouslyRunCorrelators;

View file

@ -90,36 +90,41 @@ color.bg.fieldpanel.highlight = color.bg.highlight
color.bg.fieldpanel.selection.and.highlight = green
// Icons files
icon.empty = images/EmptyIcon16.gif
icon.help = images/help-browser.png
icon.add = images/Plus2.png
icon.collapse.all = images/collapse_all.png
icon.expand.all = images/expand_all.png
icon.configure.filter = images/exec.png
icon.delete = images/error.png
icon.error = images/emblem-important.png
icon.navigate.in = images/locationIn.gif
icon.navigate.out = images/locationOut.gif
icon.notallowed = images/dialog-cancel.png
icon.folder.open = images/openSmallFolder.png
icon.refresh = images/reload3.png
icon.sort.ascending = images/sortascending.png
icon.sort.descending = images/sortdescending.png
icon.stop = images/process-stop.png
icon.warning.strong = images/software-update-urgent.png
icon.left = images/left.png
icon.right = images/right.png
icon.empty = EmptyIcon16.gif
icon.help = help-browser.png
icon.add = Plus2.png
icon.collapse.all = collapse_all.png
icon.expand.all = expand_all.png
icon.configure.filter = exec.png
icon.delete = error.png
icon.error = emblem-important.png
icon.navigate.in = locationIn.gif
icon.navigate.out = locationOut.gif
icon.not.allowed = dialog-cancel.png
icon.folder.open = openSmallFolder.png
icon.refresh = reload3.png
icon.sort.ascending = sortascending.png
icon.sort.descending = sortdescending.png
icon.stop = process-stop.png
icon.warning.strong = software-update-urgent.png
icon.left = left.png
icon.right = right.png
icon.left.alt = images/left.alternate.png
icon.right.alt = images/right.alternate.png
icon.saveas = images/disk.png
icon.makeselection = images/text_align_justify.png
icon.arrow.up.right = images/viewmagfit.png
icon.flag = images/flag.png
icon.lock = images/kgpg.png
icon.checkmark.green = images/checkmark_green.gif
icon.theme.import = images/mail-receive.png
icon.theme.export = images/mail-folder-outbox.png
icon.right.alt = right.alternate.png
icon.saveas = disk.png
icon.makeselection = text_align_justify.png
icon.arrow.down.right = viewmagfit.png[rotate(90)]
icon.arrow.up.left = viewmagfit.png[rotate(275)]
icon.flag = flag.png
icon.lock = kgpg.png
icon.checkmark.green = checkmark_green.gif
icon.filter.not.accepted = icon.flag{dialog-cancel.png[size(10,10)][move(6,6)]}
icon.blocked.match = icon.lock{icon.checkmark.green[size(12,12)][move(4,0)]}
icon.undo = undo.png
icon.redo = redo.png
icon.warning = warning.png
icon.theme.import = mail-receive.png
icon.theme.export = mail-folder-outbox.png
// Fonts

View file

@ -55,7 +55,7 @@ class ColumnFilterPanel extends JPanel {
private Component buildButtonPanel() {
JPanel panel = new JPanel(new BorderLayout());
ImageIcon icon = ResourceManager.loadImage("images/Plus.png");
Icon icon = ResourceManager.loadImage("images/Plus.png");
icon = ResourceManager.getScaledIcon(icon, BUTTON_ICON_SIZE, BUTTON_ICON_SIZE);
JButton button = new EmptyBorderButton(icon);

View file

@ -21,6 +21,8 @@ import java.awt.Color;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.text.ParseException;
import java.util.List;
import java.util.Set;
import org.apache.commons.io.FileUtils;
@ -191,6 +193,40 @@ public class ThemeUtilsTest extends AbstractDockingTest {
}
@Test
public void testParseGroupings() throws ParseException {
String source = "(ab (cd))(ef)(( gh))";
List<String> results = ThemeValueUtils.parseGroupings(source, '(', ')');
assertEquals(3, results.size());
assertEquals("ab (cd)", results.get(0));
assertEquals("ef", results.get(1));
assertEquals("( gh)", results.get(2));
}
@Test
public void testParseGroupingsParseError() {
String source = "(ab (cd))(ef)( gh))";
try {
ThemeValueUtils.parseGroupings(source, '(', ')');
fail("Expected parse Exception");
}
catch (ParseException e) {
//expected
}
}
@Test
public void testParseGroupingsParseError2() {
String source = " xx";
try {
ThemeValueUtils.parseGroupings(source, '(', ')');
fail("Expected parse Exception");
}
catch (ParseException e) {
// expected
}
}
private File createZipThemeFile(String themeName) throws IOException {
File file = createTempFile("Test_Theme", ".theme.zip");
GTheme outputTheme = new GTheme(file, themeName, LafType.METAL, false);

View file

@ -13,6 +13,7 @@
.gitignore||GHIDRA||||END|
Module.manifest||GHIDRA||||END|
data/ExtensionPoint.manifest||GHIDRA||||END|
data/generic.theme.properties||GHIDRA||||END|
src/main/java/ghidra/framework/options/package.html||GHIDRA||||END|
src/main/java/ghidra/util/datastruct/package.html||GHIDRA||||END|
src/main/java/ghidra/util/graph/attributes/package.html||GHIDRA||||END|

View file

@ -0,0 +1,11 @@
[Defaults]
// Fonts
font.standard = [font]panel.font
font.monospaced = font.standard[monospaced]
font.bold = font.standard[bold]
font.italics = font.standard[italic]
font.bold.italic = font.standard[bold][italic]
[Dark Defaults]

View file

@ -16,6 +16,7 @@
package generic.theme;
import java.io.*;
import java.text.ParseException;
import java.util.*;
import ghidra.util.Msg;
@ -84,7 +85,7 @@ public abstract class AbstractThemeReader {
}
else if (IconValue.isIconKey(key)) {
if (!GTheme.JAVA_ICON.equals(value)) {
valueMap.addIcon(parseIconProperty(key, value));
valueMap.addIcon(parseIconProperty(key, value, lineNumber));
}
}
else {
@ -93,9 +94,15 @@ public abstract class AbstractThemeReader {
}
}
private IconValue parseIconProperty(String key, String value) {
private IconValue parseIconProperty(String key, String value, int lineNumber) {
try {
return IconValue.parse(key, value);
}
catch (ParseException e) {
error(lineNumber, "Could not parse Icon value: " + value + "because " + e.getMessage());
}
return null;
}
private FontValue parseFontProperty(String key, String value, int lineNumber) {
try {

View file

@ -16,9 +16,15 @@
package generic.theme;
import java.awt.Font;
import java.util.*;
import java.text.ParseException;
import java.util.List;
import java.util.regex.Pattern;
/**
* Class that can transform one font into another. For example if want a font that is the same
* basic font as some other font, but is just a different size,style, or family, you use a
* FontModifier
*/
public class FontModifier {
private static final Pattern MODIFIER_PATTERN = Pattern.compile("(\\[([a-zA-Z]+|[0-9]+)\\])*");
@ -26,16 +32,26 @@ public class FontModifier {
private Integer style;
private Integer size;
public FontModifier() {
private FontModifier() {
}
/**
* Creates a new FontModifier that can change a given font by one or more font properties.
* @param family if non-null, modifies a font to use this family
* @param style if non-null, modifies a font to use this style
* @param size if non-null, modifies a font to be this size
*/
public FontModifier(String family, Integer style, Integer size) {
this.family = family;
this.style = style;
this.size = size;
}
/**
* Sets the family for modifying a font
* @param newFamily the font family to use when modifying fonts
*/
public void addFamilyModifier(String newFamily) {
if (family != null) {
throw new IllegalStateException("Multiple font family names specified");
@ -43,6 +59,10 @@ public class FontModifier {
this.family = newFamily;
}
/**
* Sets the font size modifier
* @param newSize the size to use when modifying fonts
*/
public void addSizeModfier(int newSize) {
if (size != null) {
throw new IllegalStateException("Multiple font sizes specified");
@ -50,6 +70,10 @@ public class FontModifier {
this.size = newSize;
}
/**
* Sets the font stle modifier. This can be called multiple times to bold and italicize.
* @param newStyle the style to use for the font.
*/
public void addStyleModifier(int newStyle) {
if (style == null) {
style = newStyle;
@ -61,6 +85,11 @@ public class FontModifier {
style = style | newStyle;
}
/**
* Returns a modified font for the given font.
* @param font the font to be modified
* @return a new modified font
*/
public Font modify(Font font) {
if (family == null) {
if (style != null && size != null) {
@ -76,27 +105,10 @@ public class FontModifier {
return new Font(family, newStyle, newSize);
}
public static FontModifier parse(String value) {
List<String> modifierValues = getModifierPieces(value);
if (modifierValues.isEmpty()) {
return null;
}
FontModifier modifier = new FontModifier();
for (String modifierString : modifierValues) {
if (setSize(modifier, modifierString)) {
continue;
}
if (setStyle(modifier, modifierString)) {
continue;
}
modifier.addFamilyModifier(modifierString);
}
if (modifier.hadModifications()) {
return modifier;
}
return null;
}
/**
* Returns a string that can be parsed by the {@link #parse(String)} method of this class
* @return a string that can be parsed by the {@link #parse(String)} method of this class
*/
public String getSerializationString() {
StringBuilder builder = new StringBuilder();
if (family != null) {
@ -125,14 +137,58 @@ public class FontModifier {
return builder.toString();
}
/**
* Parses the given string as one or more font modifiers
* @param value the string to parse as modifiers
* @return a FontModifier as specified by the given string
* @throws ParseException if The value can't be parsed
*/
public static FontModifier parse(String value) throws ParseException {
List<String> modifierValues = ThemeValueUtils.parseGroupings(value, '[', ']');
if (modifierValues.isEmpty()) {
return null;
}
FontModifier modifier = new FontModifier();
for (String modifierString : modifierValues) {
if (setSize(modifier, modifierString)) {
continue;
}
if (setStyle(modifier, modifierString)) {
continue;
}
setFamily(modifier, modifierString);
}
if (modifier.hadModifications()) {
return modifier;
}
return null;
}
private static void setFamily(FontModifier modifier, String modifierString)
throws ParseException {
try {
modifier.addFamilyModifier(modifierString);
}
catch (IllegalStateException e) {
throw new ParseException("Multiple Font Families specfied", 0);
}
}
private boolean hadModifications() {
return family != null || size != null || style != null;
}
private static boolean setStyle(FontModifier modifier, String modifierString) {
private static boolean setStyle(FontModifier modifier, String modifierString)
throws ParseException {
int style = FontValue.getStyle(modifierString);
if (style >= 0) {
try {
modifier.addStyleModifier(style);
}
catch (IllegalStateException e) {
throw new ParseException("Illegal style combination", 0);
}
return true;
}
return false;
@ -149,18 +205,4 @@ public class FontModifier {
}
}
private static List<String> getModifierPieces(String value) {
if (!MODIFIER_PATTERN.matcher(value).matches()) {
throw new IllegalArgumentException("Invalid font modifier string");
}
StringTokenizer tokenizer = new StringTokenizer(value, "[]");
List<String> list = new ArrayList<>();
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken().trim();
if (!token.isBlank()) {
list.add(token);
}
}
return list;
}
}

View file

@ -16,6 +16,7 @@
package generic.theme;
import java.awt.Font;
import java.text.ParseException;
import ghidra.util.Msg;
@ -75,7 +76,7 @@ public class FontValue extends ThemeValue<Font> {
if (referenceId != null) {
String refId = toExternalId(referenceId);
if (modifier != null) {
return "(" + refId + modifier.getSerializationString() + ")";
return refId + modifier.getSerializationString();
}
return refId;
}
@ -106,8 +107,9 @@ public class FontValue extends ThemeValue<Font> {
* @param key the key to associate the parsed value with
* @param value the font value to parse
* @return a FontValue with the given key and the parsed value
* @throws ParseException
*/
public static FontValue parse(String key, String value) {
public static FontValue parse(String key, String value) throws ParseException {
String id = fromExternalId(key);
value = clean(value);
@ -184,7 +186,7 @@ public class FontValue extends ThemeValue<Font> {
return null;
}
private static FontValue getRefFontValue(String id, String value) {
private static FontValue getRefFontValue(String id, String value) throws ParseException {
if (value.startsWith(EXTERNAL_PREFIX)) {
value = value.substring(EXTERNAL_PREFIX.length());
}

View file

@ -24,7 +24,7 @@ import javax.swing.ImageIcon;
import ghidra.util.datastruct.WeakStore;
import resources.ResourceManager;
import resources.icons.UrlImageIcon;
import resources.icons.*;
/**
* An {@link Icon} whose value is dynamically determined by looking up its id into a global
@ -89,10 +89,24 @@ public class GIcon implements Icon {
* @return the icon or null
*/
public URL getUrl() {
if (delegate instanceof UrlImageIcon) {
return ((UrlImageIcon) delegate).getUrl();
return getUrl(delegate);
}
private URL getUrl(Icon icon) {
if (icon instanceof UrlImageIcon urlIcon) {
return urlIcon.getUrl();
}
else if (icon instanceof TranslateIcon translateIcon) {
return getUrl(translateIcon.getBaseIcon());
}
else if (icon instanceof DerivedImageIcon derivedIcon) {
return getUrl(derivedIcon.getSourceIcon());
}
else if (icon instanceof RotateIcon rotateIcon) {
return getUrl(rotateIcon.getSourceIcon());
}
return null;
}
/**

View file

@ -125,4 +125,12 @@ public class GThemeDefaults {
}
}
}
public static class Fonts {
public static final String STANDARD = "font.standard";
public static final String BOLD = "font.bold";
public static final String ITALIC = "font.italic";
public static final String BOLD_ITALIC = "font.bold.italic";
public static final String MONOSPACED = "font.monospaced";
}
}

View file

@ -0,0 +1,295 @@
/* ###
* 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 generic.theme;
import java.awt.Dimension;
import java.awt.Point;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Icon;
//font.foo = images/flag.png[size(12,16)][move(3,4)][disable]
import resources.MultiIcon;
import resources.ResourceManager;
import resources.icons.RotateIcon;
import resources.icons.TranslateIcon;
/**
* Class that can transform one icon into another. Useful for scaling, translating, disabling,
* or overlaying an icon.
*/
public class IconModifier {
Dimension size;
Point translation;
boolean disabled;
Integer rotation;
List<IconValue> overlayIconValues = null;
/**
* Creates an IconModifier that can scale, translate, or disable an icon.
* @param size if non-null, scales an icon to this size.
* @param translation if non-null, translates an icon by this amount
* @param rotation if non-null, the amount in degrees to rotate the icon
* @param disabled if true, creates a disabled version of the icon
*/
public IconModifier(Dimension size, Point translation, Integer rotation, boolean disabled) {
this.size = size;
this.translation = translation;
this.rotation = rotation;
this.disabled = disabled;
}
private IconModifier() {
}
/**
* Sets size modifier. Icons that are modified by this IconModifier will be scaled to this size.
* @param size the size to scale modified icons.
*/
public void setSizeModifier(Dimension size) {
this.size = size;
}
/**
* Sets the translation for this modifier. Icons that are modified by this IconModifier will
* be translated by the amount of the given point.
* @param point the x,y amount to translate an image
*/
public void setMoveModifier(Point point) {
this.translation = point;
}
/**
* Sets the rotation for this modifier. Icons that are modified by this IconModifier will
* be rotated by the given amount (in degrees)
* @param degrees the rotation amount;
*/
public void setRotationModifer(int degrees) {
this.rotation = degrees;
}
/**
* Sets this modifier to disable an icon
*/
public void setDisabled() {
disabled = true;
}
/**
* Modifies the given icon by the any of the modifiers set.
* @param icon the icon to be modified
* @param values the ThemeValueMap needed if the modify action is to overlay other icons. The
* values are used to resolve indirect overlay icon references
* @return A new Icon that is a modified version of the given icon
*/
public Icon modify(Icon icon, GThemeValueMap values) {
Icon modified = icon;
if (size != null) {
modified = ResourceManager.getScaledIcon(modified, size.width, size.height);
}
if (disabled) {
modified = ResourceManager.getDisabledIcon(modified);
}
if (rotation != null) {
modified = new RotateIcon(icon, rotation);
}
if (translation != null) {
modified = new TranslateIcon(modified, translation.x, translation.y);
}
if (overlayIconValues != null) {
MultiIcon multiIcon = new MultiIcon(modified);
for (IconValue iconValue : overlayIconValues) {
multiIcon.addIcon(iconValue.get(values));
}
modified = multiIcon;
}
return modified;
}
/**
* Returns a string that can be parsed by the {@link #parse(String)} method of this class
* @return a string that can be parsed by the {@link #parse(String)} method of this class
*/
public String getSerializationString() {
StringBuilder builder = new StringBuilder();
if (size != null) {
builder.append("[" + "size(" + size.width + "," + size.height + ")]");
}
if (rotation != null) {
builder.append("[rotate(" + rotation + ")]");
}
if (translation != null) {
builder.append("[" + "move(" + translation.x + "," + translation.y + ")]");
}
if (disabled) {
builder.append("[disabled]");
}
return builder.toString();
}
/**
* Parses the given string as one or more icon modifiers
* @param iconModifierString the string to parse as modifiers
* @return an IconModifier as specified by the given string
* @throws ParseException if the iconModifierString in not properly formatted icon modifier
*/
public static IconModifier parse(String iconModifierString) throws ParseException {
if (iconModifierString.isBlank()) {
return null;
}
IconModifier modifier = new IconModifier();
String baseModifierString = getBaseModifierString(iconModifierString);
parseBaseModifiers(modifier, baseModifierString);
String overlayValuesString = getIconOverlaysString(iconModifierString);
parseOverlayModifiers(modifier, overlayValuesString);
if (modifier.hadModifications()) {
return modifier;
}
return null;
}
private static void parseOverlayModifiers(IconModifier modifier, String overlayValuesString)
throws ParseException {
List<String> overlayModifierStrings =
ThemeValueUtils.parseGroupings(overlayValuesString, '{', '}');
for (String overlayIconString : overlayModifierStrings) {
IconValue overlayIconValue = IconValue.parse("", overlayIconString);
modifier.addOverlayIcon(overlayIconValue);
}
}
private void addOverlayIcon(IconValue overlayIconValue) {
if (overlayIconValues == null) {
overlayIconValues = new ArrayList<>();
}
overlayIconValues.add(overlayIconValue);
}
private static void parseBaseModifiers(IconModifier modifier, String baseModifierString)
throws ParseException {
List<String> modifierValues = ThemeValueUtils.parseGroupings(baseModifierString, '[', ']');
for (String modifierString : modifierValues) {
modifierString = modifierString.replaceAll("\\s", "").toLowerCase();
if (modifierString.startsWith("size")) {
parseSizeModifier(modifier, modifierString);
}
else if (modifierString.startsWith("move")) {
parseMoveModifier(modifier, modifierString);
}
else if (modifierString.startsWith("rotate")) {
parseRotateModifier(modifier, modifierString);
}
else if (modifierString.startsWith("disabled")) {
parseDisabledModifier(modifier, modifierString);
}
else {
throw new ParseException("Invalid icon modifier: " + modifierString, 0);
}
}
}
private static String getBaseModifierString(String value) {
int overlayStart = value.indexOf("{");
if (overlayStart < 0) {
return value;
}
if (overlayStart == 0) {
return "";
}
return value.substring(0, overlayStart);
}
private static String getIconOverlaysString(String value) {
int overlayStart = value.indexOf("{");
if (overlayStart >= 0) {
return value.substring(overlayStart);
}
return "";
}
private boolean hadModifications() {
return size != null || translation != null || overlayIconValues != null ||
rotation != null || disabled;
}
private static void parseDisabledModifier(IconModifier modifier, String modifierString)
throws ParseException {
if (!modifierString.equals("disabled")) {
throw new ParseException("Illegal Icon modifier: " + modifier, 0);
}
modifier.setDisabled();
}
private static void parseRotateModifier(IconModifier modifier, String modifierString)
throws ParseException {
String argsString = modifierString.substring("rotate".length());
int rotation = parseIntArg(argsString);
modifier.setRotationModifer(rotation);
}
private static void parseMoveModifier(IconModifier modifier, String modifierString)
throws ParseException {
String argsString = modifierString.substring("move".length());
Point argValue = parsePointArgs(argsString);
modifier.setMoveModifier(argValue);
}
private static void parseSizeModifier(IconModifier modifier, String modifierString)
throws ParseException {
String argsString = modifierString.substring("size".length());
Point argValue = parsePointArgs(argsString);
modifier.setSizeModifier(new Dimension(argValue.x, argValue.y));
}
private static Point parsePointArgs(String argsString) throws ParseException {
if (!(argsString.startsWith("(") && argsString.endsWith(")"))) {
throw new ParseException("Invalid arguments: " + argsString, 0);
}
argsString = argsString.substring(1, argsString.length() - 1);
String[] split = argsString.split(",");
if (split.length != 2) {
throw new ParseException("Invalid arguments: " + argsString, 0);
}
try {
int arg1 = Integer.parseInt(split[0]);
int arg2 = Integer.parseInt(split[1]);
return new Point(arg1, arg2);
}
catch (NumberFormatException e) {
throw new ParseException("Invalid arguments: " + argsString, 0);
}
}
private static int parseIntArg(String argString) throws ParseException {
if (!(argString.startsWith("(") && argString.endsWith(")"))) {
throw new ParseException("Invalid arguments: " + argString, 0);
}
argString = argString.substring(1, argString.length() - 1);
try {
return Integer.parseInt(argString);
}
catch (NumberFormatException e) {
throw new ParseException("Invalid arguments: " + argString, 0);
}
}
}

View file

@ -15,10 +15,13 @@
*/
package generic.theme;
import java.text.ParseException;
import javax.swing.Icon;
import ghidra.util.Msg;
import resources.ResourceManager;
import resources.icons.EmptyIcon;
import resources.icons.UrlImageIcon;
/**
@ -28,12 +31,18 @@ import resources.icons.UrlImageIcon;
* and if the class's refId is non-null, then the icon value will be null.
*/
public class IconValue extends ThemeValue<Icon> {
private static final String EMPTY_ICON_STRING = "EMPTY_ICON";
static final String ICON_ID_PREFIX = "icon.";
public static final Icon LAST_RESORT_DEFAULT = ResourceManager.getDefaultIcon();
private static final String EXTERNAL_PREFIX = "[icon]";
private static final int STANDARD_EMPTY_ICON_SIZE = 16;
private IconModifier modifier;
/**
* Constructor used when the ColorValue will have a direct {@link Icon} value. The refId will
* be null. Note: if a {@link GIcon} is passed in as the value, then this will be an indirect
@ -55,6 +64,25 @@ public class IconValue extends ThemeValue<Icon> {
super(id, refId, null);
}
private IconValue(String id, String refId, IconModifier modifier) {
super(id, refId, null);
this.modifier = modifier;
}
private IconValue(String id, Icon icon, IconModifier modifier) {
super(id, null, icon);
this.modifier = modifier;
}
@Override
public Icon get(GThemeValueMap values) {
Icon icon = super.get(values);
if (modifier != null) {
return modifier.modify(icon, values);
}
return icon;
}
@Override
public String getSerializationString() {
String outputId = toExternalId(id);
@ -76,6 +104,15 @@ public class IconValue extends ThemeValue<Icon> {
* @return a String that represents the icon
*/
public static String iconToString(Icon icon) {
if (icon instanceof EmptyIcon) {
int iconWidth = icon.getIconWidth();
int iconHeight = icon.getIconHeight();
if (iconWidth == STANDARD_EMPTY_ICON_SIZE && iconHeight == STANDARD_EMPTY_ICON_SIZE) {
return EMPTY_ICON_STRING;
}
return EMPTY_ICON_STRING + "[size(" + iconWidth + "," + iconHeight + ")]";
}
if (icon instanceof UrlImageIcon urlIcon) {
return urlIcon.getOriginalPath();
}
@ -88,14 +125,60 @@ public class IconValue extends ThemeValue<Icon> {
* @param key the key to associate the parsed value with
* @param value the color value to parse
* @return an IconValue with the given key and the parsed value
* @throws ParseException
*/
public static IconValue parse(String key, String value) {
public static IconValue parse(String key, String value) throws ParseException {
String id = fromExternalId(key);
if (isIconKey(value)) {
return new IconValue(id, fromExternalId(value));
return parseRefIcon(id, value);
}
Icon icon = ResourceManager.loadImage(value);
return new IconValue(id, icon);
return parseIcon(id, value);
}
private static IconValue parseIcon(String id, String value) throws ParseException {
int modifierIndex = getModifierIndex(value);
if (modifierIndex < 0) {
return new IconValue(id, getIcon(value));
}
String baseIconString = value.substring(0, modifierIndex).trim();
Icon icon = getIcon(baseIconString);
String iconModifierString = value.substring(modifierIndex);
IconModifier modifier = IconModifier.parse(iconModifierString);
return new IconValue(id, icon, modifier);
}
private static Icon getIcon(String baseIconString) {
if (EMPTY_ICON_STRING.equals(baseIconString)) {
return new EmptyIcon(STANDARD_EMPTY_ICON_SIZE, STANDARD_EMPTY_ICON_SIZE);
}
return ResourceManager.loadImage(baseIconString);
}
private static IconValue parseRefIcon(String id, String value) throws ParseException {
if (value.startsWith(EXTERNAL_PREFIX)) {
value = value.substring(EXTERNAL_PREFIX.length());
}
int modifierIndex = getModifierIndex(value);
if (modifierIndex < 0) {
return new IconValue(id, value);
}
String refId = value.substring(0, modifierIndex).trim();
IconModifier modifier = IconModifier.parse(value.substring(modifierIndex));
return new IconValue(id, refId, modifier);
}
private static int getModifierIndex(String value) {
int baseModifierIndex = value.indexOf("[", 1); // start past first char as it coud be valid "[EXTERNAL]" prefix
int overlayModifierIndex = value.indexOf("{");
if (baseModifierIndex < 0) {
return overlayModifierIndex;
}
if (overlayModifierIndex < 0) {
return baseModifierIndex;
}
return Math.min(overlayModifierIndex, baseModifierIndex);
}
@Override
@ -140,10 +223,17 @@ public class IconValue extends ThemeValue<Icon> {
}
private String getValueOutput() {
String outputString = null;
if (referenceId != null) {
return toExternalId(referenceId);
outputString = toExternalId(referenceId);
}
return iconToString(value);
else {
outputString = iconToString(value);
}
if (modifier != null) {
outputString += modifier.getSerializationString();
}
return outputString;
}
@Override

View file

@ -0,0 +1,84 @@
/* ###
* 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 generic.theme;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
public class ThemeValueUtils {
/**
* Parses the given source string into a list of strings, one for each group. The startChar
* and endChar defined the group characters. So, for example, "(ab (cd))(ef)((gh))" would
* result in a list with the following values: "ab (cd)", "ef", and "(gh)"
* @param source the source string to parse into groups
* @param startChar the character that defines the start of a group
* @param endChar the character that defines then end of a group
* @return a List of strings, one for each consecutive group contained in the string
* @throws ParseException if the groupings are not balanced or missing altogether
*/
public static List<String> parseGroupings(String source, char startChar, char endChar)
throws ParseException {
List<String> results = new ArrayList<>();
int index = 0;
while (index < source.length()) {
int groupStart = findNextNonWhiteSpaceChar(source, index);
if (groupStart < 0) {
break;
}
if (source.charAt(groupStart) != startChar) {
throw new ParseException("Error parsing groupings for " + source, index);
}
int groupEnd = findMatchingEnd(source, groupStart + 1, startChar, endChar);
if (groupEnd < 0) {
throw new ParseException("Error parsing groupings for " + source, index);
}
results.add(source.substring(groupStart + 1, groupEnd));
index = groupEnd + 1;
}
return results;
}
private static int findMatchingEnd(String source, int index, char startChar, char endChar) {
int level = 0;
while (index < source.length()) {
char c = source.charAt(index);
if (c == startChar) {
level++;
}
else if (c == endChar) {
if (level == 0) {
return index;
}
level--;
}
index++;
}
return -1;
}
private static int findNextNonWhiteSpaceChar(String source, int index) {
while (index < source.length()) {
if (!Character.isWhitespace(source.charAt(index))) {
return index;
}
index++;
}
return -1;
}
}

View file

@ -26,8 +26,6 @@ import javax.swing.ImageIcon;
import generic.theme.GIcon;
import generic.theme.GThemeDefaults.Colors;
import ghidra.util.Msg;
import resources.icons.RotateIcon;
import resources.icons.TranslateIcon;
/**
* A class to get generic icons for standard actions. All methods in this class return an
@ -51,7 +49,7 @@ public class Icons {
public static final Icon NAVIGATE_ON_INCOMING_EVENT_ICON = new GIcon("icon.navigate.in");
public static final Icon NAVIGATE_ON_OUTGOING_EVENT_ICON = new GIcon("icon.navigate.out");
public static final Icon NOT_ALLOWED_ICON = new GIcon("icon.notallowed");
public static final Icon NOT_ALLOWED_ICON = new GIcon("icon.not.allowed");
public static final Icon OPEN_FOLDER_ICON = new GIcon("icon.folder.open");
public static final Icon REFRESH_ICON = new GIcon("icon.refresh");
@ -78,16 +76,10 @@ public class Icons {
// 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.
public static final Icon ARROW_DOWN_RIGHT_ICON =
ResourceManager.getImageIcon(new RotateIcon(new GIcon("icon.arrow.up.right"), 90));
public static final Icon ARROW_UP_LEFT_ICON =
ResourceManager.getImageIcon(new RotateIcon(new GIcon("icon.arrow.up.right"), 275));
public static final Icon FILTER_NOT_ACCEPTED_ICON =
ResourceManager.getImageIcon(new MultiIcon(new GIcon("icon.flag"),
new TranslateIcon(ResourceManager.loadImage("icon.notallowed", 10, 10), 6, 6)));
public static final Icon APPLY_BLOCKED_MATCH_ICON =
ResourceManager.getImageIcon(new MultiIcon(new GIcon("icon.lock"),
new TranslateIcon(ResourceManager.loadImage("icon.checkmark.green", 12, 12), 4, 0)));
public static final Icon ARROW_DOWN_RIGHT_ICON = new GIcon("icon.arrow.down.right");
public static final Icon ARROW_UP_LEFT_ICON = new GIcon("icon.arrow.up.left");
public static final Icon FILTER_NOT_ACCEPTED_ICON = new GIcon("icon.filter.not.accepted");
public static final Icon APPLY_BLOCKED_MATCH_ICON = new GIcon("icon.blocked.match");
/**
* Returns true if the given string is a Java code snippet that references this class

View file

@ -52,7 +52,7 @@ public class MultiIconBuilder {
* @return this builder (for chaining)
*/
public MultiIconBuilder addIcon(Icon icon, int w, int h, QUADRANT quandrant) {
ImageIcon scaled = ResourceManager.getScaledIcon(icon, w, h);
Icon scaled = ResourceManager.getScaledIcon(icon, w, h);
int x = (multiIcon.getIconWidth() - scaled.getIconWidth()) * quandrant.x;
int y = (multiIcon.getIconHeight() - scaled.getIconHeight()) * quandrant.y;
@ -75,7 +75,7 @@ public class MultiIconBuilder {
* @return this builder (for chaining)
*/
public MultiIconBuilder addIcon(Icon icon, int w, int h, int x, int y) {
ImageIcon scaled = ResourceManager.getScaledIcon(icon, w, h);
Icon scaled = ResourceManager.getScaledIcon(icon, w, h);
TranslateIcon txIcon = new TranslateIcon(scaled, x, y);
multiIcon.addIcon(txIcon);
return this;

View file

@ -338,7 +338,25 @@ public class ResourceManager {
* @param height the height of the new icon
* @return A new, scaled ImageIcon
*/
public static ImageIcon getScaledIcon(Icon icon, int width, int height) {
public static ImageIcon getScaledIcon(ImageIcon icon, int width, int height) {
return new ScaledImageIcon(icon, width, height);
}
/**
* Creates a scaled Icon from the given icon with scaling of
* {@link Image#SCALE_AREA_AVERAGING}. If an EmptyIcon is passed, a new EmptyIcon is returned
* with the new dimensions.
*
* @param icon the icon to scale
* @param width the width of the new icon
* @param height the height of the new icon
* @return A new, scaled ImageIcon
*/
public static Icon getScaledIcon(Icon icon, int width, int height) {
if (icon instanceof EmptyIcon) {
return new EmptyIcon(width, height);
}
return new ScaledImageIcon(icon, width, height);
}
@ -478,7 +496,7 @@ public class ResourceManager {
if (loadImage == null) {
return null;
}
return getScaledIcon(loadImage, width, height);
return (ImageIcon) getScaledIcon(loadImage, width, height);
}
/**
@ -514,6 +532,7 @@ public class ResourceManager {
if (icon == null) {
icon = doLoadIcon(filename);
if (icon == null) {
Msg.warn(ResourceManager.class, "Can't resolve icon: " + filename);
icon = new UnresolvedIcon(filename, getDefaultIcon());
}
iconMap.put(filename, icon);

View file

@ -52,6 +52,10 @@ public class DerivedImageIcon extends LazyImageIcon {
this.sourceImage = Objects.requireNonNull(image);
}
public Icon getSourceIcon() {
return sourceIcon;
}
protected ImageIcon createImageIcon() {
Image image = createImage();
String imageName = getFilename();

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.
@ -18,6 +17,7 @@ package resources.icons;
import java.awt.Component;
import java.awt.Graphics;
import java.util.Objects;
import javax.swing.Icon;
@ -43,4 +43,29 @@ public class EmptyIcon implements Icon {
// no-op
}
@Override
public int hashCode() {
return Objects.hash(height, width);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
EmptyIcon other = (EmptyIcon) obj;
return height == other.height && width == other.width;
}
@Override
public String toString() {
return "EmptyIcon(" + width + "," + height + ")";
}
}

View file

@ -60,4 +60,20 @@ public class RotateIcon implements Icon {
}
return description;
}
/**
* The source icon being rotated.
* @return the source icon being rotate
*/
public Icon getSourceIcon() {
return icon;
}
/**
* Returns the rotation amount.
* @return the rotation amount
*/
public int getRotation() {
return degrees;
}
}

View file

@ -58,4 +58,29 @@ public class TranslateIcon implements Icon {
public String toString() {
return getClass().getSimpleName() + "[" + ResourceManager.getIconName(icon) + "]";
}
// for testing
/**
* Returns the icon that is being translated
* @return the icon that is being translated
*/
public Icon getBaseIcon() {
return icon;
}
/**
* Returns the amount the icon is being translated on the x axis;
* @return the amount the icon is being translated on the x axis;
*/
public int getX() {
return translateX;
}
/**
* Returns the amount the icon is being translated on the y axis;
* @return the amount the icon is being translated on the y axis;
*/
public int getY() {
return translateY;
}
}

View file

@ -18,6 +18,7 @@ package generic.theme;
import static org.junit.Assert.*;
import java.awt.Font;
import java.text.ParseException;
import org.junit.Test;
@ -25,12 +26,12 @@ public class FontModifierTest {
private Font baseFont = new Font("Dialog", Font.PLAIN, 12);
@Test
public void testNoModifiers() {
public void testNoModifiers() throws ParseException {
assertNull(FontModifier.parse(""));
}
@Test
public void testSizeModifier() {
public void testSizeModifier() throws ParseException {
FontModifier modifier = FontModifier.parse("[6]");
assertNotNull(modifier);
Font newFont = modifier.modify(baseFont);
@ -40,7 +41,7 @@ public class FontModifierTest {
}
@Test
public void testStyleModifierPlain() {
public void testStyleModifierPlain() throws ParseException {
FontModifier modifier = FontModifier.parse("[plain]");
assertNotNull(modifier);
Font newFont = modifier.modify(baseFont);
@ -50,7 +51,7 @@ public class FontModifierTest {
}
@Test
public void testStyleModifierBold() {
public void testStyleModifierBold() throws ParseException {
FontModifier modifier = FontModifier.parse("[bold]");
assertNotNull(modifier);
Font newFont = modifier.modify(baseFont);
@ -60,7 +61,7 @@ public class FontModifierTest {
}
@Test
public void testStyleModifierItalic() {
public void testStyleModifierItalic() throws ParseException {
FontModifier modifier = FontModifier.parse("[ITALIC]");
assertNotNull(modifier);
Font newFont = modifier.modify(baseFont);
@ -70,7 +71,7 @@ public class FontModifierTest {
}
@Test
public void testStyleModifierBoldItalic() {
public void testStyleModifierBoldItalic() throws ParseException {
FontModifier modifier = FontModifier.parse("[BOLDitalic]");
assertNotNull(modifier);
Font newFont = modifier.modify(baseFont);
@ -80,7 +81,7 @@ public class FontModifierTest {
}
@Test
public void testStyleModifierBoldItalic2() {
public void testStyleModifierBoldItalic2() throws ParseException {
FontModifier modifier = FontModifier.parse("[BOLD][italic]");
assertNotNull(modifier);
Font newFont = modifier.modify(baseFont);
@ -90,7 +91,7 @@ public class FontModifierTest {
}
@Test
public void testFamilyModification() {
public void testFamilyModification() throws ParseException {
FontModifier modifier = FontModifier.parse("[monospaced]");
assertNotNull(modifier);
Font newFont = modifier.modify(baseFont);
@ -100,7 +101,7 @@ public class FontModifierTest {
}
@Test
public void testSizeAndStyleModification() {
public void testSizeAndStyleModification() throws ParseException {
FontModifier modifier = FontModifier.parse("[16][bold]");
assertNotNull(modifier);
Font newFont = modifier.modify(baseFont);
@ -116,7 +117,7 @@ public class FontModifierTest {
FontModifier.parse("[monospaced][courier]");
fail("Expecected Exception");
}
catch (IllegalStateException e) {
catch (ParseException e) {
// expected
}
}
@ -127,7 +128,7 @@ public class FontModifierTest {
FontModifier.parse("[plain][italic]");
fail("Expected IllegalStateException");
}
catch (IllegalStateException e) {
catch (ParseException e) {
// expected
}
}
@ -138,7 +139,7 @@ public class FontModifierTest {
FontModifier.parse("asdfasf");
fail("Expected IllegalArgumentExcption");
}
catch (IllegalArgumentException e) {
catch (ParseException e) {
// expected
}
}
@ -149,7 +150,7 @@ public class FontModifierTest {
FontModifier.parse("[12]aa[13]");
fail("Expected IllegalArgumentExcption");
}
catch (IllegalArgumentException e) {
catch (ParseException e) {
// expected
}
}
@ -160,7 +161,7 @@ public class FontModifierTest {
FontModifier.parse("[12]aa13]");
fail("Expected IllegalArgumentExcption");
}
catch (IllegalArgumentException e) {
catch (ParseException e) {
// expected
}
}
@ -171,7 +172,7 @@ public class FontModifierTest {
FontModifier.parse("[12][plain]sz");
fail("Expected IllegalArgumentExcption");
}
catch (IllegalArgumentException e) {
catch (ParseException e) {
// expected
}
}

View file

@ -18,6 +18,7 @@ package generic.theme;
import static org.junit.Assert.*;
import java.awt.Font;
import java.text.ParseException;
import org.junit.Before;
import org.junit.Test;
@ -97,7 +98,7 @@ public class FontValueTest {
}
@Test
public void testParse() {
public void testParse() throws ParseException {
FontValue value = FontValue.parse("font.test", "Dialog-PLAIN-12");
assertEquals("font.test", value.getId());
assertEquals(FONT, value.getRawValue());

View file

@ -0,0 +1,189 @@
/* ###
* 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 generic.theme;
import static org.junit.Assert.*;
import java.awt.Dimension;
import java.awt.Point;
import java.text.ParseException;
import javax.swing.Icon;
import org.junit.Test;
import resources.MultiIcon;
import resources.ResourceManager;
import resources.icons.RotateIcon;
import resources.icons.TranslateIcon;
public class IconModifierTest {
private Icon baseIcon = ResourceManager.getDefaultIcon();
private GThemeValueMap values = new GThemeValueMap();
@Test
public void testNoModifiers() throws Exception {
assertNull(IconModifier.parse(""));
}
@Test
public void testSizeModifier() throws Exception {
IconModifier modifier = IconModifier.parse("[size(7,13)]");
Icon modifiedIcon = modifier.modify(baseIcon, values);
assertEquals(7, modifiedIcon.getIconWidth());
assertEquals(13, modifiedIcon.getIconHeight());
}
@Test
public void testSizeModifier2() throws Exception {
IconModifier modifier = IconModifier.parse("[SIZE(7,13)]");
Icon modifiedIcon = modifier.modify(baseIcon, values);
assertEquals(7, modifiedIcon.getIconWidth());
assertEquals(13, modifiedIcon.getIconHeight());
}
@Test
public void testMoveModifier() throws Exception {
IconModifier modifier = IconModifier.parse("[move(4, 3)]");
Icon modifiedIcon = modifier.modify(baseIcon, values);
assertTrue(modifiedIcon instanceof TranslateIcon);
TranslateIcon translateIcon = (TranslateIcon) modifiedIcon;
assertEquals(4, translateIcon.getX());
assertEquals(3, translateIcon.getY());
}
@Test
public void testRotateModifier() throws Exception {
IconModifier modifier = IconModifier.parse("[rotate(90)]");
Icon modifiedIcon = modifier.modify(baseIcon, values);
assertTrue(modifiedIcon instanceof RotateIcon);
RotateIcon rotateIcon = (RotateIcon) modifiedIcon;
assertEquals(90, rotateIcon.getRotation());
}
@Test
public void testDisabledModifier() throws Exception {
IconModifier modifier = IconModifier.parse("[disabled]");
Icon modifiedIcon = modifier.modify(baseIcon, values);
assertNotEquals(baseIcon, modifiedIcon);
}
@Test
public void testOverlayIcon() throws Exception {
IconModifier modifier = IconModifier.parse("{images/flag.png}");
Icon modifiedIcon = modifier.modify(baseIcon, values);
assertTrue(modifiedIcon instanceof MultiIcon);
MultiIcon multiIcon = (MultiIcon) modifiedIcon;
Icon[] icons = multiIcon.getIcons();
assertEquals(2, icons.length);
assertEquals(baseIcon, icons[0]);
assertEquals(ResourceManager.loadImage("images/flag.png"), icons[1]);
}
@Test
public void testOverlayIcon2() throws Exception {
IconModifier modifier =
IconModifier.parse("[size(20,25)]{images/flag.png[size(8,9)][move(4,4)]}");
Icon modifiedIcon = modifier.modify(baseIcon, values);
assertTrue(modifiedIcon instanceof MultiIcon);
MultiIcon multiIcon = (MultiIcon) modifiedIcon;
Icon[] icons = multiIcon.getIcons();
assertEquals(2, icons.length);
assertEquals(20, icons[0].getIconWidth());
assertEquals(25, icons[0].getIconHeight());
assertEquals(8, icons[1].getIconWidth());
assertEquals(9, icons[1].getIconHeight());
}
@Test
public void testInvalidModifierString() {
try {
IconModifier.parse("dasdf");
fail("Expected IllegalArgumentExcption");
}
catch (ParseException e) {
// expected
}
}
@Test
public void testInvalidModifierString2() {
try {
IconModifier.parse("disabledx");
fail("Expected IllegalArgumentExcption");
}
catch (ParseException e) {
// expected
}
}
@Test
public void testInvalidModifierString3() {
try {
IconModifier.parse("[size(13,14,13)]");
fail("Expected IllegalArgumentExcption");
}
catch (ParseException e) {
// expected
}
}
@Test
public void testInvalidModifierString4() {
try {
IconModifier.parse("[size(14,12]");
fail("Expected IllegalArgumentExcption");
}
catch (ParseException e) {
// expected
}
}
@Test
public void testInvalidModifierString5() {
try {
IconModifier.parse("[size(14)]");
fail("Expected IllegalArgumentExcption");
}
catch (ParseException e) {
// expected
}
}
@Test
public void testInvalidModifierString6() {
try {
IconModifier.parse("[size(10,10)]move(3,4)]");
fail("Expected IllegalArgumentExcption");
}
catch (ParseException e) {
// expected
}
}
@Test
public void testGetSerializationString() {
//@formatter:off
assertEquals("[size(5,9)]", new IconModifier(new Dimension(5,9), null, null, false).getSerializationString());
assertEquals("[move(8,7)]", new IconModifier(null, new Point(8,7), null,false).getSerializationString());
assertEquals("[disabled]", new IconModifier(null, null, null, true).getSerializationString());
assertEquals("[size(5,0)][move(8,7)][disabled]", new IconModifier(new Dimension(5,0), new Point(8,7), null, true).getSerializationString());
assertEquals("[rotate(90)]", new IconModifier(null, null, 90, false).getSerializationString());
//@formatter:on
}
}

View file

@ -17,12 +17,17 @@ package generic.theme;
import static org.junit.Assert.*;
import java.text.ParseException;
import javax.swing.Icon;
import org.junit.Before;
import org.junit.Test;
import resources.MultiIcon;
import resources.ResourceManager;
import resources.icons.EmptyIcon;
import resources.icons.TranslateIcon;
public class IconValueTest {
private static Icon ICON1 = ResourceManager.getDefaultIcon();
@ -99,7 +104,7 @@ public class IconValueTest {
}
@Test
public void testParse() {
public void testParse() throws ParseException {
IconValue value = IconValue.parse("icon.test", "images/core.png");
assertEquals("icon.test", value.getId());
assertEquals(ICON1, value.getRawValue());
@ -116,6 +121,23 @@ public class IconValueTest {
assertEquals("xyz.abc", value.getReferenceId());
}
@Test
public void testParseWithOverlays() throws ParseException {
IconValue value = IconValue.parse("icon.test",
"images/core.png[size(25,25)]{images/flag.png[size(8,8)][move(4,4)]}");
assertEquals("icon.test", value.getId());
Icon icon = value.get(values);
assertTrue(icon instanceof MultiIcon);
MultiIcon multiIcon = (MultiIcon) icon;
Icon[] icons = multiIcon.getIcons();
assertEquals(2, icons.length);
assertEquals(25, icons[0].getIconWidth());
assertEquals(25, icons[0].getIconWidth());
assertEquals(8, icons[1].getIconWidth());
assertEquals(8, icons[1].getIconWidth());
assertTrue(icons[1] instanceof TranslateIcon);
}
@Test
public void testIsIconKey() {
assertTrue(IconValue.isIconKey("icon.a.b.c"));
@ -150,4 +172,33 @@ public class IconValueTest {
assertEquals("icon.parent", value.getReferenceId());
assertNull(value.getRawValue());
}
@Test
public void testParseEmptyIcon() throws ParseException {
IconValue value = IconValue.parse("icon.test", "EMPTY_ICON");
assertEquals("icon.test", value.getId());
Icon icon = value.get(values);
assertEquals(new EmptyIcon(16, 16), icon);
}
@Test
public void testParseEmptyIconWithSize() throws ParseException {
IconValue value = IconValue.parse("icon.test", "EMPTY_ICON[size(12,15)]");
assertEquals("icon.test", value.getId());
Icon icon = value.get(values);
assertEquals(new EmptyIcon(12, 15), icon);
}
@Test
public void testGetSerializationStringWithEmptyIcon() {
IconValue value = new IconValue("icon.test", new EmptyIcon(16, 16));
assertEquals("icon.test = EMPTY_ICON", value.getSerializationString());
}
@Test
public void testGetSerializationStringWithEmptyCustomSizeIcon() {
IconValue value = new IconValue("icon.test", new EmptyIcon(22, 13));
assertEquals("icon.test = EMPTY_ICON[size(22,13)]", value.getSerializationString());
}
}

View file

@ -28,6 +28,7 @@ import javax.swing.Icon;
import org.junit.Test;
import resources.MultiIcon;
import resources.ResourceManager;
public class ThemePropertyFileReaderTest {
@ -49,12 +50,15 @@ public class ThemePropertyFileReaderTest {
" font.a.b = (font.a.8[20][BOLD])",
" icon.a.10 = core.png",
" icon.a.11 = icon.a.10",
" icon.a.12 = icon.a.10[size(17,21)]",
" icon.a.13 = core.png[size(17,21)]",
" icon.a.14 = icon.a.10{core.png[size(4,4)][move(8, 8)]",
"")));
//@formatter:on
Color halfAlphaRed = new Color(0x80ff0000, true);
GThemeValueMap values = reader.getDefaultValues();
assertEquals(12, values.size());
assertEquals(15, values.size());
assertEquals(WHITE, getColor(values, "color.b.1"));
assertEquals(RED, getColor(values, "color.b.2"));
@ -70,6 +74,16 @@ public class ThemePropertyFileReaderTest {
assertEquals(ResourceManager.loadImage("core.png"), getIcon(values, "icon.a.10"));
assertEquals(ResourceManager.loadImage("core.png"), getIcon(values, "icon.a.11"));
Icon icon = getIcon(values, "icon.a.12");
assertEquals(17, icon.getIconWidth());
assertEquals(21, icon.getIconHeight());
icon = getIcon(values, "icon.a.13");
assertEquals(17, icon.getIconWidth());
assertEquals(21, icon.getIconHeight());
icon = getIcon(values, "icon.a.14");
assertTrue(icon instanceof MultiIcon);
}

View file

@ -0,0 +1,60 @@
/* ###
* 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 generic.theme;
import static org.junit.Assert.*;
import java.text.ParseException;
import java.util.List;
import org.junit.Test;
public class ThemeValueUtilsTest {
@Test
public void testParseGroupings() throws ParseException {
String source = "(ab (cd))(ef)(( gh))";
List<String> results = ThemeValueUtils.parseGroupings(source, '(', ')');
assertEquals(3, results.size());
assertEquals("ab (cd)", results.get(0));
assertEquals("ef", results.get(1));
assertEquals("( gh)", results.get(2));
}
@Test
public void testParseGroupingsParseError() {
String source = "(ab (cd))(ef)( gh))";
try {
ThemeValueUtils.parseGroupings(source, '(', ')');
fail("Expected parse Exception");
}
catch (ParseException e) {
//expected
}
}
@Test
public void testParseGroupingsParseError2() {
String source = " xx";
try {
ThemeValueUtils.parseGroupings(source, '(', ')');
fail("Expected parse Exception");
}
catch (ParseException e) {
// expected
}
}
}

View file

@ -239,7 +239,7 @@ public class GHelpBroker extends DefaultHelpBroker {
JToolBar toolbar = (JToolBar) component;
toolbar.addSeparator();
ImageIcon zoomOutIcon = ResourceManager.getScaledIcon(ZOOM_OUT_ICON, 24, 24);
Icon zoomOutIcon = ResourceManager.getScaledIcon(ZOOM_OUT_ICON, 24, 24);
JButton zoomOutBtn = new JButton(zoomOutIcon);
zoomOutBtn.setToolTipText("Zoom out");
zoomOutBtn.addActionListener(e -> {
@ -251,7 +251,7 @@ public class GHelpBroker extends DefaultHelpBroker {
});
toolbar.add(zoomOutBtn);
ImageIcon zoomInIcon = ResourceManager.getScaledIcon(ZOOM_IN_ICON, 24, 24);
Icon zoomInIcon = ResourceManager.getScaledIcon(ZOOM_IN_ICON, 24, 24);
JButton zoomInBtn = new JButton(zoomInIcon);
zoomInBtn.setToolTipText("Zoom in");
zoomInBtn.addActionListener(e -> {