diff --git a/Ghidra/Debug/Debugger/data/debugger.theme.properties b/Ghidra/Debug/Debugger/data/debugger.theme.properties index 08ed39fc5b..63729a015e 100644 --- a/Ghidra/Debug/Debugger/data/debugger.theme.properties +++ b/Ghidra/Debug/Debugger/data/debugger.theme.properties @@ -92,8 +92,8 @@ icon.debugger.thread = thread.png icon.debugger.processor = memory16.gif // TODO this icon was missing 'kcmprocessor.png' icon.debugger.launch = launch.png icon.debugger.attach = attach.png -icon.debugger.resume = continue.png -icon.debugger.terminate = stop.png +icon.debugger.resume = resume.png +icon.debugger.interrupt = interrupt.png icon.debugger.kill = kill.png icon.debugger.detach = detach.png icon.debugger.record = record.png @@ -101,10 +101,11 @@ icon.debugger.step.into = stepinto.png icon.debugger.step.over = stepover.png icon.debugger.step.back = stepback.png icon.debugger.step.finish = stepout.png +icon.debugger.step.last = steplast.png icon.debugger.skip.over = skipover.png icon.debugger.snap.forward = 2rightarrow.png icon.debugger.snap.backward = 2leftarrow.png -icon.debugger.seek.present = icon.debugger.resume +icon.debugger.seek.present = seek-present.png icon.debugger.breakpoint.set = breakpoint-enable.png icon.debugger.breakpoint.clear = breakpoint-clear.png diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/DebuggerResources.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/DebuggerResources.java index 8c81153e23..bbd5f24881 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/DebuggerResources.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/DebuggerResources.java @@ -60,7 +60,6 @@ import ghidra.util.HelpLocation; import ghidra.util.Msg; import ghidra.util.exception.CancelledException; import resources.MultiIcon; -import resources.ResourceManager; public interface DebuggerResources { String OPTIONS_CATEGORY_DEBUGGER = "Debugger"; @@ -77,23 +76,20 @@ public interface DebuggerResources { Icon ICON_PROGRAM = ProgramContentHandler.PROGRAM_ICON; Icon ICON_PROCESSOR = new GIcon("icon.debugger.processor"); - Icon ICON_INTERRUPT = ResourceManager.loadImage("images/interrupt.png"); // TODO do gColor - Icon ICON_LAUNCH = new GIcon("icon.debugger.launch"); Icon ICON_ATTACH = new GIcon("icon.debugger.attach"); Icon ICON_RESUME = new GIcon("icon.debugger.resume"); - Icon ICON_TERMINATE = new GIcon("icon.debugger.terminate"); // TODO was this deleted + Icon ICON_INTERRUPT = new GIcon("icon.debugger.interrupt"); Icon ICON_KILL = new GIcon("icon.debugger.kill"); Icon ICON_DETACH = new GIcon("icon.debugger.detach"); Icon ICON_RECORD = new GIcon("icon.debugger.record"); - Icon ICON_STEP_LAST = ResourceManager.loadImage("images/steplast.png"); // TODO GColor - Icon ICON_STEP_INTO = new GIcon("icon.debugger.step.into"); Icon ICON_STEP_OVER = new GIcon("icon.debugger.step.over"); Icon ICON_SKIP_OVER = new GIcon("icon.debugger.step.back"); Icon ICON_STEP_FINISH = new GIcon("icon.debugger.step.finish"); Icon ICON_STEP_BACK = new GIcon("icon.debugger.skip.over"); + Icon ICON_STEP_LAST = new GIcon("icon.debugger.step.last"); Icon ICON_SNAP_FORWARD = new GIcon("icon.debugger.snap.forward"); Icon ICON_SNAP_BACKWARD = new GIcon("icon.debugger.snap.backward"); diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsProviderTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsProviderTest.java index 461d2526a0..76bf66db00 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsProviderTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsProviderTest.java @@ -640,7 +640,9 @@ public class DebuggerBreakpointsProviderTest extends AbstractGhidraHeadedDebugge } assertEquals(2, filtLocs.size()); - breakpointsProvider.setSelectedBreakpoints(Set.of(data.get(0).getLogicalBreakpoint())); + LogicalBreakpointRow bpRow = data.get(0); + runSwing(() -> breakpointsProvider + .setSelectedBreakpoints(Set.of(bpRow.getLogicalBreakpoint()))); waitForSwing(); filtLocs = breakpointsProvider.locationFilterPanel.getTableFilterModel().getModelData(); diff --git a/Ghidra/Features/Base/build.gradle b/Ghidra/Features/Base/build.gradle index e5340b1370..0ea023e9e2 100644 --- a/Ghidra/Features/Base/build.gradle +++ b/Ghidra/Features/Base/build.gradle @@ -66,6 +66,7 @@ dependencies { testImplementation project(path: ':Project', configuration: 'testArtifacts') testImplementation project(path: ':SoftwareModeling', configuration: 'testArtifacts') testImplementation project(path: ':DB', configuration: 'testArtifacts') + helpPath project(path: ':Docking', configuration: 'helpPath') // this module's help has links to Base help files javacc 'net.java.dev.javacc:javacc:5.0' } diff --git a/Ghidra/Features/Base/certification.manifest b/Ghidra/Features/Base/certification.manifest index 7d90230600..30d629f544 100644 --- a/Ghidra/Features/Base/certification.manifest +++ b/Ghidra/Features/Base/certification.manifest @@ -1032,7 +1032,6 @@ src/main/resources/images/empty8x16.png||GHIDRA||||END| src/main/resources/images/emptyFragment.gif||GHIDRA||||END| src/main/resources/images/emptyFragmentInView.gif||GHIDRA||||END| src/main/resources/images/enum.png||GHIDRA||||END| -src/main/resources/images/erase16.png||GHIDRA||||END| src/main/resources/images/famfamfam_silk_icons_v013/application_cascade.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/famfamfam_silk_icons_v013/application_get.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/famfamfam_silk_icons_v013/application_key.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| @@ -1071,6 +1070,8 @@ src/main/resources/images/fingerPointer.png||GHIDRA||||END| src/main/resources/images/font.png||FAMFAMFAM Icons - CC 2.5||||END| src/main/resources/images/format-text-bold.png||Tango Icons - Public Domain|||tango icon set|END| src/main/resources/images/functionDef.png||GHIDRA||||END| +src/main/resources/images/function_graph.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| +src/main/resources/images/function_graph_curvey.png||GHIDRA||||END| src/main/resources/images/functions.gif||GHIDRA||||END| src/main/resources/images/go-down.tango.16.png||Tango Icons - Public Domain|||tango icon set|END| src/main/resources/images/go-home.png||Tango Icons - Public Domain|||Tango|END| @@ -1139,7 +1140,7 @@ src/main/resources/images/package.png||Nuvola Icons - LGPL 2.1|||Nuvola icon set src/main/resources/images/package_development.png||Nuvola Icons - LGPL 2.1|||nuvola|END| src/main/resources/images/package_green.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/page_white.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| -src/main/resources/images/page_white_copy.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| +src/main/resources/images/page_white_c.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/pencil.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/pencil16.png||GHIDRA||||END| src/main/resources/images/phone.png||Oxygen Icons - LGPL 3.0||||END| @@ -1167,11 +1168,11 @@ src/main/resources/images/stopNode.png||FAMFAMFAM Icons - CC 2.5|||famfamfam sil src/main/resources/images/table.png||FAMFAMFAM Icons - CC 2.5|||silk|END| src/main/resources/images/table_delete.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/table_go.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| +src/main/resources/images/table_relationship.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/table_row_delete.png||FAMFAMFAM Icons - CC 2.5|||silk|END| src/main/resources/images/tag_yellow.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/text-x-csrc.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| src/main/resources/images/text_list_bullets.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| -src/main/resources/images/text_lowercase.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/textfield.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/tools-report-bug.png||Oxygen Icons - LGPL 3.0||||END| src/main/resources/images/twosComplement.png||GHIDRA||||END| diff --git a/Ghidra/Features/Base/data/base.icons.theme.properties b/Ghidra/Features/Base/data/base.icons.theme.properties index 3792d7c068..9eac0906ca 100644 --- a/Ghidra/Features/Base/data/base.icons.theme.properties +++ b/Ghidra/Features/Base/data/base.icons.theme.properties @@ -23,6 +23,8 @@ icon.base.application.64 = GhidraIcon64.png icon.base.application.128 = GhidraIcon128.png icon.base.application.256 = GhidraIcon256.png +icon.help.home = GHIDRA_1.png + icon.provider.clone = camera-photo.png icon.plugin.datatypes.built.in = package_development.png diff --git a/Ghidra/Features/Base/src/main/help/help/TOC_Source.xml b/Ghidra/Features/Base/src/main/help/help/TOC_Source.xml index 757aa6bf19..4c44167d9b 100644 --- a/Ghidra/Features/Base/src/main/help/help/TOC_Source.xml +++ b/Ghidra/Features/Base/src/main/help/help/TOC_Source.xml @@ -49,10 +49,7 @@ - + @@ -383,11 +380,11 @@ - + - + diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/tool/ListingMergePanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/tool/ListingMergePanel.java index 61622fbf08..4d31877284 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/tool/ListingMergePanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/tool/ListingMergePanel.java @@ -58,8 +58,8 @@ import ghidra.util.task.TaskMonitor; public class ListingMergePanel extends JPanel implements MergeConstants, FocusListener, CodeFormatService { - private static final Icon HIDE_ICON = new GIcon("icons.base.listing.conflict.collapse"); - private static final Icon SHOW_ICON = new GIcon("icons.base.listing.conflict.expand"); + private static final Icon HIDE_ICON = new GIcon("icon.plugin.merge.conflict.collapse"); + private static final Icon SHOW_ICON = new GIcon("icon.plugin.merge.conflict.expand"); private JComponent topComp; private JComponent bottomComp; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/PreviewTable.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/PreviewTable.java index 5310ba7fbd..f3ae5aa469 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/PreviewTable.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/PreviewTable.java @@ -317,7 +317,7 @@ public class PreviewTable extends AbstractInstructionTable { private void createCopyBtn(JToolBar toolbar1) { Icon copyIcon = Icons.COPY_ICON; - Action copyAction = new CopyAction("copy", (ImageIcon) copyIcon, + Action copyAction = new CopyAction("copy", copyIcon, "Copy the full search string to clipboard"); EmptyBorderButton copyBtn = new EmptyBorderButton(); copyBtn.setAction(copyAction); @@ -328,7 +328,7 @@ public class PreviewTable extends AbstractInstructionTable { private EmptyBorderToggleButton createHexViewBtn(JToolBar toolbar1) { Icon hexIcon = new GIcon("icon.plugin.instructiontable.hex"); - Action hexAction = new HexAction("hex", (ImageIcon) hexIcon, "hex view"); + Action hexAction = new HexAction("hex", hexIcon, "hex view"); EmptyBorderToggleButton hexBtn = new EmptyBorderToggleButton(); hexBtn.setAction(hexAction); hexBtn.setName("Hex View Button"); @@ -340,7 +340,7 @@ public class PreviewTable extends AbstractInstructionTable { private EmptyBorderToggleButton createBinaryViewBtn(JToolBar toolbar1) { Icon binaryIcon = new GIcon("icon.plugin.instructiontable.binary"); - Action binaryAction = new BinaryAction("binary", (ImageIcon) binaryIcon, "binary view"); + Action binaryAction = new BinaryAction("binary", binaryIcon, "binary view"); EmptyBorderToggleButton binaryBtn = new EmptyBorderToggleButton(); binaryBtn.setAction(binaryAction); binaryBtn.setName("binary view button"); @@ -558,7 +558,7 @@ public class PreviewTable extends AbstractInstructionTable { private class BinaryAction extends AbstractAction { - public BinaryAction(String text, ImageIcon icon, String desc) { + public BinaryAction(String text, Icon icon, String desc) { super(text, icon); putValue(SHORT_DESCRIPTION, desc); } @@ -572,7 +572,7 @@ public class PreviewTable extends AbstractInstructionTable { private class HexAction extends AbstractAction { - public HexAction(String text, ImageIcon icon, String desc) { + public HexAction(String text, Icon icon, String desc) { super(text, icon); putValue(SHORT_DESCRIPTION, desc); } @@ -586,7 +586,7 @@ public class PreviewTable extends AbstractInstructionTable { private class CopyAction extends AbstractAction { - public CopyAction(String text, ImageIcon icon, String desc) { + public CopyAction(String text, Icon icon, String desc) { super(text, icon); putValue(SHORT_DESCRIPTION, desc); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramTreePlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramTreePlugin.java index c67cc22f55..c242f8b982 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramTreePlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramTreePlugin.java @@ -515,17 +515,9 @@ public class ProgramTreePlugin extends ProgramPlugin /** * Method renameView. - <<<<<<< Upstream, based on origin/master - * - * @param treeViewProvider - * @param newName - * @return boolean - ======= - * * @param treeViewProvider the provider * @param newName the new name * @return true if renamed - >>>>>>> 0eb4b9d GP-1981 - Theming - Base Module */ boolean renameView(TreeViewProvider treeViewProvider, String newName) { Listing listing = currentProgram.getListing(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FieldHeaderComp.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FieldHeaderComp.java index 1df5816d7b..e161262d16 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FieldHeaderComp.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FieldHeaderComp.java @@ -296,16 +296,10 @@ public class FieldHeaderComp extends JPanel { } /** - <<<<<<< Upstream, based on origin/master - * Returns the index of the field on the given row containing the give x pos. - * @param row the row on which to find the index of the field contianing the x coordinate. - * @param x the horizontal coordinate (in pixels) - ======= * Returns the index of the field on the given row containing the give x position. * @param row the row on which to find the index of the field containing the x coordinate. * @param x the horizontal coordinate (in pixels) * @return the column - >>>>>>> 1c5bb47 GP-1981 - Theming - GColor migration fixes */ public int getCol(int row, int x) { if (x < 0) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/base/help/GhidraHelpService.java b/Ghidra/Features/Base/src/main/java/ghidra/base/help/GhidraHelpService.java index 1716fa8f86..2e6d4f3c34 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/base/help/GhidraHelpService.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/base/help/GhidraHelpService.java @@ -22,7 +22,8 @@ import java.util.Map.Entry; import javax.help.HelpSet; import javax.help.HelpSetException; -import docking.help.*; +import docking.help.GHelpClassLoader; +import docking.help.HelpManager; import generic.jar.ResourceFile; import generic.theme.*; import ghidra.framework.Application; @@ -36,6 +37,12 @@ import resources.ResourceManager; */ public class GhidraHelpService extends HelpManager { + /** + * The hardcoded value to use for all HelpSet 'home id' values. Subclasses may change this + * value by overriding {@link #getHomeId()}. + */ + private static final String GHIDRA_HOME_ID = "Misc_Ghidra_Help_Contents"; + private static final String MASTER_HELP_SET_HS = "Base_HelpSet.hs"; private ThemeListener listener = new HelpThemeListener(); @@ -68,6 +75,11 @@ public class GhidraHelpService extends HelpManager { return ResourceManager.getResource("help/" + HelpService.DUMMY_HELP_SET_NAME); } + @Override + protected String getHomeId() { + return GHIDRA_HOME_ID; + } + private void loadHelpSets() { Map> helpSetsByModule = findHelpSetsByModule(); diff --git a/Ghidra/Features/FunctionGraph/src/main/resources/images/function_graph.png b/Ghidra/Features/Base/src/main/resources/images/function_graph.png similarity index 100% rename from Ghidra/Features/FunctionGraph/src/main/resources/images/function_graph.png rename to Ghidra/Features/Base/src/main/resources/images/function_graph.png diff --git a/Ghidra/Features/FunctionGraph/src/main/resources/images/function_graph_curvey.png b/Ghidra/Features/Base/src/main/resources/images/function_graph_curvey.png similarity index 100% rename from Ghidra/Features/FunctionGraph/src/main/resources/images/function_graph_curvey.png rename to Ghidra/Features/Base/src/main/resources/images/function_graph_curvey.png diff --git a/Ghidra/Features/VersionTracking/src/main/resources/images/page_white_c.png b/Ghidra/Features/Base/src/main/resources/images/page_white_c.png similarity index 100% rename from Ghidra/Features/VersionTracking/src/main/resources/images/page_white_c.png rename to Ghidra/Features/Base/src/main/resources/images/page_white_c.png diff --git a/Ghidra/Features/ProgramDiff/src/main/resources/images/table_relationship.png b/Ghidra/Features/Base/src/main/resources/images/table_relationship.png similarity index 100% rename from Ghidra/Features/ProgramDiff/src/main/resources/images/table_relationship.png rename to Ghidra/Features/Base/src/main/resources/images/table_relationship.png diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/listing/UserDefinedPropertyMergeManagerTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/listing/UserDefinedPropertyMergeManagerTest.java index cd48effcc7..ac83b84ae7 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/listing/UserDefinedPropertyMergeManagerTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/listing/UserDefinedPropertyMergeManagerTest.java @@ -22,6 +22,7 @@ import java.awt.Color; import org.junit.Test; import docking.AbstractErrDialog; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.program.database.*; import ghidra.program.model.address.Address; import ghidra.program.model.util.*; @@ -64,8 +65,8 @@ public class UserDefinedPropertyMergeManagerTest extends AbstractListingMergeMan super(); } -@Test - public void testAddVoidProperty() throws Exception { + @Test + public void testAddVoidProperty() throws Exception { mtf.initialize("DiffTestPgm1", new ProgramModifierListener() { @Override @@ -127,8 +128,8 @@ public class UserDefinedPropertyMergeManagerTest extends AbstractListingMergeMan assertNull(address); } -@Test - public void testAddSpaceProperty() throws Exception { + @Test + public void testAddSpaceProperty() throws Exception { // ******************** // *** DiffTestPgm2 *** // ******************** @@ -217,8 +218,8 @@ public class UserDefinedPropertyMergeManagerTest extends AbstractListingMergeMan assertNull(address); } -@Test - public void testAddObjectProperty() throws Exception { + @Test + public void testAddObjectProperty() throws Exception { // ******************** // *** DiffTestPgm1 *** // ******************** @@ -334,7 +335,7 @@ public class UserDefinedPropertyMergeManagerTest extends AbstractListingMergeMan } @Test - public void testAddStringProperty() throws Exception { + public void testAddStringProperty() throws Exception { mtf.initialize("DiffTestPgm1", new ProgramModifierListener() { @Override @@ -656,7 +657,7 @@ public class UserDefinedPropertyMergeManagerTest extends AbstractListingMergeMan AbstractErrDialog errDlg = waitForErrorDialog(); String message = errDlg.getMessage(); - assertEquals("Latest and Checked Out program versions do not have the same type for " + + assertEquals("Latest and Checked Out program versions do not have the same type for " + "'testMap' property.", message); pressButtonByText(errDlg, "OK"); @@ -683,7 +684,7 @@ public class UserDefinedPropertyMergeManagerTest extends AbstractListingMergeMan } @Test - public void testRemoveSpaceProperty() throws Exception { + public void testRemoveSpaceProperty() throws Exception { // ** DiffTestPgm2 ** // 10018ba = 1 // 10018ce = 2 @@ -745,8 +746,8 @@ public class UserDefinedPropertyMergeManagerTest extends AbstractListingMergeMan assertNull(address); } -@Test - public void testRemoveColorProperty() throws Exception { + @Test + public void testRemoveColorProperty() throws Exception { // ** DiffTestPgm2 ** // 10018ba = 1 // 10018ce = 2 @@ -800,13 +801,13 @@ public class UserDefinedPropertyMergeManagerTest extends AbstractListingMergeMan Address address = resultProgram.getMinAddress(); address = pm.getNextPropertyAddress(address); assertEquals(addr("0x10039fe"), address); - assertEquals(new SaveableColor(Color.GREEN), pm.get(address)); + assertEquals(new SaveableColor(Palette.GREEN), pm.get(address)); address = pm.getNextPropertyAddress(address); assertNull(address); } -@Test - public void testRemoveVsChangeSpaceProperty() throws Exception { + @Test + public void testRemoveVsChangeSpaceProperty() throws Exception { // ** DiffTestPgm2 ** // 10018ba = 1 // 10018ce = 2 @@ -882,8 +883,8 @@ public class UserDefinedPropertyMergeManagerTest extends AbstractListingMergeMan assertNull(address); } -@Test - public void testRemoveVsChangeTestColorProperty() throws Exception { + @Test + public void testRemoveVsChangeTestColorProperty() throws Exception { // ** DiffTestPgm2 ** // 10018ba = 1 // 10018ce = 2 @@ -953,8 +954,8 @@ public class UserDefinedPropertyMergeManagerTest extends AbstractListingMergeMan assertNull(address); } -@Test - public void testChangeSpaceProperty() throws Exception { + @Test + public void testChangeSpaceProperty() throws Exception { // ** DiffTestPgm2 ** // 10018ba = 1 // 10018ce = 2 @@ -1031,8 +1032,8 @@ public class UserDefinedPropertyMergeManagerTest extends AbstractListingMergeMan assertNull(address); } -@Test - public void testChangeTestColorProperty() throws Exception { + @Test + public void testChangeTestColorProperty() throws Exception { // ** DiffTestPgm2 ** // 10018ba = 1 // 10018ce = 2 @@ -1103,8 +1104,8 @@ public class UserDefinedPropertyMergeManagerTest extends AbstractListingMergeMan assertNull(address); } -@Test - public void testApplyToAllSpacePropertyConflicts() throws Exception { + @Test + public void testApplyToAllSpacePropertyConflicts() throws Exception { // ** DiffTestPgm2 ** // 10018ba = 1 // 10018ce = 2 @@ -1172,8 +1173,8 @@ public class UserDefinedPropertyMergeManagerTest extends AbstractListingMergeMan assertNull(address); } -@Test - public void testApplyToAllColorPropertyConflicts() throws Exception { + @Test + public void testApplyToAllColorPropertyConflicts() throws Exception { // ** DiffTestPgm2 ** // 10018ba = 1 // 10018ce = 2 @@ -1240,8 +1241,8 @@ public class UserDefinedPropertyMergeManagerTest extends AbstractListingMergeMan assertNull(address); } -@Test - public void testMultiplePropertyTypeConflicts() throws Exception { + @Test + public void testMultiplePropertyTypeConflicts() throws Exception { // ** DiffTestPgm2 ** // 10018ba = 1 // 10018ce = 2 @@ -1350,8 +1351,8 @@ public class UserDefinedPropertyMergeManagerTest extends AbstractListingMergeMan assertNull(address); } -@Test - public void testApplyToAllSpaceForMultipleTypeConflicts() throws Exception { + @Test + public void testApplyToAllSpaceForMultipleTypeConflicts() throws Exception { // ** DiffTestPgm2 ** // 10018ba = 1 // 10018ce = 2 @@ -1453,8 +1454,8 @@ public class UserDefinedPropertyMergeManagerTest extends AbstractListingMergeMan assertNull(address); } -@Test - public void testApplyToAllForEachConflict() throws Exception { + @Test + public void testApplyToAllForEachConflict() throws Exception { // ** DiffTestPgm2 ** // 10018ba = 1 // 10018ce = 2 @@ -1563,8 +1564,8 @@ public class UserDefinedPropertyMergeManagerTest extends AbstractListingMergeMan assertNull(address); } -@Test - public void testApplyToAllForEachConflictPickOriginal() throws Exception { + @Test + public void testApplyToAllForEachConflictPickOriginal() throws Exception { // ** DiffTestPgm2 ** // 10018ba = 1 // 10018ce = 2 @@ -1665,16 +1666,16 @@ public class UserDefinedPropertyMergeManagerTest extends AbstractListingMergeMan address = resultProgram.getMinAddress(); address = opm.getNextPropertyAddress(address); assertEquals(addr("0x100248c"), address); - assertEquals(new SaveableColor(Color.WHITE), opm.get(address)); + assertEquals(new SaveableColor(Palette.WHITE), opm.get(address)); address = opm.getNextPropertyAddress(address); assertEquals(addr("0x10039f1"), address); - assertEquals(new SaveableColor(Color.BLACK), opm.get(address)); + assertEquals(new SaveableColor(Palette.BLACK), opm.get(address)); address = opm.getNextPropertyAddress(address); assertEquals(addr("0x10039f8"), address); - assertEquals(new SaveableColor(Color.BLACK), opm.get(address)); + assertEquals(new SaveableColor(Palette.BLACK), opm.get(address)); address = opm.getNextPropertyAddress(address); assertEquals(addr("0x10039fe"), address); - assertEquals(new SaveableColor(Color.GREEN), opm.get(address)); + assertEquals(new SaveableColor(Palette.GREEN), opm.get(address)); address = opm.getNextPropertyAddress(address); assertNull(address); } diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/codebrowser/CodeBrowserOptionsTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/codebrowser/CodeBrowserOptionsTest.java index ca9d948c3c..85ec74cdff 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/codebrowser/CodeBrowserOptionsTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/codebrowser/CodeBrowserOptionsTest.java @@ -351,27 +351,27 @@ public class CodeBrowserOptionsTest extends AbstractGhidraHeadedIntegrationTest assertEquals("01", btf.getText()); assertEquals(3, btf.getNumCols(0)); FieldElement fe = btf.getFieldElement(0, 1); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); cb.goToField(addr("0x1001104"), "Bytes", 0, 0); btf = (ListingTextField) cb.getCurrentField(); assertEquals("05 06 07 08", btf.getText()); assertEquals(12, btf.getNumCols(0)); fe = btf.getFieldElement(0, 1); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); fe = btf.getFieldElement(0, 3); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); fe = btf.getFieldElement(0, 6); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); fe = btf.getFieldElement(0, 9); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); cb.goToField(addr("0x1001108"), "Bytes", 0, 0); btf = (ListingTextField) cb.getCurrentField(); assertEquals("09", btf.getText()); assertEquals(3, btf.getNumCols(0)); fe = btf.getFieldElement(0, 1); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); } @Test @@ -393,39 +393,39 @@ public class CodeBrowserOptionsTest extends AbstractGhidraHeadedIntegrationTest assertEquals("0102 0304", btf.getText()); assertEquals(10, btf.getNumCols(0)); FieldElement fe = btf.getFieldElement(0, 1); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); fe = btf.getFieldElement(0, 2); - assertEquals(BytesFieldFactory.ALIGNMENT_BYTES_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.ALIGNMENT_BYTES_COLOR, fe.getColor(0)); fe = btf.getFieldElement(0, 5); - assertEquals(BytesFieldFactory.ALIGNMENT_BYTES_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.ALIGNMENT_BYTES_COLOR, fe.getColor(0)); fe = btf.getFieldElement(0, 7); - assertEquals(BytesFieldFactory.ALIGNMENT_BYTES_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.ALIGNMENT_BYTES_COLOR, fe.getColor(0)); cb.goToField(addr("0x1001104"), "Bytes", 0, 0); btf = (ListingTextField) cb.getCurrentField(); assertEquals("0506 0708", btf.getText()); assertEquals(10, btf.getNumCols(0)); fe = btf.getFieldElement(0, 1); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); fe = btf.getFieldElement(0, 2); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); fe = btf.getFieldElement(0, 5); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); fe = btf.getFieldElement(0, 7); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); cb.goToField(addr("0x1001108"), "Bytes", 0, 0); btf = (ListingTextField) cb.getCurrentField(); assertEquals("090a 0b0c", btf.getText()); assertEquals(10, btf.getNumCols(0)); fe = btf.getFieldElement(0, 1); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); fe = btf.getFieldElement(0, 2); - assertEquals(BytesFieldFactory.ALIGNMENT_BYTES_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.ALIGNMENT_BYTES_COLOR, fe.getColor(0)); fe = btf.getFieldElement(0, 5); - assertEquals(BytesFieldFactory.ALIGNMENT_BYTES_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.ALIGNMENT_BYTES_COLOR, fe.getColor(0)); fe = btf.getFieldElement(0, 7); - assertEquals(BytesFieldFactory.ALIGNMENT_BYTES_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.ALIGNMENT_BYTES_COLOR, fe.getColor(0)); } @Test @@ -445,7 +445,7 @@ public class CodeBrowserOptionsTest extends AbstractGhidraHeadedIntegrationTest assertEquals("01 02 03 04", btf.getText()); assertEquals(12, btf.getNumCols(0)); FieldElement fe = btf.getFieldElement(0, 1); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); fe = btf.getFieldElement(0, 3); assertEquals(BytesFieldFactory.ALIGNMENT_BYTES_COLOR, fe.getColor(0)); fe = btf.getFieldElement(0, 6); @@ -458,26 +458,26 @@ public class CodeBrowserOptionsTest extends AbstractGhidraHeadedIntegrationTest assertEquals("05 06 07 08", btf.getText()); assertEquals(12, btf.getNumCols(0)); fe = btf.getFieldElement(0, 1); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); fe = btf.getFieldElement(0, 3); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); fe = btf.getFieldElement(0, 6); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); fe = btf.getFieldElement(0, 9); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); cb.goToField(addr("0x1001108"), "Bytes", 0, 0); btf = (ListingTextField) cb.getCurrentField(); assertEquals("09 0a 0b 0c", btf.getText()); assertEquals(12, btf.getNumCols(0)); fe = btf.getFieldElement(0, 1); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); fe = btf.getFieldElement(0, 3); - assertEquals(BytesFieldFactory.ALIGNMENT_BYTES_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.ALIGNMENT_BYTES_COLOR, fe.getColor(0)); fe = btf.getFieldElement(0, 6); - assertEquals(BytesFieldFactory.ALIGNMENT_BYTES_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.ALIGNMENT_BYTES_COLOR, fe.getColor(0)); fe = btf.getFieldElement(0, 9); - assertEquals(BytesFieldFactory.ALIGNMENT_BYTES_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.ALIGNMENT_BYTES_COLOR, fe.getColor(0)); } @Test @@ -498,69 +498,69 @@ public class CodeBrowserOptionsTest extends AbstractGhidraHeadedIntegrationTest assertEquals("01", btf.getText()); assertEquals(3, btf.getNumCols(0)); FieldElement fe = btf.getFieldElement(0, 1); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); cb.goToField(addr("0x1001201"), "Bytes", 0, 0); btf = (ListingTextField) cb.getCurrentField(); assertEquals("02", btf.getText()); assertEquals(3, btf.getNumCols(0)); fe = btf.getFieldElement(0, 1); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); cb.goToField(addr("0x1001202"), "Bytes", 0, 0); btf = (ListingTextField) cb.getCurrentField(); assertEquals("03", btf.getText()); assertEquals(3, btf.getNumCols(0)); fe = btf.getFieldElement(0, 1); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); cb.goToField(addr("0x1001203"), "Bytes", 0, 0); btf = (ListingTextField) cb.getCurrentField(); assertEquals("04", btf.getText()); assertEquals(3, btf.getNumCols(0)); fe = btf.getFieldElement(0, 1); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); cb.goToField(addr("0x1001204"), "Bytes", 0, 0); btf = (ListingTextField) cb.getCurrentField(); assertEquals("05 06 07 08", btf.getText()); assertEquals(12, btf.getNumCols(0)); fe = btf.getFieldElement(0, 1); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); fe = btf.getFieldElement(0, 3); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); fe = btf.getFieldElement(0, 6); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); fe = btf.getFieldElement(0, 9); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); cb.goToField(addr("0x1001208"), "Bytes", 0, 0); btf = (ListingTextField) cb.getCurrentField(); assertEquals("09", btf.getText()); assertEquals(3, btf.getNumCols(0)); fe = btf.getFieldElement(0, 1); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); cb.goToField(addr("0x1001209"), "Bytes", 0, 0); btf = (ListingTextField) cb.getCurrentField(); assertEquals("0a", btf.getText()); assertEquals(3, btf.getNumCols(0)); fe = btf.getFieldElement(0, 1); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); cb.goToField(addr("0x100120a"), "Bytes", 0, 0); btf = (ListingTextField) cb.getCurrentField(); assertEquals("0b", btf.getText()); assertEquals(3, btf.getNumCols(0)); fe = btf.getFieldElement(0, 1); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); cb.goToField(addr("0x100120b"), "Bytes", 0, 0); btf = (ListingTextField) cb.getCurrentField(); assertEquals("0c", btf.getText()); assertEquals(3, btf.getNumCols(0)); fe = btf.getFieldElement(0, 1); - assertEquals(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); + assertColorsEqual(BytesFieldFactory.DEFAULT_COLOR, fe.getColor(0)); } @SuppressWarnings("unchecked") diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/colorizer/ColorizingPluginTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/colorizer/ColorizingPluginTest.java index 0127040cad..b5335ac963 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/colorizer/ColorizingPluginTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/colorizer/ColorizingPluginTest.java @@ -441,7 +441,7 @@ public class ColorizingPluginTest extends AbstractGhidraHeadedIntegrationTest { private void assertColorForAddress(Color color, Address address) { Color appliedColor = colorizingService.getBackgroundColor(address); - assertEquals(color, appliedColor); + assertColorsEqual(color, appliedColor); assertMarkerColorAtAddress(address, color); } diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/programtree/ProgramTreePlugin1Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/programtree/ProgramTreePlugin1Test.java index 795d68a97c..0287766aba 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/programtree/ProgramTreePlugin1Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/programtree/ProgramTreePlugin1Test.java @@ -42,13 +42,8 @@ import ghidra.program.model.symbol.SourceType; import ghidra.program.model.symbol.SymbolTable; import ghidra.program.util.GroupPath; import ghidra.program.util.ProgramLocation; -<<<<<<< Upstream, based on origin/master import ghidra.util.Swing; import ghidra.util.task.TaskMonitor; -import resources.ResourceManager; -======= -import ghidra.util.task.TaskMonitorAdapter; ->>>>>>> 0eb4b9d GP-1981 - Theming - Base Module public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest { @@ -740,15 +735,9 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest { runSwing(() -> tree.removeFromView(finalNode.getTreePath())); int row = getRowForPath(node.getTreePath()); -<<<<<<< Upstream, based on origin/master - Component comp = runSwing(() -> tree.getCellRenderer() - .getTreeCellRendererComponent(tree, node, true, false, true, row, false)); - assertEquals(ResourceManager.loadImage(DnDTreeCellRenderer.CLOSED_FOLDER), -======= Component comp = tree.getCellRenderer() .getTreeCellRendererComponent(tree, node, true, false, true, row, false); assertEquals(new GIcon(DnDTreeCellRenderer.CLOSED_FOLDER), ->>>>>>> 0eb4b9d GP-1981 - Theming - Base Module ((JLabel) comp).getIcon()); } @@ -844,15 +833,10 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest { assertTrue(getView().hasSameAddresses(viewMgrService.getCurrentView())); int row = getRowForPath(child.getTreePath()); -<<<<<<< Upstream, based on origin/master - Component comp = runSwing(() -> tree.getCellRenderer() - .getTreeCellRendererComponent(tree, child, true, false, true, row, false)); - assertEquals(ResourceManager.loadImage(DnDTreeCellRenderer.VIEWED_FRAGMENT), -======= Component comp = tree.getCellRenderer() .getTreeCellRendererComponent(tree, child, true, false, true, row, false); assertEquals(new GIcon(DnDTreeCellRenderer.VIEWED_FRAGMENT), ->>>>>>> 0eb4b9d GP-1981 - Theming - Base Module + ((JLabel) comp).getIcon()); } diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/util/bean/opteditor/OptionsDialogTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/util/bean/opteditor/OptionsDialogTest.java index a8cd59fee4..48eff24326 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/util/bean/opteditor/OptionsDialogTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/util/bean/opteditor/OptionsDialogTest.java @@ -631,23 +631,14 @@ public class OptionsDialogTest extends AbstractGhidraHeadedIntegrationTest { JComponent comp = simpleOptionsPanel.getComponent(); assertTrue(comp.isShowing()); - Component component = findPairedComponent(comp, "Favorite Color"); + Component component = findPairedComponent(comp, "Favorite String"); assertNotNull(component); Rectangle rect = component.getBounds(); clickMouse(component, 1, rect.x, rect.y, 2, 0); waitForSwing(); - Window window = waitForWindow("Color Editor"); - assertNotNull(window); - - JColorChooser chooser = findComponent(window, JColorChooser.class); - assertNotNull(chooser); - chooser.setColor(Palette.BLUE); - - JButton okButton = findButtonByText(window, "OK"); - assertNotNull(okButton); - pressButton(okButton); + triggerText(component, "Bar"); waitForSwing(); @@ -658,8 +649,8 @@ public class OptionsDialogTest extends AbstractGhidraHeadedIntegrationTest { Options options = tool.getOptions(ToolConstants.TOOL_OPTIONS); Color c = options.getColor("Favorite Color", Palette.RED); - - assertColorsEqual(Palette.BLUE, c); + String currentValue = options.getString("Favorite String", null); + assertEquals("Bar", currentValue); assertTrue(tool.hasConfigChanged()); } @@ -718,10 +709,6 @@ public class OptionsDialogTest extends AbstractGhidraHeadedIntegrationTest { // Inner Classes //================================================================================================= - private void assertColorsEqual(Color c1, Color c2) { - assertEquals(c1.getRGB(), c2.getRGB()); - } - private KeyStroke getKeyBinding(String actionName) throws Exception { OptionsEditor editor = seleNodeWithCustomEditor("Key Bindings"); KeyBindingsPanel panel = (KeyBindingsPanel) getInstanceField("panel", editor); @@ -1117,8 +1104,11 @@ public class OptionsDialogTest extends AbstractGhidraHeadedIntegrationTest { options.setInt(name, 300); name = "Favorite Color"; + options.registerOption(name, Palette.RED, null, "description"); - options.setColor(name, Palette.RED); + + name = "Favorite String"; + options.registerOption(name, "Foo", null, "description"); // select the middle button name = "Mouse Buttons" + Options.DELIMITER + "Mouse Button To Activate"; diff --git a/Ghidra/Features/Base/src/test/java/ghidra/framework/data/OptionsDBTest.java b/Ghidra/Features/Base/src/test/java/ghidra/framework/data/OptionsDBTest.java index a3cb362d54..b39cc21177 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/framework/data/OptionsDBTest.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/framework/data/OptionsDBTest.java @@ -17,6 +17,7 @@ package ghidra.framework.data; import static org.junit.Assert.*; +import java.awt.Color; import java.awt.Font; import java.beans.PropertyChangeListener; import java.beans.PropertyEditorSupport; @@ -28,8 +29,10 @@ import javax.swing.KeyStroke; import org.junit.*; -import generic.test.AbstractGenericTest; +import docking.test.AbstractDockingTest; +import generic.theme.GColor; import generic.theme.GThemeDefaults.Colors.Palette; +import generic.theme.Gui; import ghidra.framework.options.*; import ghidra.framework.options.OptionsTest.FRUIT; import ghidra.program.database.ProgramBuilder; @@ -37,11 +40,12 @@ import ghidra.program.database.ProgramDB; import ghidra.util.HelpLocation; import ghidra.util.exception.InvalidInputException; -public class OptionsDBTest extends AbstractGenericTest { +public class OptionsDBTest extends AbstractDockingTest { private OptionsDB options; private ProgramBuilder builder; private int txID; + private GColor testColor; public enum fruit { Apple, Pear, Orange @@ -57,6 +61,8 @@ public class OptionsDBTest extends AbstractGenericTest { ProgramDB program = builder.getProgram(); txID = program.startTransaction("Test"); options = new OptionsDB(program); + Gui.setColor("color.test", Palette.MAGENTA); + testColor = new GColor("color.test"); } private void saveAndRestoreOptions() { @@ -280,16 +286,25 @@ public class OptionsDBTest extends AbstractGenericTest { @Test public void testGetDefaultValue() { - options.registerOption("Foo", Palette.RED, null, "description"); - options.setColor("Foo", Palette.BLUE); - assertEquals(Palette.BLUE, options.getColor("Foo", null)); - assertEquals(Palette.RED, options.getDefaultValue("Foo")); + options.registerOption("Foo", Color.RED, null, "description"); + options.setColor("Foo", Color.BLUE); + assertColorsEqual(Color.BLUE, options.getColor("Foo", null)); + assertColorsEqual(Color.RED, (Color) options.getDefaultValue("Foo")); + } + + @Test + public void testGetDefaultValueWithThemeValues() { + options.registerOption("Foo", testColor, null, "description"); + options.setColor("Foo", Color.BLUE); + assertColorsEqual(Color.BLUE, options.getColor("Foo", null)); + // registered options using theme values, don't have defaults + assertColorsEqual(Color.BLUE, (Color) options.getDefaultValue("Foo")); } @Test public void testRegisterPropertyEditor() { MyPropertyEditor editor = new MyPropertyEditor(); - options.registerOption("color", OptionType.COLOR_TYPE, Palette.RED, null, "description", + options.registerOption("color", OptionType.COLOR_TYPE, testColor, null, "description", editor); assertEquals(editor, options.getRegisteredPropertyEditor("color")); @@ -304,11 +319,20 @@ public class OptionsDBTest extends AbstractGenericTest { @Test public void testRestoreOptionValue() { - options.registerOption("Foo", Palette.RED, null, "description"); - options.setColor("Foo", Palette.BLUE); - assertEquals(Palette.BLUE, options.getColor("Foo", null)); + options.registerOption("Foo", 4, null, "description"); + options.setInt("Foo", 7); + assertEquals(7, options.getInt("Foo", 0)); options.restoreDefaultValue("Foo"); - assertEquals(Palette.RED, options.getColor("Foo", null)); + assertEquals(4, options.getInt("Foo", 0)); + } + + @Test + public void testRestoreThemeOptionValue() { + options.registerOption("Foo", testColor, null, "description"); + options.setColor("Foo", Palette.BLUE); + assertColorsEqual(Palette.BLUE, options.getColor("Foo", null)); + options.restoreDefaultValue("Foo"); + assertColorsEqual(Palette.MAGENTA, options.getColor("Foo", null)); } @Test @@ -549,7 +573,19 @@ public class OptionsDBTest extends AbstractGenericTest { @Test public void testSettingValueToNull() { - options.registerOption("Bar", Palette.BLUE, null, "description"); + // this will cause the palette color LAVENDER to be null - make sure to not use it in other + //tests + options.registerOption("Bar", "HEY", null, "description"); + options.setString("Bar", "THERE"); + options.setString("Bar", null); + assertEquals(null, options.getString("Bar", null)); + } + + @Test + public void testSettingThemeValueToNull() { + // this will cause the palette color LAVENDER to be null - make sure to not use it in other + //tests + options.registerOption("Bar", testColor, null, "description"); options.setColor("Bar", Palette.RED); options.setColor("Bar", null); assertEquals(null, options.getColor("Bar", null)); diff --git a/Ghidra/Features/Base/src/test/java/ghidra/framework/options/FileOptionsTest.java b/Ghidra/Features/Base/src/test/java/ghidra/framework/options/FileOptionsTest.java index 9b43826e78..5c327725d8 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/framework/options/FileOptionsTest.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/framework/options/FileOptionsTest.java @@ -17,6 +17,7 @@ package ghidra.framework.options; import static org.junit.Assert.*; +import java.awt.Color; import java.io.File; import java.io.IOException; @@ -33,17 +34,17 @@ public class FileOptionsTest extends AbstractGenericTest { options.registerOption("aaa", Integer.valueOf(5), null, "aaa description"); options.registerOption("bbb", Integer.valueOf(5), null, "bbb description"); - options.registerOption("ccc", Palette.RED, null, "ccc description"); + options.registerOption("ccc", Color.RED, null, "ccc description"); TestCustomOption custom = new TestCustomOption("bob", 23, true); options.setInt("aaa", 10); - options.setColor("ccc", Palette.BLUE); + options.setColor("ccc", Color.BLUE); options.setCustomOption("ddd", custom); assertEquals(10, options.getInt("aaa", 0)); assertEquals(5, options.getInt("bbb", 0)); - assertEquals(Palette.BLUE, options.getColor("ccc", null)); + assertEquals(Color.BLUE, options.getColor("ccc", null)); assertEquals(custom, options.getCustomOption("ddd", null)); File file = createTempFile("optionsFile", "options"); @@ -54,7 +55,7 @@ public class FileOptionsTest extends AbstractGenericTest { assertEquals(10, restored.getInt("aaa", 0)); assertFalse(restored.contains("bbb")); // default value should not have been saved - assertEquals(Palette.BLUE.getRGB(), restored.getColor("ccc", null).getRGB()); + assertEquals(Color.BLUE.getRGB(), restored.getColor("ccc", null).getRGB()); assertEquals(custom, restored.getCustomOption("ddd", null)); } diff --git a/Ghidra/Features/Base/src/test/java/ghidra/framework/options/OptionsTest.java b/Ghidra/Features/Base/src/test/java/ghidra/framework/options/OptionsTest.java index 17c1b8eef5..4258e982f8 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/framework/options/OptionsTest.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/framework/options/OptionsTest.java @@ -281,16 +281,16 @@ public class OptionsTest extends AbstractGenericTest { @Test public void testGetDefaultValue() { - options.registerOption("Foo", Palette.RED, null, null); - options.setColor("Foo", Palette.BLUE); - assertColorsEqual(Palette.BLUE, options.getColor("Foo", null)); - assertColorsEqual(Palette.RED, (Color) options.getDefaultValue("Foo")); + options.registerOption("Foo", Color.RED, null, null); + options.setColor("Foo", Color.BLUE); + assertColorsEqual(Color.BLUE, options.getColor("Foo", null)); + assertColorsEqual(Color.RED, (Color) options.getDefaultValue("Foo")); } @Test public void testRegisterPropertyEditor() { MyPropertyEditor editor = new MyPropertyEditor(); - options.registerOption("color", OptionType.COLOR_TYPE, Palette.RED, null, null, editor); + options.registerOption("color", OptionType.COLOR_TYPE, Color.RED, null, null, editor); assertEquals(editor, options.getRegisteredPropertyEditor("color")); } @@ -304,12 +304,12 @@ public class OptionsTest extends AbstractGenericTest { @Test public void testRestoreOptionValue() { - options.registerOption("Foo", Palette.RED, null, null); - options.setColor("Foo", Palette.BLUE); - assertColorsEqual(Palette.BLUE, options.getColor("Foo", null)); + options.registerOption("Foo", Color.RED, null, null); + options.setColor("Foo", Color.BLUE); + assertColorsEqual(Color.BLUE, options.getColor("Foo", null)); options.restoreDefaultValue("Foo"); - assertColorsEqual(Palette.RED, options.getColor("Foo", null)); + assertColorsEqual(Color.RED, options.getColor("Foo", null)); } @Test @@ -593,10 +593,6 @@ public class OptionsTest extends AbstractGenericTest { assertEquals(OptionType.NO_TYPE, options.getType("bar"));// there is no bar } - private void assertColorsEqual(Color c1, Color c2) { - assertEquals(c1.getRGB(), c2.getRGB()); - } - private void saveAndRestoreOptions() { Element root = options.getXmlRoot(false); options = new ToolOptions(root); diff --git a/Ghidra/Features/ByteViewer/data/byteviewer.theme.properties b/Ghidra/Features/ByteViewer/data/byteviewer.theme.properties index 33410878cf..bb57276970 100644 --- a/Ghidra/Features/ByteViewer/data/byteviewer.theme.properties +++ b/Ghidra/Features/ByteViewer/data/byteviewer.theme.properties @@ -18,10 +18,7 @@ font.byteviewer.status = SansSerif-PLAIN-11 [Dark Defaults] color.bg.byteviewer.highlight = rgb(191, 191, 64) // olive - -color.fg.byteviewer.novalue = DarkBlue color.fg.byteviewer.changed = indianRed -color.cursor.focused.byteviewer.current = color.cursor.focused -color.cursor.focused.byteviewer.noncurrent = gray -color.cursor.unfocused.byteviewer = color.cursor.unfocused +color.fg.byteviewer.separator = darkBlue +color.cursor.byteviewer.focused.not.active = gray diff --git a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerPanel.java b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerPanel.java index 15285f732c..13db74bbd7 100644 --- a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerPanel.java +++ b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerPanel.java @@ -74,7 +74,6 @@ public class ByteViewerPanel extends JPanel private ByteViewerComponent currentView; private Color editColor; private Color currentCursorColor; - private Color cursorColor; private Color currentCursorLineColor; private Color highlightColor; private int highlightButton; @@ -218,7 +217,6 @@ public class ByteViewerPanel extends JPanel } void setCursorColor(Color c) { - cursorColor = c; for (int i = 0; i < viewList.size(); i++) { ByteViewerComponent comp = viewList.get(i); comp.setNonFocusCursorColor(c); @@ -418,7 +416,7 @@ public class ByteViewerPanel extends JPanel ByteViewerComponent c = newByteViewerComponent(model); c.setEditColor(editColor); - c.setNonFocusCursorColor(cursorColor); + c.setNonFocusCursorColor(ByteViewerComponentProvider.CURSOR_NOT_FOCUSED_COLOR); c.setCurrentCursorColor(currentCursorColor); c.setCurrentCursorLineColor(currentCursorLineColor); c.setEditMode(editMode); diff --git a/Ghidra/Features/ByteViewer/src/test.slow/java/ghidra/app/plugin/core/byteviewer/ByteViewerConnectedToolBehaviorTest.java b/Ghidra/Features/ByteViewer/src/test.slow/java/ghidra/app/plugin/core/byteviewer/ByteViewerConnectedToolBehaviorTest.java index 771f573696..a6f0c734b0 100644 --- a/Ghidra/Features/ByteViewer/src/test.slow/java/ghidra/app/plugin/core/byteviewer/ByteViewerConnectedToolBehaviorTest.java +++ b/Ghidra/Features/ByteViewer/src/test.slow/java/ghidra/app/plugin/core/byteviewer/ByteViewerConnectedToolBehaviorTest.java @@ -157,8 +157,6 @@ public class ByteViewerConnectedToolBehaviorTest extends AbstractGhidraHeadedInt }); assertTrue(action.isSelected()); final ByteViewerComponent c = panelOne.getCurrentComponent(); - assertEquals(ByteViewerComponentProvider.CURSOR_NON_ACTIVE_COLOR, - c.getFocusedCursorColor()); runSwing(() -> { KeyEvent ev = new KeyEvent(c, 0, new Date().getTime(), 0, KeyEvent.VK_1, '1'); c.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(), loc.getCol(), @@ -168,7 +166,7 @@ public class ByteViewerConnectedToolBehaviorTest extends AbstractGhidraHeadedInt ByteViewerComponent c2 = panel2.getCurrentComponent(); ByteField f2 = c2.getField(BigInteger.ZERO, 0); - assertEquals(ByteViewerComponentProvider.CURSOR_NON_ACTIVE_COLOR, f2.getForeground()); + assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, f2.getForeground()); } @Test @@ -189,8 +187,6 @@ public class ByteViewerConnectedToolBehaviorTest extends AbstractGhidraHeadedInt }); assertTrue(action.isSelected()); final ByteViewerComponent c = panelOne.getCurrentComponent(); - assertEquals(ByteViewerComponentProvider.CURSOR_NON_ACTIVE_COLOR, - c.getFocusedCursorColor()); runSwing(() -> { KeyEvent ev = new KeyEvent(c, 0, new Date().getTime(), 0, KeyEvent.VK_1, '1'); c.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(), loc.getCol(), @@ -200,7 +196,7 @@ public class ByteViewerConnectedToolBehaviorTest extends AbstractGhidraHeadedInt ByteViewerComponent c2 = panel2.getCurrentComponent(); ByteField f2 = c2.getField(BigInteger.ZERO, 0); - assertEquals(ByteViewerComponentProvider.CURSOR_NON_ACTIVE_COLOR, f2.getForeground()); + assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, f2.getForeground()); undo(program); diff --git a/Ghidra/Features/ByteViewer/src/test.slow/java/ghidra/app/plugin/core/byteviewer/ByteViewerPlugin2Test.java b/Ghidra/Features/ByteViewer/src/test.slow/java/ghidra/app/plugin/core/byteviewer/ByteViewerPlugin2Test.java index 00a5fe6d49..33204ed217 100644 --- a/Ghidra/Features/ByteViewer/src/test.slow/java/ghidra/app/plugin/core/byteviewer/ByteViewerPlugin2Test.java +++ b/Ghidra/Features/ByteViewer/src/test.slow/java/ghidra/app/plugin/core/byteviewer/ByteViewerPlugin2Test.java @@ -1219,7 +1219,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { putColor(opt, ByteViewerComponentProvider.CURSOR_ACTIVE_COLOR_OPTION_NAME, Palette.GREEN); ByteViewerComponent c = panel.getCurrentComponent(); - assertEquals(Palette.GREEN, c.getFocusedCursorColor()); + assertColorsEqual(Palette.GREEN, c.getFocusedCursorColor()); } @Test @@ -1236,11 +1236,11 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { Options opt = tool.getOptions("ByteViewer"); // change the color for Current View Cursor Color - putColor(opt, ByteViewerComponentProvider.CURSOR_NON_ACTIVE_COLOR_OPTION_NAME, + putColor(opt, ByteViewerComponentProvider.CURSOR_NOT_FOCUSED_COLOR_OPTION_NAME, Palette.GREEN); ByteViewerComponent c = findComponent(panel, "Octal"); - assertEquals(Palette.GREEN, c.getNonFocusCursorColor()); + assertColorsEqual(Palette.GREEN, c.getNonFocusCursorColor()); } @Test @@ -1260,7 +1260,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { Palette.CYAN); ByteViewerComponent c = findComponent(panel, "Octal"); - assertEquals(Palette.CYAN, c.getNonFocusCursorColor()); + assertColorsEqual(Palette.CYAN, c.getNonFocusCursorColor()); } private void putFont(final Options options, final String optionName, final Font font) { @@ -1305,7 +1305,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { program.flushEvents(); ByteViewerComponent c = panel.getCurrentComponent(); ByteField field = c.getField(loc.getIndex(), loc.getFieldNum()); - assertEquals(Palette.GREEN, field.getForeground()); + assertColorsEqual(Palette.GREEN, field.getForeground()); } @Test @@ -1348,7 +1348,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { ByteViewerComponent c = panel.getCurrentComponent(); FieldLocation loc = getFieldLocation(getAddr(0x0f001000)); ByteField field = c.getField(loc.getIndex().subtract(BigInteger.ONE), 0); - assertEquals(Palette.GREEN, field.getForeground()); + assertColorsEqual(Palette.GREEN, field.getForeground()); } @Test diff --git a/Ghidra/Features/ByteViewer/src/test.slow/java/ghidra/app/plugin/core/byteviewer/ByteViewerPluginFormatsTest.java b/Ghidra/Features/ByteViewer/src/test.slow/java/ghidra/app/plugin/core/byteviewer/ByteViewerPluginFormatsTest.java index 5af1ec61a5..87a27d707f 100644 --- a/Ghidra/Features/ByteViewer/src/test.slow/java/ghidra/app/plugin/core/byteviewer/ByteViewerPluginFormatsTest.java +++ b/Ghidra/Features/ByteViewer/src/test.slow/java/ghidra/app/plugin/core/byteviewer/ByteViewerPluginFormatsTest.java @@ -436,7 +436,7 @@ public class ByteViewerPluginFormatsTest extends AbstractGhidraHeadedIntegration intComp.setCursorPosition(l.getIndex(), l.getFieldNum(), 0, 0); }); // color should indicate the edit - assertEquals(ByteViewerComponentProvider.CURSOR_NON_ACTIVE_COLOR, + assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, ((ByteField) intComp.getCurrentField()).getForeground()); } diff --git a/Ghidra/Features/Decompiler/data/decompiler.theme.properties b/Ghidra/Features/Decompiler/data/decompiler.theme.properties index 05bf6e874e..a3d6f1f17c 100644 --- a/Ghidra/Features/Decompiler/data/decompiler.theme.properties +++ b/Ghidra/Features/Decompiler/data/decompiler.theme.properties @@ -12,6 +12,7 @@ color.fg.decompiler.constant = forestGreen color.fg.decompiler.type = mediumBlue color.fg.decompiler.parameter = darkMagenta color.fg.decompiler.global = darkCyan +color.fg.decompiler.special = #cc0033 color.bg.decompiler.current.variable = rgba(255,255,0,0.5) color.fg.line.numbers = gray diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileOptions.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileOptions.java index 2940d98417..fff6884190 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileOptions.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileOptions.java @@ -330,11 +330,11 @@ public class DecompileOptions { private final static Color HIGHLIGHT_PARAMETER_COLOR = new GColor("color.fg.decompiler.parameter"); private final static String HIGHLIGHT_GLOBAL_MSG = "Display.Color for Globals"; - private Color globalColor; - private final static String HIGHLIGHT_SPECIAL_MSG = "Display.Color for Special"; - private final static Color HIGHLIGHT_SPECIAL_DEF = Color.decode("0xCC0033"); - private Color specialColor; private final static Color HIGHLIGHT_GLOBAL_COLOR = new GColor("color.fg.decompiler.global"); + + private final static String HIGHLIGHT_SPECIAL_MSG = "Display.Color for Special"; + private final static Color HIGHLIGHT_SPECIAL_COLOR = new GColor("color.fg.decompiler.special"); + private final static String HIGHLIGHT_DEFAULT_MSG = "Display.Color Default"; private final static Color HIGHLIGHT_DEFAULT_COLOR = new GColor("color.fg.decompiler"); @@ -399,21 +399,6 @@ public class DecompileOptions { commentHeadInclude = COMMENTHEAD_OPTIONDEFAULT; namespaceStrategy = NAMESPACE_OPTIONDEFAULT; integerFormat = INTEGERFORMAT_OPTIONDEFAULT; -<<<<<<< Upstream, based on origin/master - keywordColor = HIGHLIGHT_KEYWORD_DEF; - functionColor = HIGHLIGHT_FUNCTION_DEF; - commentColor = HIGHLIGHT_COMMENT_DEF; - variableColor = HIGHLIGHT_VARIABLE_DEF; - constantColor = HIGHLIGHT_CONST_DEF; - typeColor = HIGHLIGHT_TYPE_DEF; - parameterColor = HIGHLIGHT_PARAMETER_DEF; - globalColor = HIGHLIGHT_GLOBAL_DEF; - specialColor = HIGHLIGHT_SPECIAL_DEF; - defaultColor = HIGHLIGHT_DEFAULT_DEF; - codeViewerBackgroundColor = CODE_VIEWER_BACKGROUND_COLOR; - defaultFont = DEFAULT_FONT; -======= ->>>>>>> 47fa38a GP-1981 converting option colors to theme colors and font usages to theme properties displayLineNumbers = LINE_NUMBER_DEF; displayLanguage = ProgramCompilerSpec.DECOMPILER_OUTPUT_DEF; protoEvalModel = "default"; @@ -466,26 +451,7 @@ public class DecompileOptions { commentHeadInclude = opt.getBoolean(COMMENTHEAD_OPTIONSTRING, COMMENTHEAD_OPTIONDEFAULT); namespaceStrategy = opt.getEnum(NAMESPACE_OPTIONSTRING, NAMESPACE_OPTIONDEFAULT); integerFormat = opt.getEnum(INTEGERFORMAT_OPTIONSTRING, INTEGERFORMAT_OPTIONDEFAULT); -<<<<<<< Upstream, based on origin/master - keywordColor = opt.getColor(HIGHLIGHT_KEYWORD_MSG, HIGHLIGHT_KEYWORD_DEF); - typeColor = opt.getColor(HIGHLIGHT_TYPE_MSG, HIGHLIGHT_TYPE_DEF); - functionColor = opt.getColor(HIGHLIGHT_FUNCTION_MSG, HIGHLIGHT_FUNCTION_DEF); - commentColor = opt.getColor(HIGHLIGHT_COMMENT_MSG, HIGHLIGHT_COMMENT_DEF); - variableColor = opt.getColor(HIGHLIGHT_VARIABLE_MSG, HIGHLIGHT_VARIABLE_DEF); - constantColor = opt.getColor(HIGHLIGHT_CONST_MSG, HIGHLIGHT_CONST_DEF); - parameterColor = opt.getColor(HIGHLIGHT_PARAMETER_MSG, HIGHLIGHT_PARAMETER_DEF); - globalColor = opt.getColor(HIGHLIGHT_GLOBAL_MSG, HIGHLIGHT_GLOBAL_DEF); - specialColor = opt.getColor(HIGHLIGHT_SPECIAL_MSG, HIGHLIGHT_SPECIAL_DEF); - defaultColor = opt.getColor(HIGHLIGHT_DEFAULT_MSG, HIGHLIGHT_DEFAULT_DEF); - codeViewerBackgroundColor = - opt.getColor(CODE_VIEWER_BACKGROUND_COLOR_MSG, CODE_VIEWER_BACKGROUND_COLOR); - currentVariableHighlightColor = - opt.getColor(HIGHLIGHT_CURRENT_VARIABLE_MSG, HIGHLIGHT_CURRENT_VARIABLE_DEF); - defaultFont = opt.getFont(FONT_MSG, DEFAULT_FONT); - defaultFont = SystemUtilities.adjustForFontSizeOverride(defaultFont); - defaultSearchHighlightColor = opt.getColor(SEARCH_HIGHLIGHT_MSG, SEARCH_HIGHLIGHT_DEF); -======= ->>>>>>> 47fa38a GP-1981 converting option colors to theme colors and font usages to theme properties + displayLineNumbers = opt.getBoolean(LINE_NUMBER_MSG, LINE_NUMBER_DEF); decompileTimeoutSeconds = opt.getInt(DECOMPILE_TIMEOUT, SUGGESTED_DECOMPILE_TIMEOUT_SECS); payloadLimitMBytes = opt.getInt(PAYLOAD_LIMIT, SUGGESTED_MAX_PAYLOAD_BYTES); @@ -643,14 +609,10 @@ public class DecompileOptions { opt.registerOption(HIGHLIGHT_GLOBAL_MSG, HIGHLIGHT_GLOBAL_COLOR, new HelpLocation(HelpTopics.DECOMPILER, "DisplayTokenColor"), "Color used for highlighting global variables."); -<<<<<<< Upstream, based on origin/master - opt.registerOption(HIGHLIGHT_SPECIAL_MSG, HIGHLIGHT_SPECIAL_DEF, + opt.registerOption(HIGHLIGHT_SPECIAL_MSG, HIGHLIGHT_SPECIAL_COLOR, new HelpLocation(HelpTopics.DECOMPILER, "DisplayTokenColor"), "Color used for volatile or other exceptional variables."); - opt.registerOption(HIGHLIGHT_DEFAULT_MSG, HIGHLIGHT_DEFAULT_DEF, -======= opt.registerOption(HIGHLIGHT_DEFAULT_MSG, HIGHLIGHT_DEFAULT_COLOR, ->>>>>>> 47fa38a GP-1981 converting option colors to theme colors and font usages to theme properties new HelpLocation(HelpTopics.DECOMPILER, "DisplayColorDefault"), "The color used when a specific color is not specified."); opt.registerOption(BACKGROUND_COLOR_MSG, BACKGROUND_COLOR, @@ -874,7 +836,7 @@ public class DecompileOptions { * @return color associated with volatile variables or other special tokens */ public Color getSpecialColor() { - return specialColor; + return HIGHLIGHT_SPECIAL_COLOR; } /** diff --git a/Ghidra/Features/Decompiler/src/test.slow/java/ghidra/app/decompiler/component/DecompilerClangTest.java b/Ghidra/Features/Decompiler/src/test.slow/java/ghidra/app/decompiler/component/DecompilerClangTest.java index f0dd1dca60..4c4ca9b293 100644 --- a/Ghidra/Features/Decompiler/src/test.slow/java/ghidra/app/decompiler/component/DecompilerClangTest.java +++ b/Ghidra/Features/Decompiler/src/test.slow/java/ghidra/app/decompiler/component/DecompilerClangTest.java @@ -971,7 +971,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest { removeSecondaryHighlight(); Color hlColor2 = highlight(); - assertEquals(myColor, hlColor2); + assertEquals(myColor.getRGB(), hlColor2.getRGB()); } @Test @@ -1981,7 +1981,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest { Color hlColor = getSecondaryHighlight(token); assertNotNull("No highlight for token: " + token, hlColor); - assertEquals(color, hlColor); + assertEquals(color.getRGB(), hlColor.getRGB()); } private void removeSecondaryHighlight() { @@ -2279,7 +2279,17 @@ public class DecompilerClangTest extends AbstractDecompilerTest { public boolean matches(Color otherColor) { for (Color c : myColors) { - if (Objects.equals(c, otherColor)) { + if (c == null) { + if (otherColor == null) { + return true; + } + continue; + } + if (otherColor == null) { + continue; + } + + if (c.getRGB() == otherColor.getRGB()) { return true; } } diff --git a/Ghidra/Features/FunctionGraph/src/test.slow/java/ghidra/app/plugin/core/functiongraph/AbstractFunctionGraphTest.java b/Ghidra/Features/FunctionGraph/src/test.slow/java/ghidra/app/plugin/core/functiongraph/AbstractFunctionGraphTest.java index 7c91d7d701..cb4ea223ea 100644 --- a/Ghidra/Features/FunctionGraph/src/test.slow/java/ghidra/app/plugin/core/functiongraph/AbstractFunctionGraphTest.java +++ b/Ghidra/Features/FunctionGraph/src/test.slow/java/ghidra/app/plugin/core/functiongraph/AbstractFunctionGraphTest.java @@ -2082,8 +2082,7 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte protected void verifyColor(FGVertex vertex, Color expectedColor) { Color currentBackgroundColor = vertex.getBackgroundColor(); - assertEquals("Color of vertex is not as expected - vertex: " + vertex, expectedColor, - currentBackgroundColor); + assertColorsEqual(expectedColor, currentBackgroundColor); } protected void verifyDefaultColor(FGVertex... vertices) { diff --git a/Ghidra/Features/FunctionGraph/src/test.slow/java/ghidra/app/plugin/core/functiongraph/FunctionGraphPlugin1Test.java b/Ghidra/Features/FunctionGraph/src/test.slow/java/ghidra/app/plugin/core/functiongraph/FunctionGraphPlugin1Test.java index 516a0e4360..0ed501eaac 100644 --- a/Ghidra/Features/FunctionGraph/src/test.slow/java/ghidra/app/plugin/core/functiongraph/FunctionGraphPlugin1Test.java +++ b/Ghidra/Features/FunctionGraph/src/test.slow/java/ghidra/app/plugin/core/functiongraph/FunctionGraphPlugin1Test.java @@ -627,7 +627,7 @@ public class FunctionGraphPlugin1Test extends AbstractFunctionGraphTest { chooseColor(focusedVertex, testColor); Color newVertexBackgroundColor = focusedVertex.getUserDefinedColor(); - assertEquals("Background color not set", testColor, newVertexBackgroundColor); + assertColorsEqual(testColor, newVertexBackgroundColor); DockingAction clearColorAction = getClearColorAction(focusedVertex); performAction(clearColorAction, graphProvider, true); diff --git a/Ghidra/Features/FunctionGraph/src/test.slow/java/ghidra/app/plugin/core/functiongraph/FunctionGraphPlugin2Test.java b/Ghidra/Features/FunctionGraph/src/test.slow/java/ghidra/app/plugin/core/functiongraph/FunctionGraphPlugin2Test.java index ea194d9a5b..d9376c9dfd 100644 --- a/Ghidra/Features/FunctionGraph/src/test.slow/java/ghidra/app/plugin/core/functiongraph/FunctionGraphPlugin2Test.java +++ b/Ghidra/Features/FunctionGraph/src/test.slow/java/ghidra/app/plugin/core/functiongraph/FunctionGraphPlugin2Test.java @@ -285,7 +285,7 @@ public class FunctionGraphPlugin2Test extends AbstractFunctionGraphTest { // make sure the service is also cognizant of the color change appliedBackgroundColor = colorizingService.getBackgroundColor(vertex.getVertexAddress()); - assertEquals(testColor, appliedBackgroundColor); + assertColorsEqual(testColor, appliedBackgroundColor); Color vBg = vertex.getBackgroundColor(); assertEquals(appliedBackgroundColor, vBg); @@ -333,8 +333,8 @@ public class FunctionGraphPlugin2Test extends AbstractFunctionGraphTest { Color newBackgroundColor = colorizingService.getBackgroundColor(focusedVertex.getVertexAddress()); - assertEquals("'Set Most Recent Color' action did not apply that color to the color service", - mostRecentColor, newBackgroundColor); + // "'Set Most Recent Color' action did not apply that color to the color service" + assertColorsEqual(mostRecentColor, newBackgroundColor); } // TODO: see SCR 9208 - we don't currently support this, although we could diff --git a/Ghidra/Framework/Docking/certification.manifest b/Ghidra/Framework/Docking/certification.manifest index 0743e8c7e5..abe644a7bf 100644 --- a/Ghidra/Framework/Docking/certification.manifest +++ b/Ghidra/Framework/Docking/certification.manifest @@ -12,7 +12,11 @@ data/ExtensionPoint.manifest||GHIDRA||||END| data/docking.palette.theme.properties||GHIDRA||||END| data/docking.theme.properties||GHIDRA||||END| src/main/help/help/TOC_Source.xml||GHIDRA||||END| -src/main/help/help/topics/Theming/Theming.htm||GHIDRA||||END| +src/main/help/help/topics/Misc/Welcome_to_Help.htm||GHIDRA||||END| +src/main/help/help/topics/Theming/ThemingDeveloperDocs.html||GHIDRA||||END| +src/main/help/help/topics/Theming/ThemingInternals.html||GHIDRA||||END| +src/main/help/help/topics/Theming/ThemingOverview.html||GHIDRA||||END| +src/main/help/help/topics/Theming/ThemingUserDocs.html||GHIDRA||||END| src/main/help/help/topics/Theming/images/ColorEditor.png||GHIDRA||||END| src/main/help/help/topics/Theming/images/FontEditor.png||GHIDRA||||END| src/main/help/help/topics/Theming/images/IconEditor.png||GHIDRA||||END| @@ -22,8 +26,6 @@ src/main/java/docking/options/editor/package.html||GHIDRA||reviewed||END| src/main/java/docking/widgets/fieldpanel/package.html||GHIDRA||reviewed||END| src/main/java/docking/widgets/filechooser/package.html||GHIDRA||reviewed||END| src/main/java/docking/wizard/package.html||GHIDRA||reviewed||END| -src/main/resources/images/EmptyIcon.gif||GHIDRA||reviewed||END| -src/main/resources/images/EmptyIcon16.gif||GHIDRA||reviewed||END| src/main/resources/images/Plus.png||GHIDRA||reviewed||END| src/main/resources/images/StackFrameElement.png||GHIDRA||reviewed||END| src/main/resources/images/StackFrame_Red.png||GHIDRA||reviewed||END| @@ -32,18 +34,15 @@ src/main/resources/images/application-vnd.oasis.opendocument.spreadsheet-templat src/main/resources/images/application_xp.png||FAMFAMFAM Icons - CC 2.5|||fam fam|END| src/main/resources/images/arrow.gif||GHIDRA||||END| src/main/resources/images/bullet_delete.png||FAMFAMFAM Icons - CC 2.5||||END| +src/main/resources/images/check.png||GHIDRA||||END| src/main/resources/images/checkmark_green.gif||GHIDRA||reviewed||END| src/main/resources/images/close16.gif||GHIDRA||reviewed||END| src/main/resources/images/closedFolder.png||Modified Nuvola Icons - LGPL 2.1||||END| src/main/resources/images/collapse.gif||GHIDRA||||END| -src/main/resources/images/collapse_all.png||GHIDRA||||END| src/main/resources/images/computer.png||Tango Icons - Public Domain|||tango|END| src/main/resources/images/desktop.png||Nuvola Icons - LGPL 2.1|||Nuvola icon set|END| -src/main/resources/images/dialog-cancel.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| src/main/resources/images/dialog-warning.png||Oxygen Icons - LGPL 3.0||||END| -src/main/resources/images/disk.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/document-properties.png||Tango Icons - Public Domain|||tango icon set|END| -src/main/resources/images/down.png||GHIDRA||reviewed||END| src/main/resources/images/drive.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/eatbits.gif||GHIDRA||reviewed||END| src/main/resources/images/eatbits1.png||GHIDRA||reviewed||END| @@ -54,8 +53,6 @@ src/main/resources/images/eatbits5.png||GHIDRA||reviewed||END| src/main/resources/images/eatbits6.png||GHIDRA||reviewed||END| src/main/resources/images/eatbits7.png||GHIDRA||reviewed||END| src/main/resources/images/edit-clear.png||Tango Icons - Public Domain|||tango icon set|END| -src/main/resources/images/edit-cut.png||Tango Icons - Public Domain|||tango icon set|END| -src/main/resources/images/edit-cut22.png||Tango Icons - Public Domain|||original name edit-cut.png in tango 22x22|END| src/main/resources/images/edit-delete.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| src/main/resources/images/edit-undo.png||Tango Icons - Public Domain|||tango icon set|END| src/main/resources/images/expand.gif||GHIDRA||||END| @@ -63,7 +60,6 @@ src/main/resources/images/filter_off.png||GHIDRA||||END| src/main/resources/images/filter_on.png||GHIDRA||||END| src/main/resources/images/folder-open.png||Tango Icons - Public Domain||||END| src/main/resources/images/folder_add.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| -src/main/resources/images/go-home.png||Tango Icons - Public Domain|||tango icon set|END| src/main/resources/images/hourglass.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/hourglass24_01.png||GHIDRA||reviewed||END| src/main/resources/images/hourglass24_02.png||GHIDRA||reviewed||END| @@ -79,13 +75,8 @@ src/main/resources/images/hourglass24_11.png||GHIDRA||reviewed||END| src/main/resources/images/image-missing.png||Oxygen Icons - LGPL 3.0||||END| src/main/resources/images/info_small.png||GHIDRA||||END| src/main/resources/images/info_small_hover.png||GHIDRA||||END| -src/main/resources/images/information.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/inode-directory.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| -src/main/resources/images/left.alternate.png||GHIDRA||||END| -src/main/resources/images/left.png||GHIDRA||reviewed||END| src/main/resources/images/list-remove.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| -src/main/resources/images/locationIn.gif||GHIDRA||||END| -src/main/resources/images/locationOut.gif||GHIDRA||||END| src/main/resources/images/magnifier.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/mail-folder-outbox.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| src/main/resources/images/mail-receive.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| @@ -102,24 +93,17 @@ src/main/resources/images/page_green.png||FAMFAMFAM Icons - CC 2.5||||END| src/main/resources/images/play.png||GHIDRA||||END| src/main/resources/images/preferences-system-windows.png||Tango Icons - Public Domain||||END| src/main/resources/images/redo.png||GHIDRA||||END| -src/main/resources/images/reload.png||Nuvola Icons - LGPL 2.1|||Nuvola icon set|END| -src/main/resources/images/right.alternate.png||GHIDRA||||END| -src/main/resources/images/right.png||GHIDRA||reviewed||END| src/main/resources/images/software-update-available.png||Tango Icons - Public Domain|||tango icon set|END| -src/main/resources/images/sortascending.png||GHIDRA||reviewed||END| -src/main/resources/images/sortdescending.png||GHIDRA||reviewed||END| src/main/resources/images/table.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/tag.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| +src/main/resources/images/text_lowercase.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/textfield_rename.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/tip.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| src/main/resources/images/trash-empty.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| src/main/resources/images/undo.png||GHIDRA||||END| -src/main/resources/images/up.png||GHIDRA||reviewed||END| src/main/resources/images/user-home.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| src/main/resources/images/view-filter.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| -src/main/resources/images/viewmagfit.png||Nuvola Icons - LGPL 2.1|||Nuvola icon set|END| src/main/resources/images/warning.help.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| -src/main/resources/images/warning.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/weather-clear.png||Tango Icons - Public Domain|||tango icon set|END| src/main/resources/images/weather-few-clouds-reverse.png||Tango Icons - Public Domain||||END| src/main/resources/images/weather-few-clouds.png||Tango Icons - Public Domain|||tango icon set|END| diff --git a/Ghidra/Framework/Docking/data/docking.theme.properties b/Ghidra/Framework/Docking/data/docking.theme.properties index d12c57c625..43e61430b3 100644 --- a/Ghidra/Framework/Docking/data/docking.theme.properties +++ b/Ghidra/Framework/Docking/data/docking.theme.properties @@ -91,56 +91,14 @@ color.bg.fieldpanel.selection.and.highlight = green // docking buttons color.fg.button = black -// Icons files -icon.empty = EmptyIcon16.gif -icon.empty.20 = EmptyIcon.gif -icon.help = help-browser.png -icon.home = go-home.png -icon.add = Plus2.png +icon.folder.new = folder_add.png icon.subtract = list-remove.png -icon.clear = erase16.png -icon.error = emblem-important.png -icon.delete = icon.error -icon.collapse.all = collapse_all.png -icon.expand.all = expand_all.png icon.toggle.expand = expand.gif icon.toggle.collapse = collapse.gif -icon.configure.filter = exec.png -icon.navigate.in = locationIn.gif -icon.navigate.out = locationOut.gif -icon.not.allowed = dialog-cancel.png -icon.folder.closed = closedSmallFolder.png -icon.folder.open = openSmallFolder.png -icon.folder.new = folder_add.png -icon.refresh = reload3.png -icon.sort.ascending = sortascending.png -icon.sort.descending = sortdescending.png -icon.stop = process-stop.png -icon.information = information.png -icon.warning = warning.png -icon.warning.strong = software-update-urgent.png -icon.left = left.png -icon.right = right.png -icon.left.alt = left.alternate.png -icon.right.alt = right.alternate.png -icon.save = disk.png -icon.save.as = disk_save_as.png -icon.make.selection = 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.font = text_lowercase.png -icon.up = up.png -icon.down = down.png -icon.copy = page_white_copy.png -icon.cut = edit-cut.png -icon.paste = page_paste.png icon.rename = textfield_rename.png icon.check = check.png icon.search = magnifier.png diff --git a/Ghidra/Framework/Docking/src/main/help/help/TOC_Source.xml b/Ghidra/Framework/Docking/src/main/help/help/TOC_Source.xml index 9ec1fd5b9f..584eba039b 100644 --- a/Ghidra/Framework/Docking/src/main/help/help/TOC_Source.xml +++ b/Ghidra/Framework/Docking/src/main/help/help/TOC_Source.xml @@ -49,8 +49,19 @@ - + + + + + + + + + diff --git a/Ghidra/Framework/Docking/src/main/help/help/topics/Misc/Welcome_to_Help.htm b/Ghidra/Framework/Docking/src/main/help/help/topics/Misc/Welcome_to_Help.htm new file mode 100644 index 0000000000..4291313572 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/help/help/topics/Misc/Welcome_to_Help.htm @@ -0,0 +1,26 @@ + + + + Welcome to Help + + + + + + + + + + + +

