GP-1981 - Updated help to allow authors to use theme image ids; updated

help to only allow modules that live on the classpath. Dpdating themd
documentation. Fixing gradle help build
This commit is contained in:
ghidragon
2022-10-20 14:09:21 -04:00
parent c86b884daf
commit 45c52e3cb9
105 changed files with 1660 additions and 569 deletions
@@ -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
@@ -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");
@@ -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();
+1
View File
@@ -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'
}
+4 -3
View File
@@ -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|
@@ -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
@@ -49,10 +49,7 @@
<tocroot>
<tocdef id="Root"
sortgroup="a"
text="Welcome to Ghidra Help"
target="help/topics/Misc/Welcome_to_Ghidra_Help.htm">
<tocref id="Root">
<tocdef id="Intro" sortgroup="1a" text="Introduction" target="help/topics/Intro/Intro.htm" />
@@ -383,11 +380,11 @@
<tocdef id="Glossary" sortgroup="i" text="Glossary" target="help/topics/Glossary/glossary.htm" />
<tocdef id="What's New" sortgroup="j" text="What's New" target="docs/WhatsNew.html" />
<tocdef id="Tips of the Day" sortgroup="k" text="Tips of the Day" target="help/topics/Misc/Tips.htm" />
<tocdef id="Appendix" sortgroup="m" text="Appendix" target="help/topics/Misc/Appendix.htm">
<tocdef id="Appendix" sortgroup="z" text="Appendix" target="help/topics/Misc/Appendix.htm">
<tocdef id="Block Models" sortgroup="a" text="Block Models" target="help/topics/BlockModel/Block_Model.htm" />
<tocdef id="Languages" sortgroup="b" text="Languages" target="help/topics/LanguageProviderPlugin/Languages.htm" />
</tocdef>
</tocdef> <!-- End Welcome to Ghidra Help -->
</tocref> <!-- End Welcome to Ghidra Help -->
</tocroot>
@@ -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;
@@ -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);
@@ -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();
@@ -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) {
@@ -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<ResourceFile, Set<URL>> helpSetsByModule = findHelpSetsByModule();

Before

Width:  |  Height:  |  Size: 444 B

After

Width:  |  Height:  |  Size: 444 B

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Before

Width:  |  Height:  |  Size: 587 B

After

Width:  |  Height:  |  Size: 587 B

Before

Width:  |  Height:  |  Size: 663 B

After

Width:  |  Height:  |  Size: 663 B

@@ -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);
}
@@ -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")
@@ -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);
}
@@ -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());
}
@@ -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";
@@ -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));
@@ -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));
}
@@ -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);
@@ -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
@@ -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);
@@ -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);
@@ -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
@@ -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());
}
@@ -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
@@ -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;
}
/**
@@ -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;
}
}
@@ -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) {
@@ -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);
@@ -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
@@ -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|
@@ -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
@@ -49,8 +49,19 @@
<tocroot>
<tocdef id="Theming"
text="Theming"
target="help/topics/Theming/Theming.htm" >
<!--
Note: we have omitted the target url for the root node. Rather than defining a help page
for this node, we allow the system's default 'home id' to be used. (Any time a help item
has no help defined, the 'home id' is displayed.) When the system's HelpManager loads
GHelpSets, it will specify the 'home id' specific to that application.
-->
<tocdef id="Root" sortgroup="a" text="Welcome to Help">
<tocdef id="Theming" text="Theming" sortgroup="t" target="help/topics/Theming/ThemingOverview.html">
<tocdef id="Overview" sortgroup="1" text="Overview" target="help/topics/Theming/ThemingOverview.html"/>
<tocdef id="Editing Themes" sortgroup="2" text="Editing Themes" target="help/topics/Theming/ThemingUserDocs.html"/>
<tocdef id="Developer Documentation" sortgroup="3" text="Developer Documentation" target="help/topics/Theming/ThemingDeveloperDocs.html"/>
<tocdef id="Architecture Documentation" sortgroup="4" text="Architecture Documentation" target="help/topics/Theming/ThemingInternals.html"/>
</tocdef>
</tocdef>
</tocroot>
@@ -0,0 +1,26 @@
<!DOCTYPE doctype PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN">
<html>
<head>
<title>Welcome to Help</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta http-equiv="content-type" content="text/html; charset=windows-1252">
<link rel="stylesheet" type="text/css" href="../../shared/Frontpage.css">
<meta name="generator" content="Microsoft FrontPage 4.0">
</head>
<body>
<h1 align="center"><a name="Help_Contents"></a>Welcome to Help...</h1>
<div align="left">
<p>We provide context sensitive help on menu items, dialogs, buttons,
and tool windows. To access the help, press &lt;F1&gt; or &lt;Help&gt; on
any menu item or dialog. If specific help is not available for an item,
this page will be displayed.</p>
</div>
</body>
</html>
@@ -0,0 +1,441 @@
<!DOCTYPE doctype>
<HTML>
<HEAD>
<META name="generator" content=
"HTML Tidy for Java (vers. 2009-12-01), see jtidy.sourceforge.net">
<LINK rel="stylesheet" type="text/css" href="../../shared/Frontpage.css">
<TITLE>Theming Developer Documentation</TITLE>
<TITLE></TITLE>
</HEAD>
<BODY>
Theming Development Documentation
<H1>Ghidra Theming Developer Documentation</H1>
<P>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.</P>
<H2>Theme Resource Types</H2>
<P>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).&nbsp; 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.</P>
<BLOCKQUOTE>
<H3>Colors</H3>
<P>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:</P>
<BLOCKQUOTE>
<BLOCKQUOTE>
<CODE class="code">panel.setBackground(Color.Red);</CODE>
</BLOCKQUOTE>
<P>becomes</P>
<BLOCKQUOTE>
<CODE class="code">panel.setBackground(new GColor("color.bg.abc"));</CODE>
</BLOCKQUOTE>
<P>and</P>
<BLOCKQUOTE>
<CODE class="code">public static final Color MY_COLOR = Color.BLUE;</CODE>
</BLOCKQUOTE>
<P>becomes</P>
<BLOCKQUOTE>
<CODE class="code">public static final Color MY_COLOR = new
GColor("color.fg.xzy");</CODE>
</BLOCKQUOTE>
</BLOCKQUOTE>
<P>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.</P>
<H3>Fonts</H3>
<P>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:</P>
<BLOCKQUOTE>
<BLOCKQUOTE>
<CODE class="code">Font font = new Font("Monospaced", Font.BOLD, 12);</CODE>
</BLOCKQUOTE>
<P>becomes</P>
<BLOCKQUOTE>
<CODE class="code">Font font = Gui.getFont("font.xyz");</CODE>
</BLOCKQUOTE>
<P>or</P>
<BLOCKQUOTE>
<CODE class="code">myLabel.setFont(new Font("Dialog", Font.PLAIN, 14)</CODE>
</BLOCKQUOTE>
<P>becomes</P>
<BLOCKQUOTE>
<CODE class="code">Gui.registerFont(myLabel, "font.xyz");</CODE>
</BLOCKQUOTE>
</BLOCKQUOTE>
<H3>Icons</H3>
<P>Icons work just like colors, so you can just create a GIcon(String id). So, for
example,&nbsp;</P>
<BLOCKQUOTE>
<BLOCKQUOTE>
<CODE class="code">public static final Icon MY_ICON =
ResourceManager("images/balloon.png");</CODE>
</BLOCKQUOTE>
<P>becomes</P>
<BLOCKQUOTE>
<CODE class="code">public static final Icon MY_ICON = new
GIcon("icon.text.bubble");</CODE>
</BLOCKQUOTE>
</BLOCKQUOTE>
</BLOCKQUOTE>
<H2>Resource Id Strings<A name="Resource_Ids"></A></H2>
<BLOCKQUOTE>
<P>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:&nbsp;</P>
<BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
<CODE>
[type].[category[...]].[client].[specialized uses]
</CODE>
</PRE>
</BLOCKQUOTE>
</BLOCKQUOTE>
<UL>
<LI><B>type:</B> color, font, or icon.</LI>
<LI><B>category:</B> any value, examples include 'bg'(background), 'fg'(foreground),
'cursor'. There may be multiple dot-separated values.</LI>
<LI><B>client:</B> the plugin name or feature name; any value usd to represent a more
specialized use.</LI>
<LI><B>specialized uses:</B> any key value here that applies to the client, such as
"vertex' for a graph client.</LI>
</UL>
<BLOCKQUOTE>
<P>Examples:</P>
<UL>
<LI>color.bg</LI>
<LI>color.bg.listing</LI>
<LI>font.listing</LI>
<LI>font.listing.header</LI>
<LI>icon.error</LI>
<LI>icon.delete</LI>
<LI>icon.plugin.byteviewer.provider</LI>
</UL>
</BLOCKQUOTE>
</BLOCKQUOTE>
<H2>Theme Property Files</H2>
<BLOCKQUOTE>
<P>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'.</P>
<H3>Theme Properties File Naming Convention</H3>
<P>To promote consistency, theme property files should use the following naming
convention:</P>
<BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
<CODE>
[module name][.additional name]].theme.properties
</CODE>
</PRE>
</BLOCKQUOTE>
<P>Examples:</P>
<UL>
<LI>base.theme.properties</LI>
<LI>base.funtiongraph.theme.properties</LI>
</UL>
</BLOCKQUOTE>
<H3>Theme Properties File Format</H3>
<P>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:</P>
<BLOCKQUOTE>
<CODE>
<PRE>
[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]
...
</PRE>
</CODE>
</BLOCKQUOTE>
<P>Example:</P>
<BLOCKQUOTE>
<PRE>
[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
</PRE>
</BLOCKQUOTE>
<P>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.</P>
</BLOCKQUOTE>
<H2>Theme Property Values<A name="Theme_Property_Values"></A></H2>
<BLOCKQUOTE>
<P>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.</P>
<P>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".</P>
<H3>Color Values</H3>
<P>Color values supports the following formats:</P>
<BLOCKQUOTE>
<UL>
<LI>#rrggbb</LI>
<LI>#rrggbbaa</LI>
<LI>0xrrggbb</LI>
<LI>0xrrggbbaa</LI>
<LI>rgb(red, green, blue)</LI>
<LI>rgba(red, green, blue, alpha)</LI>
<LI>[web color name] the name of a web color such as red, olive, or purple</LI>
</UL>
</BLOCKQUOTE>
<P>Examples:</P>
<PRE>
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
</PRE>
<H3>Font Values</H3>
<P>Font values are specified using the following format:</P>
<BLOCKQUOTE>
<PRE>
<CODE>
[family name]-[style]-[size]
</CODE>
</PRE>
<UL>
<LI>family name: the font name such as monospaced, dialog, courier.</LI>
<LI>style: One of PLAIN, BOLD, ITALIC, or BOLDITALIC.</LI>
<LI>size: the font point size. 12 is very common.</LI>
</UL>
</BLOCKQUOTE>
<P>Examples:</P>
<PRE>
font.foo = monospaced-PLAIN-12
font.foo = courier-BOLD-14
font.foo = SansSerif-ITALIC=10
</PRE>
<H4>Font Modifiers</H4>
<P>When referencing another font, the referenced font can be modified using the following
format:</P>
<BLOCKQUOTE>
<PRE>
<CODE>
font.ref[family name][style][size]
</CODE>
</PRE>
<UL>
<LI>font.ref - the theme property id of some other font</LI>
<LI>family name: use the size and style of the reference font, but use this font
family</LI>
<LI>style: use the same font as the reference font, but with this style. One of PLAIN,
BOLD, ITALIC, or BOLDITALIC</LI>
<LI>size: use the same font as the reference font, but with this size.</LI>
</UL>
</BLOCKQUOTE>
<P>Examples:</P>
<PRE>
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
</PRE>
<H3>Icon Values</H3>
<P>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:</P>
<BLOCKQUOTE>
<PRE>
<CODE>
iconName[size(width,height)][disabled]{iconOverlayName[size(width,geight)[disabled][move(x,y)]}{...}
</CODE>
</PRE>
<UL>
<LI>iconName - the name the base icon</LI>
<LI>size(width,height) - optional modifier to scale the image to the given size.</LI>
<LI>disabled - optional modifier to create a disabled version of the icon.</LI>
<LI>{...} - optional modifier to overlay an icon on the base icon. It is recursively
defined using the same format.</LI>
<LI>move(x,y) - optional modifier on overlays to position them relative to the base
icon.</LI>
</UL>
</BLOCKQUOTE>
<P>Examples:</P>
<PRE>
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
</PRE>
<P>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:</P>
<PRE>
icon.foo = EMPTY_ICON[size(16,16)]{flag.png[size(6,6)][move(10,10)]}
</PRE>
<P class="relatedtopic">Related Topics</P>
<UL>
<LI><A href="ThemingOverview.html">Theming Overview</A></LI>
<LI><A href="ThemingUserDocs.html">Theming User Documentation</A></LI>
<LI><A href="ThemingInternals.html">Theming Architecture Documentation</A></LI>
</UL><BR>
</BLOCKQUOTE>
</BODY>
</HTML>
@@ -0,0 +1,186 @@
<!DOCTYPE doctype>
<HTML>
<HEAD>
<META name="generator" content=
"HTML Tidy for Java (vers. 2009-12-01), see jtidy.sourceforge.net">
<TITLE>Theming Internals Documentation</TITLE>
<LINK rel="stylesheet" type="text/css" href="../../shared/Frontpage.css">
</HEAD>
<BODY>
<H1>Ghidra Theming Internals Documentation</H1>
<P>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.&nbsp; The Gui class provides a set of
static methods that serves as the primary interface for managing all aspects of theming.</P>
<H2>GTheme class</H2>
<P>The GTheme class is the implementation of the theme concept. At any giving time, the
application is using resource values as specified by an&nbsp; 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"&nbsp; 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.</P>
<H2>GThemeValueMap / ThemeValue class</H2>
<P>These are the base classes for storing values for resource ids.&nbsp; 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.&nbsp; 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.</P>
<P>GThemeValueMaps have some convenience methods for doing set operations.&nbsp; 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.&nbsp;</P>
<H2>Gui class</H2>
<P>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.</P>
<H2>Application Initialization</H2>
<P>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.</P>
<H2>Loading a Theme</H2>
<P>Loading a theme consists of two main operations. Loading the LookAndFeel and building the
set of values for the resource ids.</P>
<H2>Loading the LookAndFeel</H2>
<P>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),&nbsp; extracting the Java resources mappings(Java LookAndFeel objects also
use a resource id concept), group the java resources into common groups,&nbsp; 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.</P>
<H2>Creating the Active Theme Values</H2>
<P>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" .&nbsp; When
values are loaded into a GThemeValueMap, they will replace any existing values with the same
id.&nbsp; The values are loaded in the following order:</P>
<BLOCKQUOTE>
<UL>
<LI>java defaults (values from LookAndFeel)</LI>
<LI>application defaults (from theme.properties files)</LI>
<LI>applications dark defaults (if theme is dark)</LI>
<LI>theme values (values that were overridden by a specific theme)</LI>
</UL>
</BLOCKQUOTE>
<H2>Changing Values Associated With Resource Ids</H2>
<P>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).&nbsp; It can also vary
depending on whether the value is an application defined resource or a java defined
resource.</P>
<H3>Updating Colors</H3>
<P>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.</P>
<H3>Updating Fonts</H3>
<P>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.</P>
<H3>Updating Icons</H3>
<P>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.</P>
<H2>Creating/Editing/Saving Themes</H2>
<P>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.</P>
<H2>External Icons</H2>
<P>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.</P>
<H2>Importing/Exporting Themes</H2>
<P>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.</P>
<H2>LookAndFeel Notes</H2>
<P>Getting the theming feature to work on all the various Java LookAndFeels is a
challenge.&nbsp; 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.&nbsp; 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.&nbsp; To compensate for the
differences among LookAndFeels, we created a LookAndFeelManager base class with sub-classes for
each LookAndFeel that addresses these differences.</P>
<P class="relatedtopic">Related Topics</P>
<UL>
<LI><A href="ThemingOverview.html">Theming Overview</A></LI>
<LI><A href="ThemingUserDocs.html">Theming User Documentation</A></LI>
<LI><A href="ThemingDeveloperDocs.html">Theming Developer Documentation</A></LI>
</UL><BR>
</BODY>
</HTML>
@@ -0,0 +1,118 @@
<!DOCTYPE doctype>
<HTML>
<HEAD>
<META name="generator" content=
"HTML Tidy for Java (vers. 2009-12-01), see jtidy.sourceforge.net">
<TITLE>Theming Overivew</TITLE>
<LINK rel="stylesheet" type="text/css" href="../../shared/Frontpage.css">
</HEAD>
<BODY>
<H1>Ghidra Theming Overview</H1>
<H2>Goal</H2>
<P>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.&nbsp; 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.</P>
&nbsp;
<H2>Background</H2>
<P>Ghidra previously used hundreds of hard coded colors, fonts, and icons.&nbsp; 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.</P>
<P>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.</P>
<P>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.</P>
<H2>General Concepts and Approach</H2>
<P>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.</P>
<BLOCKQUOTE>
<H3>Indirection</H3>
<P>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.</P>
<H3>Theme</H3>
<P>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.</P>
<H3>Look and Feel Values</H3>
<P>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.&nbsp; 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".</P>
<H3>User Interaction</H3>
<P>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.</P>
</BLOCKQUOTE>
<P class="relatedtopic">Related Topics</P>
<UL>
<LI><A href="ThemingUserDocs.html">Theming User Documentation</A></LI>
<LI><A href="ThemingDeveloperDocs.html">Theming Developer Documentation</A></LI>
<LI><A href="ThemingInternals.html">Theming Architecture Documentation</A></LI>
</UL><BR>
</BODY>
</HTML>
@@ -5,14 +5,14 @@
<META name="generator" content=
"HTML Tidy for Java (vers. 2009-12-01), see jtidy.sourceforge.net">
<TITLE>Theming</TITLE>
<TITLE>Theming User Documentation</TITLE>
<LINK rel="stylesheet" type="text/css" href="../../shared/Frontpage.css">
</HEAD>
<BODY>
<H1 align="center">Theming</H1>
<H1 align="center">Theming User Help</H1>
<H2>Overview</H2>
<H2>Description</H2>
<P>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</P>
<P>Users can also edit and create their own themes using the Theme Editor. Custom themes are
stored in the users &lt;application dir&gt;/themes. These are simple text files that can also
stored in the users &lt;application dir&gt;/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.</P>
@@ -171,52 +171,39 @@
<H2>Theme Property Names</H2>
<P>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.</P>
<P>The general format is:</P>
common format to help make sorting and viewing properties more intuitive as to their use. See
the <A href="ThemingDeveloperDocs.html#Resource_Ids">Developer Documentation</A> for more details on the property id
format and naming conventions.</P>
<H2>Theme Files</H2>
<BLOCKQUOTE>
<BLOCKQUOTE>
[type].[category[...]].[client].[specialized uses]
<UL>
<LI><B>type:</B> color, font, or icon</LI>
<P>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:</P>
<CODE>
<PRE>
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]
...
</PRE>
</CODE>
<LI><B>category:</B> any value, examples include "bg" (background), "fg" (foreground);
this may be multiple separated values</LI>
<LI><B>client:</B> the plugin name or feature name; any value used to represent a more
specialized use</LI>
<LI><B>specialized uses:</B> any key value here that applies to the client, such as
"vertex" for a vertex background</LI>
</UL>Examples:
<UL>
<LI>color.bg</LI>
<LI>color.bg.listing</LI>
<LI>font.button</LI>
<LI>icon.refresh</LI>
<LI>icon.refresh.disabled</LI>
</UL>
</BLOCKQUOTE>
</BLOCKQUOTE>
<H2>Theme File Format</H2>
<BLOCKQUOTE>
<P>Saved theme files have the following format:</P>
<PRE>
<CODE class="code">
name = ThemeName
<BLOCKQUOTE>
<P>Example:</P>
<PRE>
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
</CODE>
</PRE>
</PRE>
<P>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.</P>
<P>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."</P>
<H3>Specifying Color Values</H3>
<H3>Specifying Theme Property Values</H3>
<P>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 <A href="ThemingDeveloperDocs.html#Theme_Property_Values">Developer Documentation</A>.
<P>To specify the value for a color, there are 3 acceptable formats:</P>
<UL>
<LI><B>Web Color Name</B> - Examples: Blue, Red, Black, etc.</LI>
<LI><B>Hex value</B> - #rrggbb, Example: #ff01a4, where ff is the red value, 01 is the
green value, and a4 is the blue value</LI>
<LI><B>Hex with alpha value</B> -Example: #ff01a480, where ff is the red value, 01 is the
green value, and a4 is the blue value, and 80 is the alpha value</LI>
<LI><B>RGB values</B> - Example: rgb(12, 34, 56) where red is 12(decimal), green is 34, and
blue is 56</LI>
<LI><B>RGBA values</B> - Eample: rgba(12, 34, 56, 127) where red is 12(decimal), green is
34, blue is 56, and alpha is 127</LI>
</UL>
<H3>Specifying Font Values</H3>
<P>Font values are specified as follows:</P>
<PRE>
familyName-style-size
</PRE>
<UL>
<LI><B>familyName:</B> the font family name such as "monospace", "dialog", "courier"</LI>
<LI><B>style:</B>either PLAIN, BOLD, ITALIC, or BOLDITALIC</LI>
<LI><B>size:</B> the font size such as 12, 14, 22</LI>
</UL>
<P>Examples: monospace-PLAIN-12 or courier-BOLD-15</P>
<H3>Specifying Icon Values</H3>
<P>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,</P>
<PRE>
icon.refresh = images/view-refresh.png
icon.push = [EXTERNAL]images/energy.png
</PRE>
<P>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.</P>
</BLOCKQUOTE>
<P class="relatedtopic">Related Topics</P>
<UL>
<LI><A href="ThemingOverview.html">Theming Overview</A></LI>
<LI><A href="ThemingDeveloperDocs.html">Theming Developer Documentation</A></LI>
<LI><A href="ThemingInternals.html">Theming Architecture Documentation</A></LI>
</UL><BR>
</BODY>
</HTML>
@@ -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.
@@ -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;
}
@@ -211,7 +211,7 @@ public class ToolIconURL implements Comparable<ToolIconURL> {
}
private ImageIcon getImageIcon(String name) {
ImageIcon image = ResourceManager.loadImage(name);
ImageIcon image = ResourceManager.findIcon(name);
if (image instanceof UnresolvedIcon) {
return null;
}

Before

Width:  |  Height:  |  Size: 305 B

After

Width:  |  Height:  |  Size: 305 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 848 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Before

Width:  |  Height:  |  Size: 709 B

After

Width:  |  Height:  |  Size: 709 B

Some files were not shown because too many files have changed in this diff Show More