diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousBookmarkAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousBookmarkAction.java index c72345c884..bda51956a5 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousBookmarkAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousBookmarkAction.java @@ -51,19 +51,19 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction 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) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/script/ScriptInfo.java b/Ghidra/Features/Base/src/main/java/ghidra/app/script/ScriptInfo.java index 49bca25d09..324a51bfb0 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/script/ScriptInfo.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/script/ScriptInfo.java @@ -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; diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/framework/main/datatree/FrontEndPluginActionsTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/framework/main/datatree/FrontEndPluginActionsTest.java index e270daac2b..c2da7f2a89 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/framework/main/datatree/FrontEndPluginActionsTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/framework/main/datatree/FrontEndPluginActionsTest.java @@ -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); diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/SetVertexMostRecentColorAction.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/SetVertexMostRecentColorAction.java index 2cd9c75968..934cfbfc86 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/SetVertexMostRecentColorAction.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/SetVertexMostRecentColorAction.java @@ -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); diff --git a/Ghidra/Features/VersionTracking/data/version.tracking.theme.properties b/Ghidra/Features/VersionTracking/data/version.tracking.theme.properties index 34498dbfaa..345e342482 100644 --- a/Ghidra/Features/VersionTracking/data/version.tracking.theme.properties +++ b/Ghidra/Features/VersionTracking/data/version.tracking.theme.properties @@ -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] diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/impl/VTSessionContentHandler.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/impl/VTSessionContentHandler.java index 513ce83b4b..ef12f97735 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/impl/VTSessionContentHandler.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/impl/VTSessionContentHandler.java @@ -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"; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AcceptMatchAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AcceptMatchAction.java index 00d8139af2..9527b8cf65 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AcceptMatchAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AcceptMatchAction.java @@ -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); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AddToVersionTrackingSessionAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AddToVersionTrackingSessionAction.java index 6f02ce2f38..64ee1c57dd 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AddToVersionTrackingSessionAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AddToVersionTrackingSessionAction.java @@ -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")); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ApplyMatchAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ApplyMatchAction.java index b6d9b918cb..48531b562e 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ApplyMatchAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ApplyMatchAction.java @@ -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); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AutoVersionTrackingAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AutoVersionTrackingAction.java index 6906cf6e7b..6a9651cbfe 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AutoVersionTrackingAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AutoVersionTrackingAction.java @@ -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) { diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ChooseMatchTagAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ChooseMatchTagAction.java index 0beb435c0b..3a796e2898 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ChooseMatchTagAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ChooseMatchTagAction.java @@ -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; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ClearMatchAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ClearMatchAction.java index 5fe2a61213..5c2105d7ee 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ClearMatchAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ClearMatchAction.java @@ -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) { diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateImpliedMatchAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateImpliedMatchAction.java index e57d71fc76..9bb9d73856 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateImpliedMatchAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateImpliedMatchAction.java @@ -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")); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateManualMatchAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateManualMatchAction.java index 4353ac7f90..e00fbb5916 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateManualMatchAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateManualMatchAction.java @@ -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. diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateManualMatchAndAcceptAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateManualMatchAndAcceptAction.java index ca1655f3d6..9a6cec4144 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateManualMatchAndAcceptAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateManualMatchAndAcceptAction.java @@ -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 diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateManualMatchAndAcceptAndApplyAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateManualMatchAndAcceptAndApplyAction.java index 5804aff3f5..baa117c068 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateManualMatchAndAcceptAndApplyAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateManualMatchAndAcceptAndApplyAction.java @@ -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. diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateSelectionAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateSelectionAction.java index dad1804b93..73be37bffd 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateSelectionAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateSelectionAction.java @@ -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 diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateVersionTrackingSessionAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateVersionTrackingSessionAction.java index 2e56d1553c..b31b823e4c 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateVersionTrackingSessionAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/CreateVersionTrackingSessionAction.java @@ -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) { diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/EditAllTagsAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/EditAllTagsAction.java index b89305b931..e22adc3c5d 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/EditAllTagsAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/EditAllTagsAction.java @@ -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; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/EditMarkupAddressAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/EditMarkupAddressAction.java index ab9ebc31af..e07b112ad6 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/EditMarkupAddressAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/EditMarkupAddressAction.java @@ -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", diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/HelpAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/HelpAction.java index ee2ed7903b..c935c00de9 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/HelpAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/HelpAction.java @@ -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); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/MatchTableSelectionAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/MatchTableSelectionAction.java index 14749bd31b..35e405ce44 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/MatchTableSelectionAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/MatchTableSelectionAction.java @@ -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 { @@ -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 trackSelectedIndexActionState = new ActionState<>("Track Selected Index", diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RedoAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RedoAction.java index 5a6b422f7e..3e56e4e832 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RedoAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RedoAction.java @@ -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); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RejectMatchAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RejectMatchAction.java index dad1e1cc4e..c04619dd94 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RejectMatchAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RejectMatchAction.java @@ -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) { diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RemoveMatchAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RemoveMatchAction.java index 760fa1b9d9..77483d07d7 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RemoveMatchAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RemoveMatchAction.java @@ -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) { diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RemoveMatchTagAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RemoveMatchTagAction.java index ed63f3ca24..92318bf62a 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RemoveMatchTagAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/RemoveMatchTagAction.java @@ -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; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ReplaceDefaultMarkupItemAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ReplaceDefaultMarkupItemAction.java index 09e1e1eb79..ff6203ba7a 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ReplaceDefaultMarkupItemAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ReplaceDefaultMarkupItemAction.java @@ -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(); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ReplaceFirstMarkupItemAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ReplaceFirstMarkupItemAction.java index 0303cfde1c..cd32f9a58c 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ReplaceFirstMarkupItemAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ReplaceFirstMarkupItemAction.java @@ -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); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ResetMarkupItemAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ResetMarkupItemAction.java index 9c5889a31d..9e95518f77 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ResetMarkupItemAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/ResetMarkupItemAction.java @@ -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; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/SaveVersionTrackingSessionAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/SaveVersionTrackingSessionAction.java index 227f831f45..84bd93597f 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/SaveVersionTrackingSessionAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/SaveVersionTrackingSessionAction.java @@ -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; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/SelectExistingMatchAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/SelectExistingMatchAction.java index de612ee9fd..c60586094d 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/SelectExistingMatchAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/SelectExistingMatchAction.java @@ -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"; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/SetVTMatchFromOneToManyAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/SetVTMatchFromOneToManyAction.java index 82703c20ee..0a2aa62dac 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/SetVTMatchFromOneToManyAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/SetVTMatchFromOneToManyAction.java @@ -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; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/UndoAction.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/UndoAction.java index 600c3cd30f..b234c78b20 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/UndoAction.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/UndoAction.java @@ -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); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/editors/TagEditorRenderer.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/editors/TagEditorRenderer.java index 870f93b6f3..6626309f97 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/editors/TagEditorRenderer.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/editors/TagEditorRenderer.java @@ -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 { - 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 list; private final TagStateListModel listModel; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/filters/Filter.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/filters/Filter.java index 732f53ddf9..32c3b177b3 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/filters/Filter.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/filters/Filter.java @@ -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 { 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; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTPlugin.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTPlugin.java index 320e025640..62c1a94e02 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTPlugin.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTPlugin.java @@ -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; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VersionTrackingPluginPackage.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VersionTrackingPluginPackage.java index 5c145b0f1e..7007883487 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VersionTrackingPluginPackage.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VersionTrackingPluginPackage.java @@ -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,19 +15,18 @@ */ 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, - "These plugins provide feature for performing version tracking between programs." ); + super(NAME, ICON, + "These plugins provide feature for performing version tracking between programs."); } } diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/functionassociation/VTFunctionAssociationProvider.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/functionassociation/VTFunctionAssociationProvider.java index ea7324cd92..535fc4160c 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/functionassociation/VTFunctionAssociationProvider.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/functionassociation/VTFunctionAssociationProvider.java @@ -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 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 unmatchedOnlyActionState = new ActionState<>("Show Only Unmatched Functions", unmatchedIcon, SHOW_UNMATCHED); unmatchedOnlyActionState.setHelpLocation( diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/impliedmatches/VTImpliedMatchesTableProvider.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/impliedmatches/VTImpliedMatchesTableProvider.java index a2c0625018..51ee6a9699 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/impliedmatches/VTImpliedMatchesTableProvider.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/impliedmatches/VTImpliedMatchesTableProvider.java @@ -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); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/markuptable/MarkupItemStatusRenderer.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/markuptable/MarkupItemStatusRenderer.java index 6f310bb115..64dbd4909d 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/markuptable/MarkupItemStatusRenderer.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/markuptable/MarkupItemStatusRenderer.java @@ -100,7 +100,7 @@ public class MarkupItemStatusRenderer extends AbstractGhidraColumnRenderer"); - 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(""); + buf.append(""); buf.append(""); buf.append(message).append("
"); - 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(""); + buf.append(""); buf.append(""); buf.append(message).append("
"); - 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(""); + buf.append(""); buf.append(""); buf.append(message).append("
"); - 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(""); + buf.append(""); buf.append(""); buf.append(message).append("
"); - 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(""); + buf.append(""); buf.append(""); buf.append(message).append("
"); 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) { diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/MultipleLabelsRenderer.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/MultipleLabelsRenderer.java index fc1591b538..b4f081cc56 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/MultipleLabelsRenderer.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/MultipleLabelsRenderer.java @@ -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, 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"); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/relatedMatches/RelatedMatchRenderer.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/relatedMatches/RelatedMatchRenderer.java index 949cf80260..927d2a5cdd 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/relatedMatches/RelatedMatchRenderer.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/relatedMatches/RelatedMatchRenderer.java @@ -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 destinationMap; static Map 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; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/relatedMatches/VTRelatedMatchesTableProvider.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/relatedMatches/VTRelatedMatchesTableProvider.java index 9b2c024417..4e8a90ea51 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/relatedMatches/VTRelatedMatchesTableProvider.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/relatedMatches/VTRelatedMatchesTableProvider.java @@ -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; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/FilterIconFlashTimer.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/FilterIconFlashTimer.java index 6ebded5a60..fdc1b8f995 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/FilterIconFlashTimer.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/FilterIconFlashTimer.java @@ -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 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; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/MatchStatusRenderer.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/MatchStatusRenderer.java index 9ec0dbf8a9..756e2acb14 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/MatchStatusRenderer.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/util/MatchStatusRenderer.java @@ -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 diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/ChooseAddressSetEditorPanel.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/ChooseAddressSetEditorPanel.java index 38dc9bdc3e..16a79b9ab4 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/ChooseAddressSetEditorPanel.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/ChooseAddressSetEditorPanel.java @@ -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; diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/NewSessionPanel.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/NewSessionPanel.java index eb6bb77534..d82beac3db 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/NewSessionPanel.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/NewSessionPanel.java @@ -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 { 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 { 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 = diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/VTProgramTableCorrelatorModel.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/VTProgramTableCorrelatorModel.java index 573e22167d..a964855841 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/VTProgramTableCorrelatorModel.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/wizard/VTProgramTableCorrelatorModel.java @@ -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 { @@ -40,7 +40,8 @@ public class VTProgramTableCorrelatorModel extends AbstractGTableModel list; private Set previouslyRunCorrelators; diff --git a/Ghidra/Framework/Docking/data/docking.theme.properties b/Ghidra/Framework/Docking/data/docking.theme.properties index eb75e8f09c..5662c43278 100644 --- a/Ghidra/Framework/Docking/data/docking.theme.properties +++ b/Ghidra/Framework/Docking/data/docking.theme.properties @@ -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 diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/ColumnFilterPanel.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/ColumnFilterPanel.java index 0abe113e1c..feb4ad39f5 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/ColumnFilterPanel.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/ColumnFilterPanel.java @@ -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); diff --git a/Ghidra/Framework/Docking/src/test/java/docking/theme/gui/ThemeUtilsTest.java b/Ghidra/Framework/Docking/src/test/java/docking/theme/gui/ThemeUtilsTest.java index 79948be124..ec423c6c56 100644 --- a/Ghidra/Framework/Docking/src/test/java/docking/theme/gui/ThemeUtilsTest.java +++ b/Ghidra/Framework/Docking/src/test/java/docking/theme/gui/ThemeUtilsTest.java @@ -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 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); diff --git a/Ghidra/Framework/Generic/certification.manifest b/Ghidra/Framework/Generic/certification.manifest index d3ec09979e..a5abceb966 100644 --- a/Ghidra/Framework/Generic/certification.manifest +++ b/Ghidra/Framework/Generic/certification.manifest @@ -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| diff --git a/Ghidra/Framework/Generic/data/generic.theme.properties b/Ghidra/Framework/Generic/data/generic.theme.properties new file mode 100644 index 0000000000..4b94fe1ccd --- /dev/null +++ b/Ghidra/Framework/Generic/data/generic.theme.properties @@ -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] \ No newline at end of file diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/AbstractThemeReader.java b/Ghidra/Framework/Generic/src/main/java/generic/theme/AbstractThemeReader.java index a7abd2195e..9ff0e2f285 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/theme/AbstractThemeReader.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/theme/AbstractThemeReader.java @@ -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,8 +94,14 @@ public abstract class AbstractThemeReader { } } - private IconValue parseIconProperty(String key, String value) { - return IconValue.parse(key, 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) { diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/FontModifier.java b/Ghidra/Framework/Generic/src/main/java/generic/theme/FontModifier.java index 48d7824b16..8b1760da2e 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/theme/FontModifier.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/theme/FontModifier.java @@ -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 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 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) { - modifier.addStyleModifier(style); + 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 getModifierPieces(String value) { - if (!MODIFIER_PATTERN.matcher(value).matches()) { - throw new IllegalArgumentException("Invalid font modifier string"); - } - StringTokenizer tokenizer = new StringTokenizer(value, "[]"); - List list = new ArrayList<>(); - while (tokenizer.hasMoreTokens()) { - String token = tokenizer.nextToken().trim(); - if (!token.isBlank()) { - list.add(token); - } - } - return list; - } } diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/FontValue.java b/Ghidra/Framework/Generic/src/main/java/generic/theme/FontValue.java index 89f514a580..2ca57e21bc 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/theme/FontValue.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/theme/FontValue.java @@ -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 { 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 { * @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 { 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()); } diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/GIcon.java b/Ghidra/Framework/Generic/src/main/java/generic/theme/GIcon.java index e5d9e9ebb0..85016d3e93 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/theme/GIcon.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/theme/GIcon.java @@ -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; + } /** diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/GThemeDefaults.java b/Ghidra/Framework/Generic/src/main/java/generic/theme/GThemeDefaults.java index 7e183ebf21..72179d49ae 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/theme/GThemeDefaults.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/theme/GThemeDefaults.java @@ -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"; + } } diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/IconModifier.java b/Ghidra/Framework/Generic/src/main/java/generic/theme/IconModifier.java new file mode 100644 index 0000000000..0cb67ed483 --- /dev/null +++ b/Ghidra/Framework/Generic/src/main/java/generic/theme/IconModifier.java @@ -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 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 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 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); + } + } + +} diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/IconValue.java b/Ghidra/Framework/Generic/src/main/java/generic/theme/IconValue.java index 92fe807611..4f2451cbaf 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/theme/IconValue.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/theme/IconValue.java @@ -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 { + 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 { 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 { * @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 { * @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 { } 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 diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeValueUtils.java b/Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeValueUtils.java new file mode 100644 index 0000000000..376d046a54 --- /dev/null +++ b/Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeValueUtils.java @@ -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 parseGroupings(String source, char startChar, char endChar) + throws ParseException { + List 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; + } + +} diff --git a/Ghidra/Framework/Generic/src/main/java/resources/Icons.java b/Ghidra/Framework/Generic/src/main/java/resources/Icons.java index 87aac38ca0..32edadb29c 100644 --- a/Ghidra/Framework/Generic/src/main/java/resources/Icons.java +++ b/Ghidra/Framework/Generic/src/main/java/resources/Icons.java @@ -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 diff --git a/Ghidra/Framework/Generic/src/main/java/resources/MultiIconBuilder.java b/Ghidra/Framework/Generic/src/main/java/resources/MultiIconBuilder.java index 0f0abe84ae..be6d0ff5e3 100644 --- a/Ghidra/Framework/Generic/src/main/java/resources/MultiIconBuilder.java +++ b/Ghidra/Framework/Generic/src/main/java/resources/MultiIconBuilder.java @@ -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; diff --git a/Ghidra/Framework/Generic/src/main/java/resources/ResourceManager.java b/Ghidra/Framework/Generic/src/main/java/resources/ResourceManager.java index 954be29ac8..39ba9ff0b6 100644 --- a/Ghidra/Framework/Generic/src/main/java/resources/ResourceManager.java +++ b/Ghidra/Framework/Generic/src/main/java/resources/ResourceManager.java @@ -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); diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/DerivedImageIcon.java b/Ghidra/Framework/Generic/src/main/java/resources/icons/DerivedImageIcon.java index 61ffd4800d..4f4c2fbf7e 100644 --- a/Ghidra/Framework/Generic/src/main/java/resources/icons/DerivedImageIcon.java +++ b/Ghidra/Framework/Generic/src/main/java/resources/icons/DerivedImageIcon.java @@ -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(); diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/EmptyIcon.java b/Ghidra/Framework/Generic/src/main/java/resources/icons/EmptyIcon.java index ea1bc3f932..220170db42 100644 --- a/Ghidra/Framework/Generic/src/main/java/resources/icons/EmptyIcon.java +++ b/Ghidra/Framework/Generic/src/main/java/resources/icons/EmptyIcon.java @@ -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,29 +17,55 @@ package resources.icons; import java.awt.Component; import java.awt.Graphics; +import java.util.Objects; import javax.swing.Icon; -public class EmptyIcon implements Icon { +public class EmptyIcon implements Icon { - private int width; - private int height; - - public EmptyIcon( int width, int height ) { - this.width = width; - this.height = height; - } - - public int getIconHeight() { - return height; - } + private int width; + private int height; - public int getIconWidth() { - return width; - } + public EmptyIcon(int width, int height) { + this.width = width; + this.height = height; + } - public void paintIcon( Component c, Graphics g, int x, int y ) { - // no-op - } + public int getIconHeight() { + return height; + } + + public int getIconWidth() { + return width; + } + + public void paintIcon(Component c, Graphics g, int x, int y) { + // 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 + ")"; + } } diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/RotateIcon.java b/Ghidra/Framework/Generic/src/main/java/resources/icons/RotateIcon.java index 29e3886c94..7df10bb794 100644 --- a/Ghidra/Framework/Generic/src/main/java/resources/icons/RotateIcon.java +++ b/Ghidra/Framework/Generic/src/main/java/resources/icons/RotateIcon.java @@ -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; + } } diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/TranslateIcon.java b/Ghidra/Framework/Generic/src/main/java/resources/icons/TranslateIcon.java index 52e5ed09e3..b624428ef8 100644 --- a/Ghidra/Framework/Generic/src/main/java/resources/icons/TranslateIcon.java +++ b/Ghidra/Framework/Generic/src/main/java/resources/icons/TranslateIcon.java @@ -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; + } } diff --git a/Ghidra/Framework/Generic/src/test/java/generic/theme/FontModifierTest.java b/Ghidra/Framework/Generic/src/test/java/generic/theme/FontModifierTest.java index 3b6528b003..8a498c2edf 100644 --- a/Ghidra/Framework/Generic/src/test/java/generic/theme/FontModifierTest.java +++ b/Ghidra/Framework/Generic/src/test/java/generic/theme/FontModifierTest.java @@ -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 } } diff --git a/Ghidra/Framework/Generic/src/test/java/generic/theme/FontValueTest.java b/Ghidra/Framework/Generic/src/test/java/generic/theme/FontValueTest.java index d601e11826..d0e0330fe2 100644 --- a/Ghidra/Framework/Generic/src/test/java/generic/theme/FontValueTest.java +++ b/Ghidra/Framework/Generic/src/test/java/generic/theme/FontValueTest.java @@ -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()); diff --git a/Ghidra/Framework/Generic/src/test/java/generic/theme/IconModifierTest.java b/Ghidra/Framework/Generic/src/test/java/generic/theme/IconModifierTest.java new file mode 100644 index 0000000000..414d9b2332 --- /dev/null +++ b/Ghidra/Framework/Generic/src/test/java/generic/theme/IconModifierTest.java @@ -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 + } +} diff --git a/Ghidra/Framework/Generic/src/test/java/generic/theme/IconValueTest.java b/Ghidra/Framework/Generic/src/test/java/generic/theme/IconValueTest.java index 220db3a084..807365905a 100644 --- a/Ghidra/Framework/Generic/src/test/java/generic/theme/IconValueTest.java +++ b/Ghidra/Framework/Generic/src/test/java/generic/theme/IconValueTest.java @@ -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()); + } + } diff --git a/Ghidra/Framework/Generic/src/test/java/generic/theme/ThemePropertyFileReaderTest.java b/Ghidra/Framework/Generic/src/test/java/generic/theme/ThemePropertyFileReaderTest.java index 5e06c62d06..f2615798ef 100644 --- a/Ghidra/Framework/Generic/src/test/java/generic/theme/ThemePropertyFileReaderTest.java +++ b/Ghidra/Framework/Generic/src/test/java/generic/theme/ThemePropertyFileReaderTest.java @@ -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); } diff --git a/Ghidra/Framework/Generic/src/test/java/generic/theme/ThemeValueUtilsTest.java b/Ghidra/Framework/Generic/src/test/java/generic/theme/ThemeValueUtilsTest.java new file mode 100644 index 0000000000..0f147ccb3c --- /dev/null +++ b/Ghidra/Framework/Generic/src/test/java/generic/theme/ThemeValueUtilsTest.java @@ -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 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 + } + } + +} diff --git a/Ghidra/Framework/Help/src/main/java/help/GHelpBroker.java b/Ghidra/Framework/Help/src/main/java/help/GHelpBroker.java index 54484b9c1d..a6e8c49000 100644 --- a/Ghidra/Framework/Help/src/main/java/help/GHelpBroker.java +++ b/Ghidra/Framework/Help/src/main/java/help/GHelpBroker.java @@ -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 -> {