Welcome to Help...

+ +
+

We provide context sensitive help on menu items, dialogs, buttons, +and tool windows. To access the help, press <F1> or <Help> on +any menu item or dialog. If specific help is not available for an item, +this page will be displayed.

+
+ + + diff --git a/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingDeveloperDocs.html b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingDeveloperDocs.html new file mode 100644 index 0000000000..54d08f820e --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingDeveloperDocs.html @@ -0,0 +1,441 @@ + + + + + + + Theming Developer Documentation + + + + + + Theming Development Documentation + +

Ghidra Theming Developer Documentation

+ +

This document provides everything an application developer should know when developing + plugins, scripts, etc., that use colors, fonts, or icons. By following these guidelines, + developers can easily make use of Ghidra's theming capabilities.

+ +

Theme Resource Types

+ +

When developing application code for Ghidra such as plugins, actions, etc., developers often + want to use a color, font, or icon. The key idea to support theming is to never directly + reference these resources. Instead, the developer should "create" an id string for the resource + and then in a .theme.properties file provide a default value for that id (and if appropriate, + also define an alternate default value if the theme is a "dark" theme).  The way you + define and use these ids is a bit different depending on whether the resource is a color, font, + or icon. Colors and Icons are similar in that references are done using either GColor or GIcon, + Unfortunately, because of the way Fonts are implemented, there is no GFont, so using fonts is a + bit more involved.

+ +
+

Colors

+ +

For colors, developers should use the GColor class. Simply construct a new GColor object + passing in the color resource id as the argument. GColor is a subclass of Color, so it can be + used anywhere a Color would be used. The developer then needs to provide a default value for + that id in the module's theme.properties file. So, for example:

+ +
+
+ panel.setBackground(Color.Red); +
+ +

becomes

+ +
+ panel.setBackground(new GColor("color.bg.abc")); +
+ +

and

+ +
+ public static final Color MY_COLOR = Color.BLUE; +
+ +

becomes

+ +
+ public static final Color MY_COLOR = new + GColor("color.fg.xzy"); +
+
+ +

The GColor class uses a delegation model where all method calls to GColor get mapped to + its delegate. If ever the color associated with a GColor's resource id changes, the GColor is + refreshed by calling the refresh() method. This is done automatically whenever the + Gui.setColor(id) is called or a new theme is loaded.

+ +

Fonts

+ +

Unfortunately, fonts able to use the delegation trick that was used for colors. Therefore, + there is no GFont class. Programming fonts requires a bit more work. If the use of a font is + in a renderer or in a paint method, imply get the font each time from the Gui class (Font + font = Gui.getFont(String id)). To set a font on a component, use the "registerFont" method + on the Gui class. Once the component is registered, the application will automatically update + the component's font if the font associated with that id changes. So, for example:

+ +
+
+ Font font = new Font("Monospaced", Font.BOLD, 12); +
+ +

becomes

+ +
+ Font font = Gui.getFont("font.xyz"); +
+ +

or

+ +
+ myLabel.setFont(new Font("Dialog", Font.PLAIN, 14) +
+ +

becomes

+ +
+ Gui.registerFont(myLabel, "font.xyz"); +
+
+ +

Icons

+ +

Icons work just like colors, so you can just create a GIcon(String id). So, for + example, 

+ +
+
+ public static final Icon MY_ICON = + ResourceManager("images/balloon.png"); +
+ +

becomes

+ +
+ public static final Icon MY_ICON = new + GIcon("icon.text.bubble"); +
+
+
+ +

Resource Id Strings

+ +
+

Resource Ids are strings used to identify the color, font, or icon. These strings are + "made up" by the developer and should be chosen in a way that it is as self describing as + possible. So, for example, if you wanted the text color in some error message in some widget + "abc", you might create the color id "color.fg.abc.error". To make resource ids as consistent + as possible, we created a convention for ids as follows: 

+ +
+
+
+
+     [type].[category[...]].[client].[specialized uses]
+
+
+
+
+ + + +
+

Examples:

+ +
    +
  • color.bg
  • + +
  • color.bg.listing
  • + +
  • font.listing
  • + +
  • font.listing.header
  • + +
  • icon.error
  • + +
  • icon.delete
  • + +
  • icon.plugin.byteviewer.provider
  • +
+
+
+ +

Theme Property Files

+ +
+

The default values for resource ids are defined in "theme property" files that created in + each module's data directory. For small modules there can be just one theme properties, but + larger modules should probably use multiple files; one for each sub-feature. The application + will find all theme property files as long as they exist in a module's data directory and end + with '.theme.properties'.

+ +

Theme Properties File Naming Convention

+ +

To promote consistency, theme property files should use the following naming + convention:

+ +
+
+
+
+      [module name][.additional name]].theme.properties
+
+
+
+ +

Examples:

+ +
    +
  • base.theme.properties
  • + +
  • base.funtiongraph.theme.properties
  • +
+
+ +

Theme Properties File Format

+ +

Theme files uses a very simple format for specifying theme property values. Each line + specifies a property id (sometimes referfed to as key) and a value, separated by an "=". A + theme properties file consists of two sections: the standard defaults section and a section + for specifying defaults for "dark" themes. So a file theme file uses the following + format:

+ +
+ +
+[Defaults]
+
+[property id 1] = [some value]
+[property id 2] = [some value]
+[property id 3] = [some value]
+...
+
+[Dark Defaults]
+
+[property id 1] = [some value]
+[property id 2] = [some value]
+...
+
+
+
+ +

Example:

+ +
+
+[Defaults]
+ 
+color.bg = white
+color.bg.listing = color.bg
+ 
+color.fg.listing.address = black
+color.fg.listing.bytes = #00ff00
+ 
+font.global = courirer-BOLD-12
+font.global.listing = font.global
+ 
+icon.error = defaultError.png
+ 
+ 
+[Dark Defaults]
+ 
+color.bg = black
+ 
+color.fg.listing.address = gray
+color.fg.listing.bytes = orange
+
+
+ +

NOTE: The [Dark Defaults] section is for overriding values defined in the standard + [Defaults] section. If a property id is not given a value in the defaults section, it is an + error. If a value is not defined in the [Dark Defaults] section, then the value defined in + the [Defaults] section will be used in a dark theme.

+
+ +

Theme Property Values

+ +
+

The values specified in the theme properties files can be specified in a variety of ways, + including ways to modify other property values. For example, an icon's size can be modified + directly in the theme properties file. A font value can specified as a reference to another + defined font, but with a different size or style.

+ +

Also, any value can also be a reference to some other id of the same type. So, for + example, a reference color entry might be something like "color.bg.listing = color.bg". This + says that the listing's background color should be whatever "color.bg" is defined to be. Note + that all of the application's defined properties start with either "color.", "font.", or + "icon.". Properties defined by a Java LookAndFeel don't follow this pattern. To reference a + property that does not have a standard prefix, an id can be prefixed with "[color]", + "[font]", or "[icon] as appropriate to allow the theme property parser to recognize the + values as ids to other properties. So to refer to a property named "table.background, it + would be "color.bg.table = [color]table.background".

+ +

Color Values

+ +

Color values supports the following formats:

+ +
+
    +
  • #rrggbb
  • + +
  • #rrggbbaa
  • + +
  • 0xrrggbb
  • + +
  • 0xrrggbbaa
  • + +
  • rgb(red, green, blue)
  • + +
  • rgba(red, green, blue, alpha)
  • + +
  • [web color name] the name of a web color such as red, olive, or purple
  • +
+
+ +

Examples:

+
+        color.foo = #0000ff             // blue
+        color.foo = #ff000080           // red with half transparency
+        color.foo = 0x00ff00            // green 
+        color.foo = 0xff000080          // red with half transparency
+        color.foo = rgb(0, 0, 255)      // blue
+        color.foo = rgba(255,0, 0, 128) // red with half transparency
+        color.foo = blue                // web color defined as 0x0000FF
+        color.foo = LawnGreen           // web color defined as 0x7CFC00
+
+ +

Font Values

+ +

Font values are specified using the following format:

+ +
+
+
+      [family name]-[style]-[size]
+
+
+ +
    +
  • family name: the font name such as monospaced, dialog, courier.
  • + +
  • style: One of PLAIN, BOLD, ITALIC, or BOLDITALIC.
  • + +
  • size: the font point size. 12 is very common.
  • +
+
+ +

Examples:

+
+        font.foo = monospaced-PLAIN-12
+        font.foo = courier-BOLD-14
+        font.foo = SansSerif-ITALIC=10
+
+ +

Font Modifiers

+ +

When referencing another font, the referenced font can be modified using the following + format:

+ +
+
+
+      font.ref[family name][style][size]
+
+
+ +
    +
  • font.ref - the theme property id of some other font
  • + +
  • family name: use the size and style of the reference font, but use this font + family
  • + +
  • style: use the same font as the reference font, but with this style. One of PLAIN, + BOLD, ITALIC, or BOLDITALIC
  • + +
  • size: use the same font as the reference font, but with this size.
  • +
+
+ +

Examples:

+
+        font.foo = SansSerif-PLAIN-12   // standard font spec
+        font.bar = font.foo[BOLD]       // results in SansSerif-BOLD-12
+        font.bar = font.foo[15]         // results in SansSerif-PLAIN-15
+        font.bar = font.foo[monospaced] // results in monospaced-PLAIN-12
+        font.bar = font.foo[ITALIC][15] // results in SansSerif-ITALIC-15
+
+ +

Icon Values

+ +

Icon are specified by simply entering the name of an icon that is in the classpath. + However, an icon value can get complicated because it can be modified in a number of ways, + such as scaling, disabling, even overlaying other icons. The format is as follows:

+ +
+
+
+      iconName[size(width,height)][disabled]{iconOverlayName[size(width,geight)[disabled][move(x,y)]}{...}
+
+
+
+ +
    +
  • iconName - the name the base icon
  • + +
  • size(width,height) - optional modifier to scale the image to the given size.
  • + +
  • disabled - optional modifier to create a disabled version of the icon.
  • + +
  • {...} - optional modifier to overlay an icon on the base icon. It is recursively + defined using the same format.
  • + +
  • move(x,y) - optional modifier on overlays to position them relative to the base + icon.
  • +
+
+ +

Examples:

+
+        icon.foo = house.png               // using the icon house.png found as an image resource on the classpath
+        icon.foo = house.png[size(10,10)]  // uses the house.png icon, but scales it to 10x10
+        icon.foo = house.png[disabled]     // creates a disabled version of house.png
+        icon.foo = house.png[16,16]{hammer.png[size(4,4)][move(12,12)]} 
+                                                // creates a 16x16 version of the house icon with a 4x4 scaled 
+                                                // hammer.icon overlayed in its lower right corner
+
+ +

To create an icon suitable for dynamically overlaying other icons, there is special syntax + for specifying an empty base icon, then overlay another icon in some specific area of the + empty icon. This icon can then be used to overlay dynamically in the code. For example, to + create an overlay icon that would add a flag to the bottom, right corner any other iconw:

+
+        icon.foo = EMPTY_ICON[size(16,16)]{flag.png[size(6,6)][move(10,10)]}
+
+ +

Related Topics

+ +
+
+ + diff --git a/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingInternals.html b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingInternals.html new file mode 100644 index 0000000000..eaa3667ba8 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingInternals.html @@ -0,0 +1,186 @@ + + + + + + + Theming Internals Documentation + + + + +

Ghidra Theming Internals Documentation

+ +

This document describes the api for initializing and managing themes. A theme (the GTheme + class) in Ghidra represents a specific LookAndFeel as well the set of values for the color, + font, and icon resource ids used in the application.  The Gui class provides a set of + static methods that serves as the primary interface for managing all aspects of theming.

+ +

GTheme class

+ +

The GTheme class is the implementation of the theme concept. At any giving time, the + application is using resource values as specified by an  active theme. The theme specifies + the LookAndFeel, whether or not the overall theme is "dark" (which determines which default + values to use) and any resource values which have been overridden specifically by that theme. + There are two types of of themes; "built-in"  themes and file based themes. "Built-in" + themes are implemented directly as sub-classes of GTheme and simply specify a Java LookAndFeel + and whether or not the theme is "dark". There is one "built-in" theme for each supported + LookAndFeel. File based themes read their values from a theme file. Theme files are created by + editing and saving existing themes.

+ +

GThemeValueMap / ThemeValue class

+ +

These are the base classes for storing values for resource ids.  A GThemeValueMap + consists of three hashmaps; one each for colors, fonts, and icons. Each hashmap maps an id to a + appropriate subclass of ThemeValue, which is the base class for ColorValue, FontValue, and + IconValue. Resource values are stored in these ThemeValue sub-classes because the value can be + either a concrete value or be a reference to some other resource of the same type. So, for + example, "color.bg.foo" could map directly to an actual color or its value could be reference + to some other indirect color like "color.bg.bar". In any ThemeValue object, either the + referenceId or the direct value must be null.  To get the ultimate concrete value, there + is a convenience method called "get" on ThemeValues that takes a GThemeValueMap as an argument. + This method will recursively resolve referenceIds which is why it needs a value map as an + argument.

+ +

GThemeValueMaps have some convenience methods for doing set operations.  You can load + values from other GThemeValueMaps into this map, which adds to the current map, replacing + values with the same id with values from the other map. Also, there is a method for getting the + differences from one GThemeValueMap to another. 

+ +

Gui class

+ +

The Gui class is a set of static methods that provides the primary API for managing themes. + It has methods for switching themes, adding themes, deleting themes, saving themes, restoring + themes, getting/setting values for resource ids, adding theme listeners, and others.

+ +

Application Initialization

+ +

Applications need to call Gui.initialize() before any uses of color, fonts, or icons occur. + This will load all resource defaults from the theme.properties files, read the last used theme + from preferences, and load that theme which includes setting the LookAndFeel.

+ +

Loading a Theme

+ +

Loading a theme consists of two main operations. Loading the LookAndFeel and building the + set of values for the resource ids.

+ +

Loading the LookAndFeel

+ +

Because each LookAndFeel present different challenges to the theming feature, there is a + LookAndFeelManager for each LookAndFeel. The LookAndFeelManager is responsible for installing + the lookAndFeel (in the case of Nimbus, we had to install a special subclass of the + NimbusLookAndFeel),  extracting the Java resources mappings(Java LookAndFeel objects also + use a resource id concept), group the java resources into common groups,  possibly fix up + some issues specific to that LookAndFeel, possibly install global properties, and have specific + update (kicking) techniques to get that LookAndFeel to update its componentUIs when values + change.

+ +

Creating the Active Theme Values

+ +

After the LookAndFeel is loaded and the java values extracted, the final resource mapping is + created. This is done by loading various resource values sets(each stored in a GThemeValueMap) + in the correct order into a new GThemeValueMap in GUI called "currentValues" .  When + values are loaded into a GThemeValueMap, they will replace any existing values with the same + id.  The values are loaded in the following order:

+ +
+ +
+ +

Changing Values Associated With Resource Ids

+ +

Whenever the value associated with a resource id changes, the application gets "kicked" in + various ways to update the display with the new value. The technique used to "kick" the + application differs depending on the resource type and the LookAndFeel (these differences are + captured in the LookAndFeelManager sub-classes for each LookAndFeel).  It can also vary + depending on whether the value is an application defined resource or a java defined + resource.

+ +

Updating Colors

+ +

Updating Colors is the easiest of all the resource. First GColor.refreshAll() is called, + which causes every GColor to refresh its delegate. Next, repaint() is called on all the top + level java windows in the application. Also, since color values in the UIDefaults are actually + replaced with GColor objects, this technique works for both application defined resources and + java defined resources.

+ +

Updating Fonts

+ +

Updating Fonts is a bit more involved. First, if the changed font is java defined, the + UIDefaults for that font Id (and any that derive from it) are updated. Next, all the components + that have a registeredFontId are updated, and finally the updateComponentTreeUI method is + called on all windows in the application.

+ +

Updating Icons

+ +

Updating Icons is a mixed bag. If the Icon is application defined, GIcon.refreshAll() is + called which causes every GIcon to refresh its delegate and then call repaint on all the + windows. If the icon is java defined, then the UIDefaults has to be updated and the + updateComponentTreeUI method on all windows is called.

+ +

Creating/Editing/Saving Themes

+ +

New themes can be created and saved to files in the theme directory in the users ghidra + application directory. When the application is started, this directory is scanned and any + .theme files are loaded and available to be selected as the active theme. The Gui class has + methods for setting the value of a color, font, or icon for a given resource id. If any values + are currently different from the active theme, the theme can be saved. If the active theme is a + built-in theme, then the only choice is to save the theme with a new theme name. Saving the + theme will create a new xxx.theme file where xxx is the name of the theme. Otherwise, the + existing theme file can be overwritten or a new theme name can be supplied to save to a new + file.

+ +

External Icons

+ +

When settings icons for an icon resource id, the user has the option of using a icon that + exists on the application classpath or using any supported icon file (.png or .gif) If the user + chooses to use an icon file, then that icon will be copied into an images directory in their + application directory (.ghidra). These icons are considered external in that if the theme were + given to another user, you would also need to give them the icon files.

+ +

Importing/Exporting Themes

+ +

Themes can be shared with other users by exporting and importing themes. When exporting a + theme that doesn't use any external icons (icons not on the classpath), the theme can be + exported to a .theme file of the users choosing. If the theme does contain external icons, the + user has the option to save the theme as a .zip file which would contain both the .theme file + and all the external icon files.

+ +

LookAndFeel Notes

+ +

Getting the theming feature to work on all the various Java LookAndFeels is a + challenge.  Java created the concept of UiDefaults, which is a mapping of property names + to values. The implication is that users can change default values by setting values on the + UIDefaults. Unfortunately, not all LookAndFeels support this concept. Nimbus and GTK+, in + particular are problematic. Nimbus sort of honors values in UIDefaults, but only if they are + installed before Nimbus is loaded. So for out theming purposes, we had to extend the Nimbus + LookAndFeel in order to override the getDefaults() method (this is the method where + LookAndFeels populate the UiDefaults) so that we can install any overridden values from the + selected theme. Also, every time a Java defined property changes, we have to re-install the + Nimbus LookAndFeel because once it is installed, it no longer pays attention to changes to the + UIDefaults.  The GTK+ LookAndFeel is even more problematic. It gets many of its properties + from native libraries and there doesn't appear to be anyway of changing them. Therefore, themes + based on GTK+ doesn't allow for changing java defined values.  To compensate for the + differences among LookAndFeels, we created a LookAndFeelManager base class with sub-classes for + each LookAndFeel that addresses these differences.

+ +

Related Topics

+ +
+ + diff --git a/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingOverview.html b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingOverview.html new file mode 100644 index 0000000000..d0b5b8e364 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingOverview.html @@ -0,0 +1,118 @@ + + + + + + + Theming Overivew + + + + +

Ghidra Theming Overview

+ +

Goal

+ +

The goal was to add a theming infrastructure/feature to Ghidra that would allow + users/developers to completely configure the colors, fonts, and icons used within Ghidra. There + are two main reasons for creating this feature. The first reason is to create the much + requested "Dark Theme". Many people find Ghidra's current color scheme to be hard on the eyes + and would greatly appreciate a color scheme that is not so bright.  The second reason is + for accessibility purposes. For example, the themeing feature would allow for the creating of a + high contrast color scheme, or a color scheme that helps mitigate color blindness or a theme + that uses larger fonts.

+   + +

Background

+ +

Ghidra previously used hundreds of hard coded colors, fonts, and icons.  They are + defined throughout the code in a somewhat haphazard fashion. Many features use colors to convey + similar concepts, but no effort was even made to use similar colors for those similar concepts. + Also, these colors were generally chosen to work with one of the common "light" java look and + feels. They often look terrible when used in conjunction with other LookAndFeels, especially + dark ones.

+ +

Ghidra does allow some customization of the current colors using "options", but this falls + short for several reasons. One problem is that not all colors or fonts are changeable via the + options. Another problem is that the options are tool based and you have to make the same + customization for each tool. A third problem is that options are unrelated to the LookAndFeel + option. In other words you can't have different option choices depending on the current + LookAndFeel.

+ +

Also, all of Ghidra's icons are hard coded and many are not suitable to use in a dark theme. + Overall, the hard coding of colors, fonts, and icons and the limitation of options makes + creating a good dark theme virtually impossible. So to address these issues, a new theming + infrastructure was created.

+ +

General Concepts and Approach

+ +

To achieve a theming capability in Ghidra, we had to implement the following concepts. + First, provide a level of indirection when using colors, fonts, or icons in code. Second, + introduce the concept of a theme which maps the indirect colors. font, and icons to actual + values in the context of a java LookAndFeel. Third, provide access to (and the ability to + change), the colors, fonts, and icons supplied by the Java LookAndFeel. And finally, provide + the GUIs needed to allow users to switch between, create, edit, save, import, and export + themes.

+ +
+

Indirection

+ +

The basic idea for indirection is to never directly use a hard coded color, font, or icon + when developing a feature in the application. Instead, these properties will be indirectly + referred to by an identifying string such as "color.bg.mywidget", where the string will + follow a known convention that helps indicate its use. Default values for these identifying + strings will be specified in data files that exist in the module where the code that defined + id is located. Also, the values associated with these ids can be either a concrete value such + as an actual color, font, or icon, or the value can be just an identifying string to + different property. This allows users to change individual values or entire groups of values + with one change.

+ +

Theme

+ +

A theme is simply the object that specifies all the values for colors, fonts, and icons + used in the application as well as the LookAndFeel. The idea is that there will be a set of + themes to choose from and by simply switching the theme, the LookAndFeel and all the colors, + fonts, and icons can be switched out at one time. The set of themes to choose from are a mix + of built-in themes and saved custom themes. There is one built-in theme for each supported + LookAndFeel, which will use the values from the LookAndFeel as well as all the default values + for the defined property ids. Users will be able to create custom themes where they can + basically change any defined color, font, or icon, including those supplied by the associated + LookAndFeel for that theme.

+ +

Look and Feel Values

+ +

The Java LookAndFeel is specified by the active theme. The Java LookAndFeel objects also + define colors, fonts, and icons indirectly using identifying strings such as "Button.font" + and "Menu.background". These values determine the default values used by all GUI elements + unless overridden by developers in code when they create the components. Uses have the + ability to change these values in the same way as values defined by Ghidra code. This will + allow users to generate themes that completely change the look of the GUI with out the + developers having to explicitly set a color, font and icon on every component as they get + created in code.  Another concept used by Java LookAndFeels is that many of the + individual components share the same colors and those shared colors are defined using a group + key such as "control", "text", or "menu". The idea is that by changing a group color, all + components that share that group color are changed together. Or an individual components + color can be changed by changing its specific key such as "Menu.background".

+ +

User Interaction

+ +

Users will be able create, edit, delete, import, export, and of course switch the + application's active theme. The GUI theme editor allows users to do all of these actions. + Using the active theme as a starting point, users will be able to change any color, font, or + icon defined either by the LookAndFeel or the application. One or more of these changes can + be saved as a new theme and stored in a file in their application directory. Themes can be + shared with other users by exporting and import themes.

+
+ +

Related Topics

+ +
+ + diff --git a/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/Theming.htm b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingUserDocs.html similarity index 73% rename from Ghidra/Framework/Docking/src/main/help/help/topics/Theming/Theming.htm rename to Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingUserDocs.html index 7046251bc1..3da437d6ae 100644 --- a/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/Theming.htm +++ b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingUserDocs.html @@ -5,14 +5,14 @@ - Theming + Theming User Documentation -

Theming

+

Theming User Help

-

Overview

+

Description

The Theming feature allows users to customize the colors, fonts, and icons used throughout the application. The active theme determines the Java LookAndFeel, whether the theme should use @@ -21,7 +21,7 @@ their home application directory

Users can also edit and create their own themes using the Theme Editor. Custom themes are - stored in the users <application dir>/themes. These are simple text files that can also + stored in the users <application dir>/themes. These are simple text files that can easily be modified using any text editor. Also, users can share themes by exporting them to a file that can be given to other users who can them import them into their own system.

@@ -171,52 +171,39 @@

Theme Property Names

Theme Property Names (also referred to as ids or keys) that are defined by Ghidra use a - common format to help make sorting and viewing properties more intuitive as to their use.

- -

The general format is:

+ common format to help make sorting and viewing properties more intuitive as to their use. See + the Developer Documentation for more details on the property id + format and naming conventions.

+

Theme Files

-
- [type].[category[...]].[client].[specialized uses] -
    -
  • type: color, font, or icon
  • +

    Theme Files are used to store saved custom themes. They are simple text files and are + stored in the user's home application directory. The first three properties are always the + theme name, the look and feel name, and whether the theme uses standard defaults or dark + defaults. Then there is just a list of overridden property "name = value" lines.So the format + is:

    + +
    +        name = [theme name]
    +        lookAndFeel = [lookAndFeel name]
    +        useDarkDefaults = [true or false]
    +        
    +        [theme id 1]= [color, icon, or font value]
    +        [theme id 2]= [color, icon, or font value]
    +        [theme id 3]= [color, icon, or font value]
    +        [theme id 4]= [color, icon, or font value]
    +        ...
    +	
    +
    -
  • category: any value, examples include "bg" (background), "fg" (foreground); - this may be multiple separated values
  • - -
  • client: the plugin name or feature name; any value used to represent a more - specialized use
  • - -
  • specialized uses: any key value here that applies to the client, such as - "vertex" for a vertex background
  • -
Examples: - -
    -
  • color.bg
  • - -
  • color.bg.listing
  • - -
  • font.button
  • - -
  • icon.refresh
  • - -
  • icon.refresh.disabled
  • -
-
-
- -

Theme File Format

- -
-

Saved theme files have the following format:

-
-     
-   
-        name = ThemeName
+     
+

Example:

+
+        name = BigFontTheme
         lookAndFeel = Nimbus
         useDarkDefaults = false
-        
+		
         color.bg = Black
         color.bg.foo = #012345
         [color]Panel.background = Red
@@ -224,13 +211,8 @@
         icon.refresh = images/reload3.png    
         color.bg.bar = color.bg.foo   
         color.bg.xxx = [color]Panel.background
-    
-   
-
+
-

The first three properties are always the theme name, the look and feel name, and whether - the theme uses standard defaults or dark defaults. Then there is just a list of overridden - property "name = value" lines.

Each property line is expected to begin with either "color.", "font.", or "icon." Since java defined properties don't start with these prefixes, they will have "[color]", "[font]", @@ -242,61 +224,17 @@ right side of the assignment is a property name and not a value, then it must also use the bracketed prefix if the property name doesn't start with "color.", "font.", or "icon."

-

Specifying Color Values

+

Specifying Theme Property Values

+

Specifying property values varies depending on whether it is a color, font, or icon. Fonts + and icons also support specifying modifiers. For a complete description of how to specify + these values, see the Developer Documentation. -

To specify the value for a color, there are 3 acceptable formats:

- - - -

Specifying Font Values

- -

Font values are specified as follows:

-
-        familyName-style-size
-   
-
- - - -

Examples: monospace-PLAIN-12 or courier-BOLD-15

- -

Specifying Icon Values

- -

Icon values are specified by a relative path to the icon file. There are two types of - icons; those that are included with Ghidra and those that were selected from the filesystem - and imported into the theme. Icons that have been imported into the theme are stored in an - images directory in the users Ghidra application directory. Icons included with Ghidra are - relative to an images data directory in some module. So for example,

-
-        icon.refresh = images/view-refresh.png
-        icon.push = [EXTERNAL]images/energy.png
-   
-
- -

The first example is a standard icon included with Ghidra. It exists in a module's data - directory in the images folder. The second example is for an icon that is not included with - Ghidra. The "[EXTERNAL]" prefix indicates that this icon is being stored in the user's - application directory in the images folder.

+

Related Topics

+
diff --git a/Ghidra/Framework/Docking/src/main/java/docking/framework/DockingApplicationLayout.java b/Ghidra/Framework/Docking/src/main/java/docking/framework/DockingApplicationLayout.java index 7cab83e2bd..ce42b87d9f 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/framework/DockingApplicationLayout.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/framework/DockingApplicationLayout.java @@ -72,11 +72,7 @@ public class DockingApplicationLayout extends ApplicationLayout { * properties. * * @param applicationRootDirs list of application root directories which should be - <<<<<<< Upstream, based on origin/master * used to identify modules and resources. The first entry will be treated as the - ======= - * used to identify modules and resources. The first entry will be treated as the - >>>>>>> 4485b75 GP-1981 - Support Tool - initial support tool fixes; updates to module discovery to use the classpath in dev mode for filtering * installation root. * @param applicationProperties The properties object that will be read system properties. * @throws FileNotFoundException if there was a problem getting a user directory. diff --git a/Ghidra/Framework/Docking/src/main/java/docking/help/HelpManager.java b/Ghidra/Framework/Docking/src/main/java/docking/help/HelpManager.java index 8816a1da01..350cefd820 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/help/HelpManager.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/help/HelpManager.java @@ -51,6 +51,12 @@ import utilities.util.reflection.ReflectionUtilities; */ public class HelpManager implements HelpService { + /** + * The hardcoded value to use for all HelpSet 'home id' values. Subclasses may change this + * value by overriding {@link #getHomeId()}. + */ + private static final String HOME_ID = "Misc_Help_Contents"; + public static final String SHOW_AID_KEY = "SHOW.HELP.NAVIGATION.AID"; private static final String TABLE_OF_CONTENTS_FILENAME_KEY = "data"; @@ -84,6 +90,7 @@ public class HelpManager implements HelpService { */ protected HelpManager(URL url) throws HelpSetException { mainHS = new DockingHelpSet(new GHelpClassLoader(null), url); + mainHS.setHomeID(getHomeId()); mainHB = mainHS.createHelpBroker(); mainHS.setTitle(GHIDRA_HELP_TITLE); @@ -121,6 +128,15 @@ public class HelpManager implements HelpService { } } + /** + * Returns the 'home id' to be used by all help sets in the system (as opposed to allowing each + * help set to define its own home id. + * @return the home id + */ + protected String getHomeId() { + return HOME_ID; + } + @Override public void excludeFromHelp(Object helpObject) { excludedFromHelp.add(helpObject); @@ -695,6 +711,7 @@ public class HelpManager implements HelpService { private HelpSet createHelpSet(URL url, GHelpClassLoader classLoader) throws HelpSetException { if (!urlToHelpSets.containsKey(url)) { GHelpSet hs = new GHelpSet(classLoader, url); + hs.setHomeID(getHomeId()); urlToHelpSets.put(url, hs); return hs; } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/util/image/ToolIconURL.java b/Ghidra/Framework/Docking/src/main/java/docking/util/image/ToolIconURL.java index 3231181e55..432acc2a53 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/util/image/ToolIconURL.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/util/image/ToolIconURL.java @@ -211,7 +211,7 @@ public class ToolIconURL implements Comparable { } private ImageIcon getImageIcon(String name) { - ImageIcon image = ResourceManager.loadImage(name); + ImageIcon image = ResourceManager.findIcon(name); if (image instanceof UnresolvedIcon) { return null; } diff --git a/Ghidra/Framework/Project/src/main/resources/images/check.png b/Ghidra/Framework/Docking/src/main/resources/images/check.png similarity index 100% rename from Ghidra/Framework/Project/src/main/resources/images/check.png rename to Ghidra/Framework/Docking/src/main/resources/images/check.png diff --git a/Ghidra/Framework/Docking/src/main/resources/images/dialog-cancel.png b/Ghidra/Framework/Docking/src/main/resources/images/dialog-cancel.png deleted file mode 100644 index 45f8949bfe..0000000000 Binary files a/Ghidra/Framework/Docking/src/main/resources/images/dialog-cancel.png and /dev/null differ diff --git a/Ghidra/Framework/Docking/src/main/resources/images/reload.png b/Ghidra/Framework/Docking/src/main/resources/images/reload.png deleted file mode 100644 index 1c026d32c3..0000000000 Binary files a/Ghidra/Framework/Docking/src/main/resources/images/reload.png and /dev/null differ diff --git a/Ghidra/Features/Base/src/main/resources/images/text_lowercase.png b/Ghidra/Framework/Docking/src/main/resources/images/text_lowercase.png similarity index 100% rename from Ghidra/Features/Base/src/main/resources/images/text_lowercase.png rename to Ghidra/Framework/Docking/src/main/resources/images/text_lowercase.png diff --git a/Ghidra/Framework/Docking/src/test/java/docking/widgets/fieldpanel/ColorRangeMapTest.java b/Ghidra/Framework/Docking/src/test/java/docking/widgets/fieldpanel/ColorRangeMapTest.java index 8281eaad15..21a9123f91 100644 --- a/Ghidra/Framework/Docking/src/test/java/docking/widgets/fieldpanel/ColorRangeMapTest.java +++ b/Ghidra/Framework/Docking/src/test/java/docking/widgets/fieldpanel/ColorRangeMapTest.java @@ -15,10 +15,6 @@ */ package docking.widgets.fieldpanel; -import static org.junit.Assert.*; - -import java.awt.Color; - import org.junit.Test; import docking.widgets.fieldpanel.internal.ColorRangeMap; @@ -60,8 +56,4 @@ public class ColorRangeMapTest extends AbstractGenericTest { assertColorsEqual(Palette.WHITE, map.getColor(100, Palette.WHITE)); } - private void assertColorsEqual(Color c1, Color c2) { - assertEquals(c1.getRGB(), c2.getRGB()); - } - } diff --git a/Ghidra/Framework/Generic/certification.manifest b/Ghidra/Framework/Generic/certification.manifest index a5abceb966..681485db8d 100644 --- a/Ghidra/Framework/Generic/certification.manifest +++ b/Ghidra/Framework/Generic/certification.manifest @@ -25,6 +25,8 @@ src/main/resources/generic.log4j.xml||GHIDRA||||END| src/main/resources/generic.log4jdev.xml||GHIDRA||||END| src/main/resources/generic.log4jfile.xml||GHIDRA||||END| src/main/resources/generic.log4jtest.xml||GHIDRA||||END| +src/main/resources/images/EmptyIcon.gif||GHIDRA||||END| +src/main/resources/images/EmptyIcon16.gif||GHIDRA||||END| src/main/resources/images/GhidraIcon128.png||GHIDRA||||END| src/main/resources/images/GhidraIcon16.png||GHIDRA||||END| src/main/resources/images/GhidraIcon24.png||GHIDRA||||END| @@ -36,34 +38,57 @@ src/main/resources/images/GhidraIcon64.png||GHIDRA||||END| src/main/resources/images/Plus2.png||GHIDRA||||END| src/main/resources/images/applications-multimedia16.png||Tango Icons - Public Domain|||tango|END| src/main/resources/images/checkmark_green.gif||GHIDRA||||END| +src/main/resources/images/closedSmallFolder.png||Modified Nuvola Icons - LGPL 2.1||||END| +src/main/resources/images/collapse_all.png||GHIDRA||||END| src/main/resources/images/core.png||Nuvola Icons - LGPL 2.1|||Nuvola icon set|END| src/main/resources/images/core24.png||Nuvola Icons - LGPL 2.1|||Nuvola icon set|END| src/main/resources/images/dialog-cancel.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| +src/main/resources/images/disk.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| +src/main/resources/images/disk_save_as.png||FAMFAMFAM Icons - CC 2.5||||END| +src/main/resources/images/down.png||GHIDRA||||END| src/main/resources/images/dragon16.gif||GHIDRA||||END| +src/main/resources/images/edit-cut.png||Tango Icons - Public Domain|||tango icon set|END| +src/main/resources/images/edit-cut22.png||Tango Icons - Public Domain|||tango icon set|END| src/main/resources/images/emblem-important.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| +src/main/resources/images/erase16.png||GHIDRA||||END| src/main/resources/images/error.png||Nuvola Icons - LGPL 2.1|||Nuvola icon set|END| src/main/resources/images/exec.png||Crystal Clear Icons - LGPL 2.1||||END| src/main/resources/images/expand_all.png||GHIDRA||||END| src/main/resources/images/face-monkey16.png||Tango Icons - Public Domain|||originally face-monkey from tango|END| src/main/resources/images/flag.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| +src/main/resources/images/go-home.png||Tango Icons - Public Domain|||tango icon set|END| src/main/resources/images/greenDragon16.png||GHIDRA||||END| src/main/resources/images/greenDragon24.png||GHIDRA||||END| src/main/resources/images/help-browser.png||Tango Icons - Public Domain|||tango icon set|END| +src/main/resources/images/information.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/internet-web-browser16.png||Tango Icons - Public Domain|||originally internet-web-browser.png from tango|END| src/main/resources/images/kgpg.png||Nuvola Icons - LGPL 2.1|||Nuvola icon set|END| +src/main/resources/images/left.alternate.png||GHIDRA||||END| +src/main/resources/images/left.png||GHIDRA||||END| +src/main/resources/images/locationIn.gif||GHIDRA||||END| +src/main/resources/images/locationOut.gif||GHIDRA||||END| src/main/resources/images/mergemgr16.gif||GHIDRA||||END| src/main/resources/images/network-receive16.png||Tango Icons - Public Domain|||originally network-receive.png from tango|END| src/main/resources/images/openFolder.png||Modified Nuvola Icons - LGPL 2.1||||END| src/main/resources/images/openSmallFolder.png||Modified Nuvola Icons - LGPL 2.1||||END| +src/main/resources/images/page_paste.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| +src/main/resources/images/page_white_copy.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/process-stop.png||Tango Icons - Public Domain|||Theirs: Oxygen icon theme (dual license; LGPL or CC-SA-3.0)tango icon set|END| src/main/resources/images/program_obj.png||GHIDRA|||Custom Icon|END| src/main/resources/images/redDragon16.png||GHIDRA|||Renamed GIF version of redDragon16.png|END| src/main/resources/images/redDragon24.png||GHIDRA||||END| src/main/resources/images/redDragon32.png||GHIDRA||||END| src/main/resources/images/reload3.png||Crystal Clear Icons - LGPL 2.1||||END| +src/main/resources/images/right.alternate.png||GHIDRA||||END| +src/main/resources/images/right.png||GHIDRA||||END| src/main/resources/images/software-update-urgent.png||Tango Icons - Public Domain|||tango icon set|END| +src/main/resources/images/sortascending.png||GHIDRA||||END| +src/main/resources/images/sortdescending.png||GHIDRA||||END| src/main/resources/images/text_align_justify.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| +src/main/resources/images/up.png||GHIDRA||||END| src/main/resources/images/video-x-generic16.png||Tango Icons - Public Domain|||tango|END| +src/main/resources/images/viewmagfit.png||Nuvola Icons - LGPL 2.1|||Nuvola icon set|END| +src/main/resources/images/warning.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/log4j-appender-console-with-links.xml||GHIDRA||||END| src/main/resources/log4j-appender-console.xml||GHIDRA||||END| src/main/resources/log4j-appender-logpanel.xml||GHIDRA||||END| diff --git a/Ghidra/Framework/Generic/data/generic.theme.properties b/Ghidra/Framework/Generic/data/generic.theme.properties index 777515097b..d1c9d63cfc 100644 --- a/Ghidra/Framework/Generic/data/generic.theme.properties +++ b/Ghidra/Framework/Generic/data/generic.theme.properties @@ -7,5 +7,65 @@ font.italics = font.standard[italic] font.bold.italic = font.standard[bold][italic] font.monospaced = monospaced-PLAIN-12 +// Icons files + +icon.flag = flag.png +icon.lock = kgpg.png +icon.checkmark.green = checkmark_green.gif + +icon.empty = EmptyIcon16.gif +icon.empty.20 = EmptyIcon.gif + +icon.help = help-browser.png + +icon.add = Plus2.png +icon.copy = page_white_copy.png +icon.cut = edit-cut.png +icon.paste = page_paste.png + +icon.collapse.all = collapse_all.png +icon.expand.all = expand_all.png + +icon.configure.filter = exec.png +icon.clear = erase16.png +icon.delete = icon.error +icon.error = emblem-important.png + +icon.home = go-home.png +icon.navigate.in = locationIn.gif +icon.navigate.out = locationOut.gif + +icon.not.allowed = dialog-cancel.png +icon.folder.open = openSmallFolder.png +icon.folder.closed = closedSmallFolder.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.warning = warning.png +icon.information = information.png + +icon.left = left.png +icon.right = right.png +icon.up = up.png +icon.down = down.png + +icon.left.alt = left.alternate.png +icon.right.alt = right.alternate.png + +icon.save = disk.png +icon.save.as = disk_save_as.png + +icon.make.selection = text_align_justify.png + +icon.arrow.down.right = viewmagfit.png[rotate(90)] +icon.arrow.up.left = viewmagfit.png[rotate(275)] +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)]} + + [Dark Defaults] \ No newline at end of file diff --git a/Ghidra/Framework/Generic/src/main/java/generic/test/AbstractGenericTest.java b/Ghidra/Framework/Generic/src/main/java/generic/test/AbstractGenericTest.java index 584b03d0b6..5d052c3e20 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/test/AbstractGenericTest.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/test/AbstractGenericTest.java @@ -45,6 +45,7 @@ import org.junit.runner.Description; import generic.jar.ResourceFile; import generic.test.rule.Repeated; import generic.test.rule.RepeatedTestRule; +import generic.theme.GIcon; import generic.theme.Gui; import generic.util.WindowUtilities; import ghidra.GhidraTestApplicationLayout; @@ -56,6 +57,7 @@ import ghidra.util.exception.AssertException; import ghidra.util.task.AbstractSwingUpdateManager; import ghidra.util.task.SwingUpdateManager; import junit.framework.AssertionFailedError; +import resources.icons.UrlImageIcon; import sun.awt.AppContext; import utilities.util.FileUtilities; import utilities.util.reflection.ReflectionUtilities; @@ -2050,4 +2052,51 @@ public abstract class AbstractGenericTest extends AbstractGTest { } } + /** + * Asserts that the two colors have the same rgb values (handles GColor) + * @param expected the expected color + * @param actual the actual color + */ + public void assertColorsEqual(Color expected, Color actual) { + if (expected.getRGB() == actual.getRGB()) { + return; + } + fail("Expected: [" + expected.getClass().getSimpleName() + "]" + expected + + ", but got: [" + actual.getClass().getSimpleName() + "]" + actual); + } + + /** + * Asserts that the two icons are or refer to the same icon (handles GIcon) + * @param expected the expected icon + * @param actual the actual icon + */ + public void assertIconsEqual(Icon expected, Icon actual) { + if (expected.equals(actual)) { + return; + } + URL url1 = getURL(expected); + URL url2 = getURL(actual); + + if (url1 != null && url1.equals(url2)) { + return; + } + fail("Expected icon [" + expected.getClass().getSimpleName() + "]" + expected.toString() + + ", but got: [" + actual.getClass().getSimpleName() + "]" + actual.toString()); + } + + /** + * Gets the URL for the given icon + * @param icon the icon to get a URL for + * @return the URL for the given icon + */ + public URL getURL(Icon icon) { + if (icon instanceof UrlImageIcon urlIcon) { + return urlIcon.getUrl(); + } + if (icon instanceof GIcon gIcon) { + return gIcon.getUrl(); + } + return null; + } + } diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/ColorValue.java b/Ghidra/Framework/Generic/src/main/java/generic/theme/ColorValue.java index 7b869230d2..ec17688515 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/theme/ColorValue.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/theme/ColorValue.java @@ -32,7 +32,7 @@ public class ColorValue extends ThemeValue { private static final String EXTERNAL_PREFIX = "[color]"; private static final String SYSTEM_COLOR_PREFIX = "system.color"; - public static final Color LAST_RESORT_DEFAULT = Color.GRAY; + public static final Color LAST_RESORT_DEFAULT = new Color(128, 128, 128); /** * Constructor used when the ColorValue will have a direct {@link Color} value. The refId will @@ -93,7 +93,7 @@ public class ColorValue extends ThemeValue { } @Override - protected Color getUnresolvedReferenceValue(String unresolvedId) { + protected Color getUnresolvedReferenceValue(String id, String unresolvedId) { Throwable t = ReflectionUtilities.createThrowableWithStackOlderThan(); StackTraceElement[] trace = t.getStackTrace(); @@ -103,9 +103,8 @@ public class ColorValue extends ThemeValue { t.setStackTrace(filtered); Msg.error(this, - "Could not resolve indirect color for \"" + unresolvedId + - "\", using last resort default!", - t); + "Could not resolve indirect color path for \"" + unresolvedId + + "\" for primary id \"" + id + "\", using last resort default"); return LAST_RESORT_DEFAULT; } 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 65154ab3b9..c5ef68db4c 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/theme/FontValue.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/theme/FontValue.java @@ -143,9 +143,10 @@ public class FontValue extends ThemeValue { } @Override - protected Font getUnresolvedReferenceValue(String unresolvedId) { - Msg.warn(this, "Could not resolve indirect font for " + unresolvedId + - ", using last resort default"); + protected Font getUnresolvedReferenceValue(String id, String unresolvedId) { + Msg.warn(this, + "Could not resolve indirect font path for \"" + unresolvedId + + "\" for primary id \"" + id + "\", using last resort default"); return LAST_RESORT_DEFAULT; } diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/GColor.java b/Ghidra/Framework/Generic/src/main/java/generic/theme/GColor.java index 08b3afb604..7aa2176b7f 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/theme/GColor.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/theme/GColor.java @@ -127,6 +127,10 @@ public class GColor extends Color { return delegate.darker(); } + public boolean isUnresolved() { + return delegate == ColorValue.LAST_RESORT_DEFAULT; + } + @Override public String toString() { return toHexString(); diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/Gui.java b/Ghidra/Framework/Generic/src/main/java/generic/theme/Gui.java index a315ef204e..9bf7dc04da 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/theme/Gui.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/theme/Gui.java @@ -321,7 +321,11 @@ public class Gui { * @return the current {@link Font} associated with the given id. */ public static Font getFont(String id) { - return getFont(id, true); + Font font = getFont(id, true); + if (font == FontValue.LAST_RESORT_DEFAULT) { + return null; + } + return font; } /** @@ -390,6 +394,15 @@ public class Gui { * @param color the new color for the id */ public static void setColor(String id, Color color) { + if (color == null) { + + } + if (color instanceof GColor gColor) { + if (id.equals(gColor.getId())) { + Msg.warn(Gui.class, "Attempted to set a color to a reference to itself!"); + return; // this would create a circular reference to itself, don't do it + } + } setColor(new ColorValue(id, color)); } @@ -407,7 +420,9 @@ public class Gui { notifyThemeChanged(new ColorChangedThemeEvent(currentValues, newValue)); // now update the ui - lookAndFeelManager.colorsChanged(); + if (lookAndFeelManager != null) { + lookAndFeelManager.colorsChanged(); + } } /** 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 da9fdfa7e5..0af14893a0 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/theme/IconValue.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/theme/IconValue.java @@ -180,7 +180,7 @@ public class IconValue extends ThemeValue { } private static int getModifierIndex(String value) { - int baseModifierIndex = value.indexOf("[", 1); // start past first char as it coud be valid "[EXTERNAL]" prefix + int baseModifierIndex = value.indexOf("[", 1); // start past first char as it could be valid "[EXTERNAL]" prefix int overlayModifierIndex = value.indexOf("{"); if (baseModifierIndex < 0) { return overlayModifierIndex; @@ -197,10 +197,10 @@ public class IconValue extends ThemeValue { } @Override - protected Icon getUnresolvedReferenceValue(String unresolvedId) { + protected Icon getUnresolvedReferenceValue(String id, String unresolvedId) { Msg.warn(this, "Could not resolve indirect icon path for \"" + unresolvedId + - "\", using last resort default"); + "\" for primary id \"" + id + "\", using last resort default"); return LAST_RESORT_DEFAULT; } diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeValue.java b/Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeValue.java index 85dd49b9b3..3a21bfbb9e 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeValue.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeValue.java @@ -33,6 +33,9 @@ public abstract class ThemeValue implements Comparable> { protected final String referenceId; protected ThemeValue(String id, String referenceId, T value) { + if (id.equals(referenceId)) { + throw new IllegalArgumentException("Can't create a themeValue that referencs itself"); + } this.id = id; this.referenceId = referenceId; this.value = value; @@ -92,11 +95,11 @@ public abstract class ThemeValue implements Comparable> { visitedKeys.add(parent.id); if (visitedKeys.contains(parent.referenceId)) { Msg.warn(this, "Theme value reference loop detected for key: " + id); - return getUnresolvedReferenceValue(id); + return getUnresolvedReferenceValue(id, parent.referenceId); } parent = getReferredValue(values, parent.referenceId); } - return getUnresolvedReferenceValue(id); + return getUnresolvedReferenceValue(id, referenceId); } /** @@ -151,10 +154,11 @@ public abstract class ThemeValue implements Comparable> { /** * Returns the T to be used if the indirect reference couldn't be resolved. - * @param unresolvedId the id that couldn't be resolved + * @param id the id we are trying to get a value foe + * @param unresolvedId the reference id that couldn't be resolved * @return the default value to be used if the indirect reference couldn't be resolved. */ - protected abstract T getUnresolvedReferenceValue(String unresolvedId); + protected abstract T getUnresolvedReferenceValue(String id, String unresolvedId); /** * Returns the ThemeValue referred to by this ThemeValue. Needs to be overridden by diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/AbstractOptions.java b/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/AbstractOptions.java index 65544fccd1..7ffd84aeba 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/AbstractOptions.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/AbstractOptions.java @@ -141,7 +141,7 @@ public abstract class AbstractOptions implements Options { if (type == OptionType.COLOR_TYPE) { if (defaultValue instanceof GColor gColor) { - registerThemeColor(optionName, gColor.getId(), help, description); + registerThemeColor(optionName, gColor.getId(), help, description, editor); return; } warnNonThemeValue("Registering non theme color: " + optionName); @@ -197,14 +197,14 @@ public abstract class AbstractOptions implements Options { } private void registerThemeColor(String optionName, String colorId, HelpLocation help, - String description) { + String description, PropertyEditor editor) { Option currentOption = getExistingComptibleOption(optionName, OptionType.COLOR_TYPE); if (currentOption != null && currentOption instanceof ThemeColorOption) { - currentOption.updateRegistration(description, help, null, null); + currentOption.updateRegistration(description, help, null, editor); return; } description += " (Theme Color: " + colorId + ")"; - Option option = new ThemeColorOption(optionName, colorId, description, help); + Option option = new ThemeColorOption(optionName, colorId, description, help, editor); valueMap.put(optionName, option); } diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/EditorState.java b/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/EditorState.java index 644da95148..1c79064c95 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/EditorState.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/EditorState.java @@ -186,4 +186,9 @@ public class EditorState implements PropertyChangeListener { return options.getDescription(name); } + @Override + public String toString() { + return "EditorState: " + name + "= " + currentValue; + } + } diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/ThemeColorOption.java b/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/ThemeColorOption.java index 40af93f4f5..22cb07fb48 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/ThemeColorOption.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/ThemeColorOption.java @@ -16,7 +16,9 @@ package ghidra.framework.options; import java.awt.Color; +import java.beans.PropertyEditor; +import generic.theme.GColor; import generic.theme.Gui; import ghidra.util.HelpLocation; @@ -30,14 +32,23 @@ public class ThemeColorOption extends Option { private String colorId; public ThemeColorOption(String optionName, String colorId, String description, - HelpLocation help) { - super(optionName, OptionType.COLOR_TYPE, description, help, null, true, null); + HelpLocation help, PropertyEditor editor) { + super(optionName, OptionType.COLOR_TYPE, description, help, null, true, editor); this.colorId = colorId; } @Override public Color getCurrentValue() { - return Gui.getColor(colorId); + GColor gColor = new GColor(colorId); + if (gColor.isUnresolved()) { + return null; + } + return gColor; + } + + @Override + public Object getDefaultValue() { + return getCurrentValue(); } @Override diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/ThemeFontOption.java b/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/ThemeFontOption.java index 5174dd862e..5a0aa9ef04 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/ThemeFontOption.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/ThemeFontOption.java @@ -40,6 +40,11 @@ public class ThemeFontOption extends Option { return Gui.getFont(fontId); } + @Override + public Object getDefaultValue() { + return getCurrentValue(); + } + @Override public void doSetCurrentValue(Object value) { Gui.setFont(fontId, (Font) value); diff --git a/Ghidra/Framework/Docking/src/main/resources/images/EmptyIcon.gif b/Ghidra/Framework/Generic/src/main/resources/images/EmptyIcon.gif similarity index 100% rename from Ghidra/Framework/Docking/src/main/resources/images/EmptyIcon.gif rename to Ghidra/Framework/Generic/src/main/resources/images/EmptyIcon.gif diff --git a/Ghidra/Framework/Docking/src/main/resources/images/EmptyIcon16.gif b/Ghidra/Framework/Generic/src/main/resources/images/EmptyIcon16.gif similarity index 100% rename from Ghidra/Framework/Docking/src/main/resources/images/EmptyIcon16.gif rename to Ghidra/Framework/Generic/src/main/resources/images/EmptyIcon16.gif diff --git a/Ghidra/Framework/Project/src/main/resources/images/closedSmallFolder.png b/Ghidra/Framework/Generic/src/main/resources/images/closedSmallFolder.png similarity index 100% rename from Ghidra/Framework/Project/src/main/resources/images/closedSmallFolder.png rename to Ghidra/Framework/Generic/src/main/resources/images/closedSmallFolder.png diff --git a/Ghidra/Framework/Docking/src/main/resources/images/collapse_all.png b/Ghidra/Framework/Generic/src/main/resources/images/collapse_all.png similarity index 100% rename from Ghidra/Framework/Docking/src/main/resources/images/collapse_all.png rename to Ghidra/Framework/Generic/src/main/resources/images/collapse_all.png diff --git a/Ghidra/Framework/Docking/src/main/resources/images/disk.png b/Ghidra/Framework/Generic/src/main/resources/images/disk.png similarity index 100% rename from Ghidra/Framework/Docking/src/main/resources/images/disk.png rename to Ghidra/Framework/Generic/src/main/resources/images/disk.png diff --git a/Ghidra/Framework/Project/src/main/resources/images/disk_save_as.png b/Ghidra/Framework/Generic/src/main/resources/images/disk_save_as.png similarity index 100% rename from Ghidra/Framework/Project/src/main/resources/images/disk_save_as.png rename to Ghidra/Framework/Generic/src/main/resources/images/disk_save_as.png diff --git a/Ghidra/Framework/Docking/src/main/resources/images/down.png b/Ghidra/Framework/Generic/src/main/resources/images/down.png similarity index 100% rename from Ghidra/Framework/Docking/src/main/resources/images/down.png rename to Ghidra/Framework/Generic/src/main/resources/images/down.png diff --git a/Ghidra/Framework/Docking/src/main/resources/images/edit-cut.png b/Ghidra/Framework/Generic/src/main/resources/images/edit-cut.png similarity index 100% rename from Ghidra/Framework/Docking/src/main/resources/images/edit-cut.png rename to Ghidra/Framework/Generic/src/main/resources/images/edit-cut.png diff --git a/Ghidra/Framework/Docking/src/main/resources/images/edit-cut22.png b/Ghidra/Framework/Generic/src/main/resources/images/edit-cut22.png similarity index 100% rename from Ghidra/Framework/Docking/src/main/resources/images/edit-cut22.png rename to Ghidra/Framework/Generic/src/main/resources/images/edit-cut22.png diff --git a/Ghidra/Features/Base/src/main/resources/images/erase16.png b/Ghidra/Framework/Generic/src/main/resources/images/erase16.png similarity index 100% rename from Ghidra/Features/Base/src/main/resources/images/erase16.png rename to Ghidra/Framework/Generic/src/main/resources/images/erase16.png diff --git a/Ghidra/Framework/Docking/src/main/resources/images/go-home.png b/Ghidra/Framework/Generic/src/main/resources/images/go-home.png similarity index 100% rename from Ghidra/Framework/Docking/src/main/resources/images/go-home.png rename to Ghidra/Framework/Generic/src/main/resources/images/go-home.png diff --git a/Ghidra/Framework/Docking/src/main/resources/images/information.png b/Ghidra/Framework/Generic/src/main/resources/images/information.png similarity index 100% rename from Ghidra/Framework/Docking/src/main/resources/images/information.png rename to Ghidra/Framework/Generic/src/main/resources/images/information.png diff --git a/Ghidra/Framework/Docking/src/main/resources/images/left.alternate.png b/Ghidra/Framework/Generic/src/main/resources/images/left.alternate.png similarity index 100% rename from Ghidra/Framework/Docking/src/main/resources/images/left.alternate.png rename to Ghidra/Framework/Generic/src/main/resources/images/left.alternate.png diff --git a/Ghidra/Framework/Docking/src/main/resources/images/left.png b/Ghidra/Framework/Generic/src/main/resources/images/left.png similarity index 100% rename from Ghidra/Framework/Docking/src/main/resources/images/left.png rename to Ghidra/Framework/Generic/src/main/resources/images/left.png diff --git a/Ghidra/Framework/Docking/src/main/resources/images/locationIn.gif b/Ghidra/Framework/Generic/src/main/resources/images/locationIn.gif similarity index 100% rename from Ghidra/Framework/Docking/src/main/resources/images/locationIn.gif rename to Ghidra/Framework/Generic/src/main/resources/images/locationIn.gif diff --git a/Ghidra/Framework/Docking/src/main/resources/images/locationOut.gif b/Ghidra/Framework/Generic/src/main/resources/images/locationOut.gif similarity index 100% rename from Ghidra/Framework/Docking/src/main/resources/images/locationOut.gif rename to Ghidra/Framework/Generic/src/main/resources/images/locationOut.gif diff --git a/Ghidra/Framework/Project/src/main/resources/images/page_paste.png b/Ghidra/Framework/Generic/src/main/resources/images/page_paste.png similarity index 100% rename from Ghidra/Framework/Project/src/main/resources/images/page_paste.png rename to Ghidra/Framework/Generic/src/main/resources/images/page_paste.png diff --git a/Ghidra/Features/Base/src/main/resources/images/page_white_copy.png b/Ghidra/Framework/Generic/src/main/resources/images/page_white_copy.png similarity index 100% rename from Ghidra/Features/Base/src/main/resources/images/page_white_copy.png rename to Ghidra/Framework/Generic/src/main/resources/images/page_white_copy.png diff --git a/Ghidra/Framework/Docking/src/main/resources/images/right.alternate.png b/Ghidra/Framework/Generic/src/main/resources/images/right.alternate.png similarity index 100% rename from Ghidra/Framework/Docking/src/main/resources/images/right.alternate.png rename to Ghidra/Framework/Generic/src/main/resources/images/right.alternate.png diff --git a/Ghidra/Framework/Docking/src/main/resources/images/right.png b/Ghidra/Framework/Generic/src/main/resources/images/right.png similarity index 100% rename from Ghidra/Framework/Docking/src/main/resources/images/right.png rename to Ghidra/Framework/Generic/src/main/resources/images/right.png diff --git a/Ghidra/Framework/Docking/src/main/resources/images/sortascending.png b/Ghidra/Framework/Generic/src/main/resources/images/sortascending.png similarity index 100% rename from Ghidra/Framework/Docking/src/main/resources/images/sortascending.png rename to Ghidra/Framework/Generic/src/main/resources/images/sortascending.png diff --git a/Ghidra/Framework/Docking/src/main/resources/images/sortdescending.png b/Ghidra/Framework/Generic/src/main/resources/images/sortdescending.png similarity index 100% rename from Ghidra/Framework/Docking/src/main/resources/images/sortdescending.png rename to Ghidra/Framework/Generic/src/main/resources/images/sortdescending.png diff --git a/Ghidra/Framework/Docking/src/main/resources/images/up.png b/Ghidra/Framework/Generic/src/main/resources/images/up.png similarity index 100% rename from Ghidra/Framework/Docking/src/main/resources/images/up.png rename to Ghidra/Framework/Generic/src/main/resources/images/up.png diff --git a/Ghidra/Framework/Docking/src/main/resources/images/viewmagfit.png b/Ghidra/Framework/Generic/src/main/resources/images/viewmagfit.png similarity index 100% rename from Ghidra/Framework/Docking/src/main/resources/images/viewmagfit.png rename to Ghidra/Framework/Generic/src/main/resources/images/viewmagfit.png diff --git a/Ghidra/Framework/Docking/src/main/resources/images/warning.png b/Ghidra/Framework/Generic/src/main/resources/images/warning.png similarity index 100% rename from Ghidra/Framework/Docking/src/main/resources/images/warning.png rename to Ghidra/Framework/Generic/src/main/resources/images/warning.png diff --git a/Ghidra/Framework/Generic/src/test/java/generic/constraint/DecisionTreeTest.java b/Ghidra/Framework/Generic/src/test/java/generic/constraint/DecisionTreeTest.java index 7f0bc0aa3d..1e1141558d 100644 --- a/Ghidra/Framework/Generic/src/test/java/generic/constraint/DecisionTreeTest.java +++ b/Ghidra/Framework/Generic/src/test/java/generic/constraint/DecisionTreeTest.java @@ -28,7 +28,6 @@ import org.junit.Test; import generic.constraint.DecisionNode.PropertyValue; import generic.test.AbstractGenericTest; -import generic.theme.GThemeDefaults.Colors.Palette; public class DecisionTreeTest extends AbstractGenericTest { @@ -134,7 +133,7 @@ public class DecisionTreeTest extends AbstractGenericTest { @Test public void testMatchFromFirstXML() { - Color c = Palette.WHITE; + Color c = Color.WHITE; DecisionSet decisionSet = decisionTree.getDecisionsSet(c, "NAME"); List decisions = decisionSet.getDecisions(); assertEquals(1, decisions.size()); @@ -147,7 +146,7 @@ public class DecisionTreeTest extends AbstractGenericTest { @Test public void testMatchFromAdditionalXML() { - Color c = Palette.MAGENTA; + Color c = new Color(255, 0, 255); DecisionSet decisionSet = decisionTree.getDecisionsSet(c, "NAME"); List decisions = decisionSet.getDecisions(); assertEquals(1, decisions.size()); @@ -160,7 +159,7 @@ public class DecisionTreeTest extends AbstractGenericTest { @Test public void testMatchMultiple() { - Color c = Palette.YELLOW; + Color c = Color.YELLOW; DecisionSet decisionSet = decisionTree.getDecisionsSet(c, "NAME"); List decisions = decisionSet.getDecisions(); assertEquals(2, decisions.size()); @@ -179,7 +178,7 @@ public class DecisionTreeTest extends AbstractGenericTest { @Test public void testNoMatchUsingDefault() { - Color c = Palette.GRAY; + Color c = Color.GRAY; DecisionSet decisionSet = decisionTree.getDecisionsSet(c, "NAME"); List decisions = decisionSet.getDecisions(); assertEquals(1, decisions.size()); diff --git a/Ghidra/Framework/Generic/src/test/java/generic/theme/GuiTest.java b/Ghidra/Framework/Generic/src/test/java/generic/theme/GuiTest.java index 5a7ec20ae4..c65c8106b1 100644 --- a/Ghidra/Framework/Generic/src/test/java/generic/theme/GuiTest.java +++ b/Ghidra/Framework/Generic/src/test/java/generic/theme/GuiTest.java @@ -69,6 +69,7 @@ public class GuiTest { Gui.setThemePreferenceManager(new ThemePreferenceManager() { + @Override public GTheme getTheme() { return new MetalTheme(); } @@ -337,7 +338,7 @@ public class GuiTest { @Test public void testGetApplicationDarkDefaults() { - // dark defaults are a combination of standard defalts overlayed with dark defaults + // dark defaults are a combination of standard defaults overlayed with dark defaults GThemeValueMap expected = new GThemeValueMap(); expected.load(defaultValues); expected.load(darkDefaultValues); diff --git a/Ghidra/Framework/Generic/src/test/java/ghidra/util/HTMLUtilitiesTest.java b/Ghidra/Framework/Generic/src/test/java/ghidra/util/HTMLUtilitiesTest.java index 2c100e37ed..d45c9d2e25 100644 --- a/Ghidra/Framework/Generic/src/test/java/ghidra/util/HTMLUtilitiesTest.java +++ b/Ghidra/Framework/Generic/src/test/java/ghidra/util/HTMLUtilitiesTest.java @@ -21,8 +21,6 @@ import static org.junit.Assert.*; import org.junit.Before; import org.junit.Test; -import generic.theme.GThemeDefaults.Colors.Palette; - public class HTMLUtilitiesTest { private SpyErrorLogger spyLogger = new SpyErrorLogger(); @@ -128,13 +126,13 @@ public class HTMLUtilitiesTest { @Test public void testToRGBString() { - String rgb = HTMLUtilities.toRGBString(Palette.RED); + String rgb = HTMLUtilities.toRGBString(WebColors.RED); assertEquals("255000000", rgb); } @Test public void testToHexString() { - String rgb = HTMLUtilities.toHexString(Palette.RED); + String rgb = HTMLUtilities.toHexString(WebColors.RED); assertEquals("#FF0000", rgb); } diff --git a/Ghidra/Framework/Graph/src/test/java/ghidra/graph/GraphAlgorithmsVisualDebugger.java b/Ghidra/Framework/Graph/src/test/java/ghidra/graph/GraphAlgorithmsVisualDebugger.java index ba9796834f..fda5028e57 100644 --- a/Ghidra/Framework/Graph/src/test/java/ghidra/graph/GraphAlgorithmsVisualDebugger.java +++ b/Ghidra/Framework/Graph/src/test/java/ghidra/graph/GraphAlgorithmsVisualDebugger.java @@ -15,7 +15,7 @@ */ package ghidra.graph; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.*; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; @@ -25,6 +25,8 @@ import javax.swing.JFrame; import org.junit.Test; +import docking.framework.DockingApplicationConfiguration; +import ghidra.framework.ApplicationConfiguration; import ghidra.graph.algo.*; import ghidra.graph.algo.viewer.*; import ghidra.util.SystemUtilities; @@ -37,6 +39,13 @@ import ghidra.util.exception.CancelledException; */ public class GraphAlgorithmsVisualDebugger extends AbstractGraphAlgorithmsTest { + @Override + protected ApplicationConfiguration createApplicationConfiguration() { + DockingApplicationConfiguration config = new DockingApplicationConfiguration(); + config.setShowSplashScreen(false); + return config; + } + @Override protected GDirectedGraph createGraph() { return GraphFactory.createDirectedGraph(); diff --git a/Ghidra/Framework/Graph/src/test/java/ghidra/service/graph/GraphDisplayOptionsTest.java b/Ghidra/Framework/Graph/src/test/java/ghidra/service/graph/GraphDisplayOptionsTest.java index 193033bc38..bee4f05b9f 100644 --- a/Ghidra/Framework/Graph/src/test/java/ghidra/service/graph/GraphDisplayOptionsTest.java +++ b/Ghidra/Framework/Graph/src/test/java/ghidra/service/graph/GraphDisplayOptionsTest.java @@ -17,6 +17,7 @@ package ghidra.service.graph; import static org.junit.Assert.*; +import java.awt.Font; import java.util.Arrays; import java.util.List; @@ -24,22 +25,47 @@ import org.junit.Before; import org.junit.Test; import docking.FakeDockingTool; +import docking.test.AbstractDockingTest; import generic.theme.GThemeDefaults.Colors.Palette; +import generic.theme.Gui; import ghidra.framework.options.Options; import ghidra.framework.options.ToolOptions; import ghidra.util.HelpLocation; -public class GraphDisplayOptionsTest { +public class GraphDisplayOptionsTest extends AbstractDockingTest { private GraphType graphType; private GraphDisplayOptions options; @Before public void setUp() { + Gui.setColor("color.V1", Palette.BLACK); + Gui.setColor("color.V2", Palette.BLACK); + Gui.setColor("color.V3", Palette.BLACK); + Gui.setColor("color.E1", Palette.BLACK); + Gui.setColor("color.E2", Palette.BLACK); + Gui.setColor("color.E3", Palette.BLACK); + Gui.setColor("color.edge.default", Palette.BLACK); + Gui.setColor("color.vertex.default", Palette.BLACK); + Gui.setColor("color.edge.selected", Palette.BLACK); + Gui.setColor("color.vertex.selected", Palette.BLACK); + Gui.setFont("font.graph", new Font("monospaced", Font.PLAIN, 12)); List vertexTypes = Arrays.asList("V1", "V2", "V3"); List edgeTypes = Arrays.asList("E1", "E2", "E3"); graphType = new GraphType("Test", "Test Description", vertexTypes, edgeTypes); options = new GraphDisplayOptions(graphType); + options.setVertexColor("V1", "color.V1"); + options.setVertexColor("V2", "color.V2"); + options.setVertexColor("V3", "color.V3"); + options.setEdgeColor("E1", "color.E1"); + options.setEdgeColor("E2", "color.E2"); + options.setEdgeColor("E3", "color.E3"); + options.setDefaultEdgeColor("color.edge.default"); + options.setDefaultVertexColor("color.vertex.default"); + options.setEdgeSelectionColor("color.edge.selected"); + options.setVertexSelectionColor("color.vertex.selected"); + options.setFont("font.graph"); + } @Test @@ -204,9 +230,10 @@ public class GraphDisplayOptionsTest { @Test public void testGetVertexColorForType() { - assertEquals(options.getDefaultVertexColor(), options.getVertexColor("V1")); + assertEquals(options.getDefaultVertexColor().getRGB(), + options.getVertexColor("V1").getRGB()); options.setVertexColor("V1", Palette.RED); - assertEquals(Palette.RED, options.getVertexColor("V1")); + assertEquals(Palette.RED.getRGB(), options.getVertexColor("V1").getRGB()); } @Test @@ -235,8 +262,8 @@ public class GraphDisplayOptionsTest { Options vertexColorOptions = graphDisplayOptions.getOptions("Vertex Colors"); List leafOptionNames = vertexColorOptions.getLeafOptionNames(); assertEquals(Arrays.asList("V1", "V2", "V3"), leafOptionNames); - assertEquals(options.getDefaultVertexColor(), - vertexColorOptions.getColor("V1", Palette.WHITE)); + assertEquals(options.getDefaultVertexColor().getRGB(), + vertexColorOptions.getColor("V1", Palette.BLACK).getRGB()); Options vertexShapeOptions = graphDisplayOptions.getOptions("Vertex Shapes"); leafOptionNames = vertexShapeOptions.getLeafOptionNames(); @@ -247,8 +274,8 @@ public class GraphDisplayOptionsTest { Options edgeColorOptions = graphDisplayOptions.getOptions("Edge Colors"); leafOptionNames = edgeColorOptions.getLeafOptionNames(); assertEquals(Arrays.asList("E1", "E2", "E3"), leafOptionNames); - assertEquals(options.getDefaultEdgeColor(), - edgeColorOptions.getColor("E1", Palette.WHITE)); + assertEquals(options.getDefaultEdgeColor().getRGB(), + edgeColorOptions.getColor("E1", Palette.WHITE).getRGB()); Options miscellaneousOptions = graphDisplayOptions.getOptions("Miscellaneous"); leafOptionNames = miscellaneousOptions.getLeafOptionNames(); @@ -268,13 +295,13 @@ public class GraphDisplayOptionsTest { AttributedVertex vertex = new AttributedVertex("Foo"); vertex.setVertexType("V1"); - assertEquals(Palette.BLUE.getRGB(), options.getVertexColor(vertex).getRGB()); + assertEquals(Palette.BLACK.getRGB(), options.getVertexColor(vertex).getRGB()); Options graphDisplayOptions = toolOptions.getOptions(options.getRootOptionsName()); Options vertexColorOptions = graphDisplayOptions.getOptions("Vertex Colors"); - vertexColorOptions.setColor("V1", Palette.CYAN); + vertexColorOptions.setColor("V1", Palette.GOLD); - assertEquals(Palette.CYAN, options.getVertexColor(vertex)); + assertEquals(Palette.GOLD.getRGB(), options.getVertexColor(vertex).getRGB()); } } diff --git a/Ghidra/Framework/Help/src/main/java/help/CustomTOCView.java b/Ghidra/Framework/Help/src/main/java/help/CustomTOCView.java index 4764282c01..8b5841137b 100644 --- a/Ghidra/Framework/Help/src/main/java/help/CustomTOCView.java +++ b/Ghidra/Framework/Help/src/main/java/help/CustomTOCView.java @@ -18,10 +18,10 @@ package help; import java.awt.Component; import java.net.MalformedURLException; import java.net.URL; -import java.util.Hashtable; -import java.util.Locale; +import java.util.*; import javax.help.*; +import javax.help.Map; import javax.help.Map.ID; import javax.help.event.HelpModelEvent; import javax.help.plaf.HelpNavigatorUI; @@ -143,6 +143,8 @@ public class CustomTOCView extends TOCView { * Our hook to install our custom cell renderer. */ class CustomTOCNavigatorUI extends BasicTOCNavigatorUI { + private static final String ROOT_TOC_ID = "Root"; + public CustomTOCNavigatorUI(JHelpTOCNavigator b) { super(b); } @@ -184,27 +186,42 @@ public class CustomTOCView extends TOCView { } TOCItem item = (TOCItem) treeItem; - ID itemID = item.getID(); - if (itemID == null) { - Msg.debug(this, "No help ID for " + item); - return; - } - String presentation = item.getPresentation(); if (presentation != null) { return; // don't currently support presentations } CustomTreeItemDecorator customItem = (CustomTreeItemDecorator) item; + ID itemId = getId(customItem, helpModel); + if (itemId == null) { + Msg.debug(this, "No help ID for " + item); + return; + } + String customDisplayText = customItem.getDisplayText(); try { - helpModel.setCurrentID(itemID, customDisplayText, navigator); + helpModel.setCurrentID(itemId, customDisplayText, navigator); } catch (InvalidHelpSetContextException ex) { Msg.error(this, "Exception setting new help item ID", ex); } } + private ID getId(CustomTreeItemDecorator item, HelpModel helpModel) { + ID itemId = item.getID(); + if (itemId != null) { + return itemId; + } + + String tocID = item.getTocID(); + if (Objects.equals(tocID, ROOT_TOC_ID)) { + HelpSet hs = helpModel.getHelpSet(); + return hs.getHomeID(); + } + + return null; + } + private TOCItem getSelectedItem(TreeSelectionEvent e, JHelpNavigator navigator) { TreePath newLeadSelectionPath = e.getNewLeadSelectionPath(); if (newLeadSelectionPath == null) { diff --git a/Ghidra/Framework/Help/src/main/java/help/GHelpBuilder.java b/Ghidra/Framework/Help/src/main/java/help/GHelpBuilder.java index d40205bb97..2a51ad64c3 100644 --- a/Ghidra/Framework/Help/src/main/java/help/GHelpBuilder.java +++ b/Ghidra/Framework/Help/src/main/java/help/GHelpBuilder.java @@ -21,7 +21,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; -import ghidra.GhidraApplicationLayout; +import generic.theme.Gui; import ghidra.framework.Application; import ghidra.framework.ApplicationConfiguration; import help.validator.*; @@ -55,8 +55,8 @@ public class GHelpBuilder { private String outputDirectoryName; private String moduleName; - private Collection dependencyHelpPaths = new LinkedHashSet(); - private Collection helpInputDirectories = new LinkedHashSet(); + private Collection dependencyHelpPaths = new LinkedHashSet<>(); + private Collection helpInputDirectories = new LinkedHashSet<>(); private static boolean debugEnabled = false; private boolean ignoreInvalid = false; // TODO: Do actual validation here @@ -66,9 +66,18 @@ public class GHelpBuilder { public static void main(String[] args) throws Exception { GHelpBuilder builder = new GHelpBuilder(); builder.exitOnError = true; + ApplicationConfiguration config = new ApplicationConfiguration() { + @Override + protected void initializeApplication() { + Gui.initialize(); + } - ApplicationConfiguration config = new ApplicationConfiguration(); - Application.initializeApplication(new GhidraApplicationLayout(), config); + @Override + public boolean isHeadless() { + return false; + } + }; + Application.initializeApplication(new HelpApplicationLayout("Help Builder", "0.1"), config); builder.build(args); } @@ -98,7 +107,7 @@ public class GHelpBuilder { } private HelpModuleCollection collectAllHelp() { - List allHelp = new ArrayList(helpInputDirectories); + List allHelp = new ArrayList<>(helpInputDirectories); for (File file : dependencyHelpPaths) { allHelp.add(file); } diff --git a/Ghidra/Framework/Help/src/main/java/help/GHelpHTMLEditorKit.java b/Ghidra/Framework/Help/src/main/java/help/GHelpHTMLEditorKit.java index 59b58ebec9..62168f89ee 100644 --- a/Ghidra/Framework/Help/src/main/java/help/GHelpHTMLEditorKit.java +++ b/Ghidra/Framework/Help/src/main/java/help/GHelpHTMLEditorKit.java @@ -34,6 +34,8 @@ import javax.swing.text.html.*; import javax.swing.text.html.HTML.Tag; import generic.jar.ResourceFile; +import generic.theme.GIcon; +import generic.theme.Gui; import ghidra.framework.Application; import ghidra.framework.preferences.Preferences; import ghidra.util.Msg; @@ -480,6 +482,12 @@ public class GHelpHTMLEditorKit extends HTMLEditorKit { } String srcString = src.toString(); + + //check if the icon is a defined icon theme id + if (Gui.hasIcon(srcString)) { + return new GIcon(srcString).getUrl(); + } + if (isJavaCode(srcString)) { return installImageFromJavaCode(srcString); } diff --git a/Ghidra/Framework/Help/src/main/java/help/GHelpSet.java b/Ghidra/Framework/Help/src/main/java/help/GHelpSet.java index 6b1cd1cc22..b847bc8834 100644 --- a/Ghidra/Framework/Help/src/main/java/help/GHelpSet.java +++ b/Ghidra/Framework/Help/src/main/java/help/GHelpSet.java @@ -54,8 +54,6 @@ import ghidra.util.SystemUtilities; */ public class GHelpSet extends HelpSet { - private static final String HOME_ID = "Misc_Welcome_to_Ghidra_Help"; - /** static map that contains all known help sets in the system. */ private static java.util.Map helpSetsToCombinedMaps = new java.util.HashMap<>(); private static java.util.Map helpSetsToLocalMaps = new java.util.HashMap<>(); @@ -79,8 +77,6 @@ public class GHelpSet extends HelpSet { setKeyData(kitTypeRegistry, type, editorKit); setKeyData(kitLoaderRegistry, type, classLoader); - setHomeID(HOME_ID); - initializeCombinedMapWrapper(); } @@ -121,6 +117,11 @@ public class GHelpSet extends HelpSet { } } + @Override + public String toString() { + return getHelpSetURL().toString(); + } + //================================================================================================== // Inner Classes //================================================================================================== diff --git a/Ghidra/Framework/Help/src/main/java/help/HelpApplicationLayout.java b/Ghidra/Framework/Help/src/main/java/help/HelpApplicationLayout.java new file mode 100644 index 0000000000..1872016f53 --- /dev/null +++ b/Ghidra/Framework/Help/src/main/java/help/HelpApplicationLayout.java @@ -0,0 +1,154 @@ +/* ### + * 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 help; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.*; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import generic.jar.ResourceFile; +import ghidra.framework.ApplicationProperties; +import ghidra.framework.GModule; +import ghidra.util.SystemUtilities; +import util.CollectionUtils; +import utility.application.ApplicationLayout; +import utility.application.ApplicationUtilities; +import utility.module.ClasspathFilter; +import utility.module.ModuleUtilities; + +// +// TODO this class should be deleted when the GP-1981 branch is merged into master. The +// DockingApplicationLayout is not accessible by help, due to Docking depending on Help. +// Much of the application layout code should live in Utility so that it is reachable by more +// modules. Docking and Ghidra application layout classes should also have their names +// changed. +// +// Perhaps: ModuleAppliactionLayout and ClasspathApplicationLayout. +// +public class HelpApplicationLayout extends ApplicationLayout { + + private static final String NO_RELEASE_NAME = "NO_RELEASE"; + + /** Dev mode main source bin dir pattern */ + private static final Pattern CLASS_PATH_MODULE_NAME_PATTERN = + Pattern.compile(".*/(\\w+)/bin/main"); + + /** + * Constructs a new docking application layout object with the given name and version. + * + * @param name The name of the application. + * @param version The version of the application. + * @throws FileNotFoundException if there was a problem getting a user directory. + */ + public HelpApplicationLayout(String name, String version) throws FileNotFoundException { + + this.applicationProperties = + Objects.requireNonNull(new ApplicationProperties(name, version, NO_RELEASE_NAME)); + this.applicationRootDirs = getDefaultApplicationRootDirs(); + applicationRootDirs.addAll(getAdditionalApplicationRootDirs(applicationRootDirs)); + + // Application installation directory + applicationInstallationDir = applicationRootDirs.iterator().next().getParentFile(); + if (SystemUtilities.isInDevelopmentMode()) { + applicationInstallationDir = applicationInstallationDir.getParentFile(); + } + + // Modules + if (SystemUtilities.isInDevelopmentMode()) { + + // In development mode we rely on the IDE's classpath to determine which modules to + // include, as opposed to scanning the filesystem. This prevents unrelated modules + // from being used. + + modules = ModuleUtilities.findModules(applicationRootDirs, + ModuleUtilities.findModuleRootDirectories(applicationRootDirs), + new ClasspathFilter()); + } + else { + modules = ModuleUtilities.findModules(applicationRootDirs, applicationRootDirs); + } + + // User directories + userTempDir = ApplicationUtilities.getDefaultUserTempDir(applicationProperties); + userSettingsDir = ApplicationUtilities.getDefaultUserSettingsDir(applicationProperties, + applicationInstallationDir); + } + + protected Collection getAdditionalApplicationRootDirs( + Collection roots) { + return Collections.emptyList(); + } + + protected Map findModules() { + if (!SystemUtilities.isInDevelopmentMode()) { + // in release mode we only have one application root, so no need to find all others + return ModuleUtilities.findModules(applicationRootDirs, applicationRootDirs); + } + + // In development mode we may have multiple module root directories under which modules may + // be found. Search all roots for modules. + Collection roots = + ModuleUtilities.findModuleRootDirectories(applicationRootDirs, new ArrayList<>()); + Map allModules = ModuleUtilities.findModules(applicationRootDirs, roots); + + // Filter any modules found to ensure that we only include those that are listed on the + // classpath. (Due to the nature of how the development classpath is created, not all + // found modules may match the classpath entries.) + Set cpNames = getClassPathModuleNames(); + Map filteredModules = new HashMap<>(); + Set> entrySet = allModules.entrySet(); + for (Entry entry : entrySet) { + GModule module = entry.getValue(); + if (cpNames.contains(module.getName())) { + filteredModules.put(entry.getKey(), module); + } + } + + return filteredModules; + } + + private Set getClassPathModuleNames() { + String cp = System.getProperty("java.class.path"); + String[] pathParts = cp.split(File.pathSeparator); + Set paths = new HashSet<>(Arrays.asList(pathParts)); + Set cpNames = new HashSet<>(); + for (String cpEntry : paths) { + Matcher matcher = CLASS_PATH_MODULE_NAME_PATTERN.matcher(cpEntry); + if (matcher.matches()) { + cpNames.add(matcher.group(1)); + } + } + return cpNames; + } + + /** + * Get the default list of Application directories. In repo-based + * development mode this includes the root Ghidra directory within each repo. + * When not in development mode, the requirement is that the current working + * directory correspond to the installation root. The first entry will be + * the primary root in both cases. + * @return root directories + */ + public static Collection getDefaultApplicationRootDirs() { + if (SystemUtilities.isInDevelopmentMode()) { + return ApplicationUtilities.findDefaultApplicationRootDirs(); + } + return CollectionUtils.asList(new ResourceFile(System.getProperty("user.dir"))); + } +} diff --git a/Ghidra/Framework/Help/src/main/java/help/HelpBuildUtils.java b/Ghidra/Framework/Help/src/main/java/help/HelpBuildUtils.java index a69d6c6128..965d52c451 100644 --- a/Ghidra/Framework/Help/src/main/java/help/HelpBuildUtils.java +++ b/Ghidra/Framework/Help/src/main/java/help/HelpBuildUtils.java @@ -24,6 +24,8 @@ import java.util.Collections; import java.util.regex.Matcher; import java.util.regex.Pattern; +import generic.theme.GIcon; +import generic.theme.Gui; import help.validator.location.*; import resources.IconProvider; import resources.Icons; @@ -73,9 +75,12 @@ public class HelpBuildUtils { } /** - * Returns a file object that is the help topic directory for the given file. - * This method is useful for finding the help topic directory when the given - * file doesn't live directly under a help topic. + * Returns a file object that is the help topic directory for the given file. + * + *

This method is useful for finding the help topic directory when the given file doesn't + * live directly under a help topic. + * @param file the file for which to find a topic + * @return the path to the help topic directory */ public static Path getHelpTopicDir(Path file) { Path helpTopics = file.getFileSystem().getPath("help", "topics"); @@ -540,7 +545,7 @@ public class HelpBuildUtils { * @param sourceFile the source file path of the image reference * @param ref the reference text * @return an absolute path; null if the URI is remote - * @throws URISyntaxException + * @throws URISyntaxException if there is an exception creating a URL/URI for the image location */ public static ImageLocation locateImageReference(Path sourceFile, String ref) throws URISyntaxException { @@ -563,6 +568,13 @@ public class HelpBuildUtils { } return ImageLocation.createRuntimeLocation(sourceFile, ref, resolved, path); } + if (Gui.hasIcon(ref)) { + GIcon gIcon = new GIcon(ref); + URL url = gIcon.getUrl(); + URI resolved = url.toURI(); + Path path = toPath(resolved); + return ImageLocation.createRuntimeLocation(sourceFile, ref, resolved, path); + } URI resolved = resolve(sourceFile, ref); if (isRemote(resolved)) { @@ -574,13 +586,14 @@ public class HelpBuildUtils { } /** - * Turn an HTML HREF reference into an absolute path. This will - * locate files based upon relative references, specialized help system references (i.e., - * help/topics/...), and absolute URLs. + * Turn an HTML HREF reference into an absolute path. This will locate files based upon + * relative references, specialized help system references (i.e., help/topics/...), and + * absolute URLs. * + * @param sourceFile the reference's source file * @param ref the reference text * @return an absolute path; null if the URI is remote - * @throws URISyntaxException + * @throws URISyntaxException if there is an exception creating a URL/URI for the image location */ public static Path locateReference(Path sourceFile, String ref) throws URISyntaxException { diff --git a/Ghidra/Framework/Help/src/test/java/help/HelpBuildUtilsTest.java b/Ghidra/Framework/Help/src/test/java/help/HelpBuildUtilsTest.java index acc7faf851..357bf1a880 100644 --- a/Ghidra/Framework/Help/src/test/java/help/HelpBuildUtilsTest.java +++ b/Ghidra/Framework/Help/src/test/java/help/HelpBuildUtilsTest.java @@ -17,12 +17,19 @@ package help; import static org.junit.Assert.*; +import java.io.File; +import java.io.IOException; import java.net.URISyntaxException; import java.nio.file.Path; import java.nio.file.Paths; import org.junit.Test; +import generic.theme.Gui; +import ghidra.GhidraTestApplicationLayout; +import ghidra.framework.ApplicationConfiguration; +import utility.application.ApplicationLayout; + public class HelpBuildUtilsTest extends AbstractHelpTest { private static final String HELP_TOPIC_PATH = "/some/fake/path/to/help/topics"; @@ -33,6 +40,22 @@ public class HelpBuildUtilsTest extends AbstractHelpTest { super(); } + @Override + protected ApplicationLayout createApplicationLayout() throws IOException { + return new GhidraTestApplicationLayout(new File(getTestDirectoryPath())); + } + + @Override + protected ApplicationConfiguration createApplicationConfiguration() { + ApplicationConfiguration configuration = new ApplicationConfiguration() { + @Override + public boolean isHeadless() { + return false; + } + }; + return configuration; + } + @Test public void testGetRelativeHelpPath() { String relativeString = "help/topics/FooTopic/FooFile.html"; @@ -78,6 +101,7 @@ public class HelpBuildUtilsTest extends AbstractHelpTest { @Test public void testLocateReferences_Icons() throws URISyntaxException { + Gui.initialize(); Path sourceFile = Paths.get(HTML_FILE_PATH); String reference = "Icons.REFRESH_ICON"; // see Icons class ImageLocation location = HelpBuildUtils.locateImageReference(sourceFile, reference); diff --git a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/framework/main/datatree/VersionControlAction2Test.java b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/framework/main/datatree/VersionControlAction2Test.java index ef005ff63b..84fd92be8c 100644 --- a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/framework/main/datatree/VersionControlAction2Test.java +++ b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/framework/main/datatree/VersionControlAction2Test.java @@ -17,6 +17,8 @@ package ghidra.framework.main.datatree; import static org.junit.Assert.*; +import java.net.URL; +import java.util.Objects; import java.util.Set; import javax.swing.*; @@ -190,9 +192,11 @@ public class VersionControlAction2Test extends AbstractVersionControlActionTest assertTrue(icon instanceof MultiIcon); Icon[] icons = ((MultiIcon) icon).getIcons(); Icon checkOutIcon = ResourceManager.loadImage("images/checkex.png"); + URL checkOutIconUrl = getURL(checkOutIcon); boolean found = false; for (Icon element : icons) { - if (checkOutIcon.equals(element)) { + URL elementUrl = getURL(element); + if (Objects.equals(checkOutIconUrl, elementUrl)) { found = true; break; } diff --git a/Ghidra/Test/IntegrationTest/src/test/java/ghidra/util/bean/PathManagerTest.java b/Ghidra/Test/IntegrationTest/src/test/java/ghidra/util/bean/PathManagerTest.java index 8fdb268d56..69573d1611 100644 --- a/Ghidra/Test/IntegrationTest/src/test/java/ghidra/util/bean/PathManagerTest.java +++ b/Ghidra/Test/IntegrationTest/src/test/java/ghidra/util/bean/PathManagerTest.java @@ -17,6 +17,7 @@ package ghidra.util.bean; import static org.junit.Assert.*; +import java.awt.Container; import java.io.File; import java.util.ArrayList; import java.util.List; @@ -34,7 +35,7 @@ import docking.widgets.table.GTable; import generic.util.Path; import ghidra.framework.preferences.Preferences; import ghidra.util.filechooser.ExtensionFileFilter; -import resources.ResourceManager; +import resources.Icons; public class PathManagerTest extends AbstractDockingTest { @@ -42,6 +43,10 @@ public class PathManagerTest extends AbstractDockingTest { private GTable table; private JFrame frame; private boolean wasListenerNotified = false; + private JButton removeButton; + private JButton addButton; + private JButton upButton; + private JButton downButton; @Before public void setUp() throws Exception { @@ -61,6 +66,11 @@ public class PathManagerTest extends AbstractDockingTest { frame.pack(); }); frame.setVisible(true); + Container panel = pathManager.getComponent(); + removeButton = findButtonByIcon(panel, Icons.DELETE_ICON); + addButton = findButtonByIcon(panel, Icons.ADD_ICON); + upButton = findButtonByIcon(panel, Icons.UP_ICON); + downButton = findButtonByIcon(panel, Icons.DOWN_ICON); } @After @@ -72,8 +82,6 @@ public class PathManagerTest extends AbstractDockingTest { @Test public void testUpArrow() throws Exception { selectRow(3); - JButton upButton = findButtonByIcon(pathManager.getComponent(), - ResourceManager.loadImage("images/up.png")); assertNotNull(upButton); pressButton(upButton, true); waitForSwing(); @@ -105,8 +113,6 @@ public class PathManagerTest extends AbstractDockingTest { public void testDownArrow() throws Exception { selectRow(2); - JButton downButton = findButtonByIcon(pathManager.getComponent(), - ResourceManager.loadImage("images/down.png")); assertNotNull(downButton); pressButton(downButton, true); waitForSwing(); @@ -138,30 +144,28 @@ public class PathManagerTest extends AbstractDockingTest { public void testRemove() throws Exception { selectRow(3); - JButton button = findButtonByIcon(pathManager.getComponent(), - ResourceManager.loadImage("images/edit-delete.png")); - assertNotNull(button); - pressButton(button, true); + assertNotNull(removeButton); + pressButton(removeButton, true); waitForSwing(); int row = table.getSelectedRow(); assertEquals(2, row); - pressButton(button, true); + pressButton(removeButton, true); waitForSwing(); row = table.getSelectedRow(); assertEquals(1, row); - pressButton(button, true); + pressButton(removeButton, true); waitForSwing(); row = table.getSelectedRow(); assertEquals(0, row); - pressButton(button, true); + pressButton(removeButton, true); waitForSwing(); row = table.getSelectedRow(); assertEquals(-1, row); - assertTrue(!button.isEnabled()); + assertTrue(!removeButton.isEnabled()); } @Test @@ -188,10 +192,8 @@ public class PathManagerTest extends AbstractDockingTest { Preferences.LAST_IMPORT_DIRECTORY, GhidraFileChooserMode.FILES_AND_DIRECTORIES, true, new ExtensionFileFilter(new String[] { "h" }, "C Header Files")); - JButton button = findButtonByIcon(pathManager.getComponent(), - ResourceManager.loadImage("images/Plus.png")); - assertNotNull(button); - pressButton(button, false); + assertNotNull(addButton); + pressButton(addButton, false); waitForSwing(); GhidraFileChooser fileChooser = waitForDialogComponent(GhidraFileChooser.class); @@ -226,10 +228,8 @@ public class PathManagerTest extends AbstractDockingTest { Preferences.LAST_IMPORT_DIRECTORY, GhidraFileChooserMode.FILES_AND_DIRECTORIES, true, new ExtensionFileFilter(new String[] { "h" }, "C Header Files")); - JButton button = findButtonByIcon(pathManager.getComponent(), - ResourceManager.loadImage("images/Plus.png")); - assertNotNull(button); - pressButton(button, false); + assertNotNull(addButton); + pressButton(addButton, false); waitForSwing(); GhidraFileChooser fileChooser = waitForDialogComponent(GhidraFileChooser.class); diff --git a/Ghidra/Test/IntegrationTest/src/test/java/ghidra/util/bean/PathnameTablePanelTest.java b/Ghidra/Test/IntegrationTest/src/test/java/ghidra/util/bean/PathnameTablePanelTest.java index 0cd1c8019c..9707476846 100644 --- a/Ghidra/Test/IntegrationTest/src/test/java/ghidra/util/bean/PathnameTablePanelTest.java +++ b/Ghidra/Test/IntegrationTest/src/test/java/ghidra/util/bean/PathnameTablePanelTest.java @@ -28,10 +28,11 @@ import docking.widgets.OptionDialog; import docking.widgets.filechooser.GhidraFileChooser; import docking.widgets.filechooser.GhidraFileChooserMode; import docking.widgets.pathmanager.PathnameTablePanel; +import generic.theme.GIcon; import ghidra.app.util.importer.LibrarySearchPathManager; import ghidra.framework.preferences.Preferences; import ghidra.util.filechooser.ExtensionFileFilter; -import resources.ResourceManager; +import resources.Icons; /** * @@ -45,6 +46,11 @@ public class PathnameTablePanelTest extends AbstractDockingTest { private JFrame frame; private String[] tablePaths = { "c:\\path_one", "c:\\path_two", "c:\\path_three", "c:\\path_four", "c:\\path_five" }; + private JButton resetButton; + private JButton removeButton; + private JButton addButton; + private JButton upButton; + private JButton downButton; @Before public void setUp() throws Exception { @@ -54,6 +60,12 @@ public class PathnameTablePanelTest extends AbstractDockingTest { frame = new JFrame("Test"); frame.getContentPane().add(panel); runSwing(() -> frame.setVisible(true)); + + resetButton = findButtonByIcon(panel, new GIcon("icon.widget.pathmanager.reset")); + removeButton = findButtonByIcon(panel, Icons.DELETE_ICON); + addButton = findButtonByIcon(panel, Icons.ADD_ICON); + upButton = findButtonByIcon(panel, Icons.UP_ICON); + downButton = findButtonByIcon(panel, Icons.DOWN_ICON); } @After @@ -64,7 +76,6 @@ public class PathnameTablePanelTest extends AbstractDockingTest { @Test public void testUpArrow() throws Exception { selectRow(3); - JButton upButton = findButtonByIcon(panel, ResourceManager.loadImage("images/up.png")); assertNotNull(upButton); pressButton(upButton, true); waitForPostedSwingRunnables(); @@ -96,7 +107,6 @@ public class PathnameTablePanelTest extends AbstractDockingTest { public void testDownArrow() throws Exception { selectRow(2); - JButton downButton = findButtonByIcon(panel, ResourceManager.loadImage("images/down.png")); assertNotNull(downButton); pressButton(downButton, true); waitForPostedSwingRunnables(); @@ -128,35 +138,33 @@ public class PathnameTablePanelTest extends AbstractDockingTest { public void testRemove() throws Exception { selectRow(4); - JButton button = - findButtonByIcon(panel, ResourceManager.loadImage("images/edit-delete.png")); - assertNotNull(button); - pressButton(button, true); + assertNotNull(removeButton); + pressButton(removeButton, true); waitForPostedSwingRunnables(); int row = table.getSelectedRow(); assertEquals(3, row); - pressButton(button, true); + pressButton(removeButton, true); waitForPostedSwingRunnables(); row = table.getSelectedRow(); assertEquals(2, row); - pressButton(button, true); + pressButton(removeButton, true); waitForPostedSwingRunnables(); row = table.getSelectedRow(); assertEquals(1, row); - pressButton(button, true); + pressButton(removeButton, true); waitForPostedSwingRunnables(); row = table.getSelectedRow(); assertEquals(0, row); - pressButton(button, true); + pressButton(removeButton, true); waitForPostedSwingRunnables(); row = table.getSelectedRow(); assertEquals(-1, row); - assertTrue(!button.isEnabled()); + assertTrue(!removeButton.isEnabled()); } @Test @@ -168,9 +176,8 @@ public class PathnameTablePanelTest extends AbstractDockingTest { GhidraFileChooserMode.FILES_AND_DIRECTORIES, true, new ExtensionFileFilter(new String[] { "h" }, "C Header Files")); - JButton button = findButtonByIcon(panel, ResourceManager.loadImage("images/Plus.png")); - assertNotNull(button); - pressButton(button, false); + assertNotNull(addButton); + pressButton(addButton, false); waitForPostedSwingRunnables(); selectFromFileChooser(); @@ -191,9 +198,8 @@ public class PathnameTablePanelTest extends AbstractDockingTest { GhidraFileChooserMode.FILES_AND_DIRECTORIES, true, new ExtensionFileFilter(new String[] { "h" }, "C Header Files")); - JButton button = findButtonByIcon(panel, ResourceManager.loadImage("images/Plus.png")); - assertNotNull(button); - pressButton(button, false); + assertNotNull(addButton); + pressButton(addButton, false); waitForPostedSwingRunnables(); GhidraFileChooser fileChooser = waitForDialogComponent(GhidraFileChooser.class); @@ -226,9 +232,8 @@ public class PathnameTablePanelTest extends AbstractDockingTest { GhidraFileChooserMode.FILES_AND_DIRECTORIES, true, new ExtensionFileFilter(new String[] { "h" }, "C Header Files")); - JButton button = findButtonByIcon(panel, ResourceManager.loadImage("images/Plus.png")); - assertNotNull(button); - pressButton(button, false); + assertNotNull(addButton); + pressButton(addButton, false); waitForPostedSwingRunnables(); selectFromFileChooser(); @@ -242,11 +247,6 @@ public class PathnameTablePanelTest extends AbstractDockingTest { @Test public void testReset() throws Exception { - JButton removeButton = - findButtonByIcon(panel, ResourceManager.loadImage("images/edit-delete.png")); - JButton addButton = findButtonByIcon(panel, ResourceManager.loadImage("images/Plus.png")); - JButton resetButton = - findButtonByIcon(panel, ResourceManager.loadImage("images/trash-empty.png")); assertNotNull(removeButton); assertNotNull(addButton); diff --git a/gradle/helpProject.gradle b/gradle/helpProject.gradle index a75989f6d7..0bfe584944 100644 --- a/gradle/helpProject.gradle +++ b/gradle/helpProject.gradle @@ -70,11 +70,11 @@ task indexHelp(type: JavaExec) { group "private" description "indexes the helps files for this module. [gradle/helpProject.gradle]" - File helpRootDir = file('src/main/help/help') File outputFile = file("build/help/main/help/${project.name}_JavaHelpSearch") dependsOn configurations.helpPath + dependsOn configurations.runtimeClasspath inputs.dir helpRootDir outputs.dir outputFile @@ -132,12 +132,18 @@ task buildHelp(type: JavaExec, dependsOn: indexHelp) { group rootProject.GHIDRA_GROUP description " Builds the help for this module. [gradle/helpProject.gradle]\n" - outputs.upToDateWhen {false} + outputs.upToDateWhen {false} // TODO remove this. we should be able to get the inputs right + // the issue is if docs get changed in a dependant module, + // this modules needs to know to rebuild File helpRootDir = file('src/main/help/help') File outputDir = file('build/help/main/help') - inputs.dir helpRootDir + inputs.dir file('src/main/help'); + File resourcesDir = file('src/main/resources') + if (resourcesDir.exists()) { + inputs.dir file('src/main/resources'); + } outputs.dir outputDir mainClass = 'help.GHelpBuilder' @@ -150,8 +156,15 @@ task buildHelp(type: JavaExec, dependsOn: indexHelp) { // args '-debug' // print debug info doFirst { - // this modules runtime classpath (contains jhall.jar) - classpath project(':Help').sourceSets.main.runtimeClasspath + + // this module's runtime classpath (contains jhall.jar) + classpath project(':Help').sourceSets.main.runtimeClasspath + + // include the classpath for the project using this Help gradle script plugin + classpath += project.sourceSets.main.runtimeClasspath + // since this runs BEFORE resources are copied, include the resources source dir in + // the classpath so the help validator can find them + classpath += files('src/main/resources') configurations.helpPath.each { args "-hp"