diff --git a/Ghidra/Features/Base/src/main/help/help/TOC_Source.xml b/Ghidra/Features/Base/src/main/help/help/TOC_Source.xml index 076b46b713..757aa6bf19 100644 --- a/Ghidra/Features/Base/src/main/help/help/TOC_Source.xml +++ b/Ghidra/Features/Base/src/main/help/help/TOC_Source.xml @@ -67,6 +67,7 @@ + diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/VarnodeLocationCellEditor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/VarnodeLocationCellEditor.java index 293f5f88f4..a93be40e57 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/VarnodeLocationCellEditor.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/VarnodeLocationCellEditor.java @@ -15,7 +15,6 @@ */ package ghidra.app.plugin.core.function.editor; -import java.awt.Color; import java.awt.Component; import java.awt.event.*; import java.math.BigInteger; @@ -28,6 +27,7 @@ import javax.swing.table.TableCellEditor; import docking.widgets.combobox.GhidraComboBox; import docking.widgets.textfield.IntegerTextField; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.util.AddressInput; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressOutOfBoundsException; @@ -44,12 +44,7 @@ class VarnodeLocationCellEditor extends AbstractCellEditor implements TableCellE private AddressInput addressInput; private IntegerTextField offsetInput; - private Comparator registerWrapperComparator = new Comparator() { - @Override - public int compare(Register r1, Register r2) { - return r1.toString().compareToIgnoreCase(r2.toString()); - } - }; + private Comparator registerWrapperComparator = (r1, r2) -> r1.toString().compareToIgnoreCase(r2.toString()); private VarnodeInfo currentVarnode; private int maxRegisterSize; @@ -146,12 +141,7 @@ class VarnodeLocationCellEditor extends AbstractCellEditor implements TableCellE if (address != null) { addressInput.setAddress(address); } - addressInput.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - stopCellEditing(); - } - }); + addressInput.addActionListener(e -> stopCellEditing()); return addressInput; } @@ -162,14 +152,9 @@ class VarnodeLocationCellEditor extends AbstractCellEditor implements TableCellE if (address != null) { offsetInput.setValue(address.getOffset()); } - offsetInput.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - stopCellEditing(); - } - }); + offsetInput.addActionListener(e -> stopCellEditing()); JComponent component = offsetInput.getComponent(); - component.setBorder(BorderFactory.createLineBorder(Color.GRAY, 1)); + component.setBorder(BorderFactory.createLineBorder(Palette.GRAY, 1)); return component; } @@ -215,12 +200,7 @@ class VarnodeLocationCellEditor extends AbstractCellEditor implements TableCellE } }); - combo.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - stopCellEditing(); - } - }); + combo.addActionListener(e -> stopCellEditing()); return combo; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/VarnodeSizeCellEditor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/VarnodeSizeCellEditor.java index 0d6dabeaba..cf52210291 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/VarnodeSizeCellEditor.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/VarnodeSizeCellEditor.java @@ -15,7 +15,6 @@ */ package ghidra.app.plugin.core.function.editor; -import java.awt.Color; import java.awt.Component; import java.awt.event.*; import java.math.BigInteger; @@ -25,6 +24,7 @@ import javax.swing.*; import javax.swing.table.TableCellEditor; import docking.widgets.textfield.IntegerTextField; +import generic.theme.GThemeDefaults.Colors.Palette; class VarnodeSizeCellEditor extends AbstractCellEditor implements TableCellEditor { @@ -70,14 +70,9 @@ class VarnodeSizeCellEditor extends AbstractCellEditor implements TableCellEdito }; input.getComponent().addFocusListener(focusListener); } - input.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - stopCellEditing(); - } - }); + input.addActionListener(e -> stopCellEditing()); JComponent component = input.getComponent(); - component.setBorder(BorderFactory.createLineBorder(Color.GRAY, 1)); + component.setBorder(BorderFactory.createLineBorder(Palette.GRAY, 1)); return component; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/RegisterValuesPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/RegisterValuesPanel.java index bbdfc5b272..616d8f23ec 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/RegisterValuesPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/RegisterValuesPanel.java @@ -27,6 +27,7 @@ import javax.swing.*; import docking.widgets.OptionDialog; import docking.widgets.table.*; import generic.theme.GColor; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.cmd.register.SetRegisterCmd; import ghidra.app.events.ProgramSelectionPluginEvent; import ghidra.app.services.*; @@ -492,7 +493,7 @@ class RegisterValueRange { class RegisterValueRenderer extends GTableCellRenderer { - private Color defaultColor = Color.LIGHT_GRAY; + private Color defaultColor = Palette.LIGHT_GRAY; RegisterValueRenderer(JTable table) { setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AddressAnnotatedStringHandler.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AddressAnnotatedStringHandler.java index 736b3195e4..38623b1fd7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AddressAnnotatedStringHandler.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AddressAnnotatedStringHandler.java @@ -15,10 +15,9 @@ */ package ghidra.app.util.viewer.field; -import java.awt.Color; - import docking.widgets.fieldpanel.field.AttributedString; import generic.theme.GThemeDefaults.Colors.Messages; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.nav.Navigatable; import ghidra.app.services.GoToService; import ghidra.framework.plugintool.ServiceProvider; @@ -76,7 +75,7 @@ public class AddressAnnotatedStringHandler implements AnnotatedStringHandler { buffer.append(string).append(" "); } - return new AttributedString(buffer.toString(), Color.LIGHT_GRAY, + return new AttributedString(buffer.toString(), Palette.LIGHT_GRAY, prototypeString.getFontMetrics(0)); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/IndentField.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/IndentField.java index 080c574dfa..6446826ed4 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/IndentField.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/IndentField.java @@ -22,6 +22,7 @@ import javax.swing.JComponent; import docking.widgets.fieldpanel.internal.FieldBackgroundColorManager; import docking.widgets.fieldpanel.internal.PaintContext; import docking.widgets.fieldpanel.support.*; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.util.viewer.format.FieldFormatModel; import ghidra.app.util.viewer.proxy.EmptyProxy; import ghidra.app.util.viewer.proxy.ProxyObj; @@ -177,7 +178,7 @@ public class IndentField implements ListingField { public void paint(JComponent c, Graphics g, PaintContext context, Rectangle clip, FieldBackgroundColorManager map, RowColLocation cursorLoc, int rowHeight) { - g.setColor(Color.LIGHT_GRAY); + g.setColor(Palette.LIGHT_GRAY); // draw the vertical lines to the left of the data (these are shown when there are vertical // bars drawn for inset data) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/OpenCloseField.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/OpenCloseField.java index bdbd1069a4..8297462d28 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/OpenCloseField.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/OpenCloseField.java @@ -23,6 +23,7 @@ import javax.swing.JComponent; import docking.widgets.fieldpanel.internal.FieldBackgroundColorManager; import docking.widgets.fieldpanel.internal.PaintContext; import docking.widgets.fieldpanel.support.*; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.util.viewer.format.FieldFormatModel; import ghidra.app.util.viewer.proxy.EmptyProxy; import ghidra.app.util.viewer.proxy.ProxyObj; @@ -176,7 +177,7 @@ public class OpenCloseField implements ListingField { } } - g.setColor(Color.LIGHT_GRAY); + g.setColor(Palette.LIGHT_GRAY); // draw the vertical lines to the left of the toggle handle (these are shown when // there are vertical bars drawn for inset data) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/listingpanel/ListingCodeComparisonPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/listingpanel/ListingCodeComparisonPanel.java index 43d49381e4..ddf2519d71 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/listingpanel/ListingCodeComparisonPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/listingpanel/ListingCodeComparisonPanel.java @@ -35,6 +35,7 @@ import docking.widgets.fieldpanel.internal.FieldPanelCoordinator; import docking.widgets.fieldpanel.listener.FieldLocationListener; import docking.widgets.fieldpanel.support.FieldLocation; import docking.widgets.fieldpanel.support.ViewerPosition; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.GhidraOptions; import ghidra.app.nav.Navigatable; import ghidra.app.plugin.core.codebrowser.MarkerServiceBackgroundColorModel; @@ -72,6 +73,8 @@ public class ListingCodeComparisonPanel extends CodeComparisonPanel implements FormatModelListener, CodeFormatService, ListingDiffChangeListener, OptionsChangeListener { + private static final Color FG_COLOR_TITLE = Palette.DARK_GRAY; + private static final String DUAL_LISTING_HEADER_SHOWING = "DUAL_LISTING_HEADER_SHOWING"; private static final String DUAL_LISTING_SIDE_BY_SIDE = "DUAL_LISTING_SIDE_BY_SIDE"; public static final String NAME = "DualListing"; @@ -1406,7 +1409,7 @@ public class ListingCodeComparisonPanel String programStr = HTMLUtilities.friendlyEncodeHTML(program.getDomainFile().getPathname()); - String specialProgramStr = HTMLUtilities.colorString(Color.DARK_GRAY, programStr); + String specialProgramStr = HTMLUtilities.colorString(FG_COLOR_TITLE, programStr); buf.append(specialProgramStr); buf.append(padStr); } @@ -1441,7 +1444,7 @@ public class ListingCodeComparisonPanel String programStr = HTMLUtilities.friendlyEncodeHTML(program.getDomainFile().getPathname()); - String specialProgramStr = HTMLUtilities.colorString(Color.DARK_GRAY, programStr); + String specialProgramStr = HTMLUtilities.colorString(FG_COLOR_TITLE, programStr); buf.append(specialProgramStr); buf.append(padStr); } @@ -1461,7 +1464,7 @@ public class ListingCodeComparisonPanel String padStr = HTMLUtilities.spaces(4); buf.append(padStr); String programStr = HTMLUtilities.friendlyEncodeHTML(program.getDomainFile().getPathname()); - String specialProgramStr = HTMLUtilities.colorString(Color.DARK_GRAY, programStr); + String specialProgramStr = HTMLUtilities.colorString(FG_COLOR_TITLE, programStr); buf.append(specialProgramStr); buf.append(padStr); return HTMLUtilities.wrapAsHTML(buf.toString()); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/FunctionsXmlMgr.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/FunctionsXmlMgr.java index d5887d3869..fca8dacd82 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/FunctionsXmlMgr.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/FunctionsXmlMgr.java @@ -15,11 +15,11 @@ */ package ghidra.app.util.xml; -import java.awt.Color; import java.util.*; import javax.swing.ImageIcon; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.cmd.function.*; import ghidra.app.services.DataTypeManagerService; import ghidra.app.util.NamespaceUtils; @@ -129,7 +129,8 @@ class FunctionsXmlMgr { if (bt == null) { ImageIcon icon = ResourceManager.loadImage("images/imported_bookmark.gif"); - bt = bm.defineType("IMPORTED", icon, Color.DARK_GRAY, 0); + bt = bm.defineType("IMPORTED", icon, Palette.DARK_GRAY, + 0); } bm.setBookmark(entryPoint, "IMPORTED", LIB_BOOKMARK_CATEGORY, "Library function"); @@ -680,7 +681,7 @@ class FunctionsXmlMgr { private Parameter[] getRegisterParameters(Function function) { - ArrayList list = new ArrayList(); + ArrayList list = new ArrayList<>(); Parameter[] params = function.getParameters(); for (Parameter param : params) { if (param.isRegisterVariable()) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/util/FunctionUtility.java b/Ghidra/Features/Base/src/main/java/ghidra/program/util/FunctionUtility.java index 0d100f86d9..cd86c27bff 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/program/util/FunctionUtility.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/program/util/FunctionUtility.java @@ -15,9 +15,9 @@ */ package ghidra.program.util; -import java.awt.Color; import java.util.*; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.program.model.address.Address; import ghidra.program.model.data.DataType; import ghidra.program.model.data.GenericCallingConvention; @@ -381,7 +381,7 @@ public class FunctionUtility { String programStr = HTMLUtilities.friendlyEncodeHTML(program.getDomainFile().getPathname()); - String specialProgramStr = HTMLUtilities.colorString(Color.DARK_GRAY, programStr); + String specialProgramStr = HTMLUtilities.colorString(Palette.DARK_GRAY, programStr); buf.append(specialProgramStr); buf.append(padStr); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/util/table/field/MemoryTypeProgramLocationBasedTableColumn.java b/Ghidra/Features/Base/src/main/java/ghidra/util/table/field/MemoryTypeProgramLocationBasedTableColumn.java index 996fae5b6e..48e46aed32 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/util/table/field/MemoryTypeProgramLocationBasedTableColumn.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/util/table/field/MemoryTypeProgramLocationBasedTableColumn.java @@ -23,6 +23,7 @@ import javax.swing.ImageIcon; import javax.swing.JLabel; import docking.widgets.table.GTableCellRenderingData; +import generic.theme.GThemeDefaults.Colors; import ghidra.docking.settings.Settings; import ghidra.framework.plugintool.ServiceProvider; import ghidra.program.model.listing.Program; @@ -75,7 +76,7 @@ public class MemoryTypeProgramLocationBasedTableColumn private class MemoryTypeRenderer extends AbstractGhidraColumnRenderer { - private Color disabledColor = Color.LIGHT_GRAY; + private Color disabledColor = Colors.DISABLED; private ImageIcon offIcon = ResourceManager.loadImage("images/EmptyIcon16.gif"); private ImageIcon onIcon = ResourceManager.loadImage("images/check.png"); diff --git a/Ghidra/Features/Base/src/main/java/help/screenshot/GhidraScreenShotGenerator.java b/Ghidra/Features/Base/src/main/java/help/screenshot/GhidraScreenShotGenerator.java index 21f04775de..8a298ec967 100644 --- a/Ghidra/Features/Base/src/main/java/help/screenshot/GhidraScreenShotGenerator.java +++ b/Ghidra/Features/Base/src/main/java/help/screenshot/GhidraScreenShotGenerator.java @@ -38,6 +38,14 @@ import ghidra.framework.main.FrontEndTool; import ghidra.util.Msg; import ghidra.util.exception.AssertException; +/** + * Extend this class to create screen shot images for help. The name of the class determines the + * topic directory where the captured image will be stored. So if the class name is + * XyzShreenShots, the resulting captured image will appear in help topic directy "Xyz", regardless + * of which module has that topic. The test name will determine the name of the image file + * that is generated. So if the test name is testHappyBirthday, the filename will be + * HappyBirthday.png. + */ public abstract class GhidraScreenShotGenerator extends AbstractScreenShotGenerator { private static final Color FG_COLOR_TEXT = Palette.getColor("color.palate.cornflowerblue"); diff --git a/Ghidra/Features/BytePatterns/src/main/java/ghidra/bitpatterns/gui/ByteSequenceAnalyzerProvider.java b/Ghidra/Features/BytePatterns/src/main/java/ghidra/bitpatterns/gui/ByteSequenceAnalyzerProvider.java index ce17de6f98..dee5126f7a 100644 --- a/Ghidra/Features/BytePatterns/src/main/java/ghidra/bitpatterns/gui/ByteSequenceAnalyzerProvider.java +++ b/Ghidra/Features/BytePatterns/src/main/java/ghidra/bitpatterns/gui/ByteSequenceAnalyzerProvider.java @@ -25,6 +25,8 @@ import docking.*; import docking.action.DockingAction; import docking.action.MenuData; import docking.widgets.table.GFilterTable; +import generic.theme.GColor; +import generic.theme.GThemeDefaults.Colors; import ghidra.bitpatterns.info.*; import ghidra.util.HelpLocation; import ghidra.util.bytesearch.DittedBitSequence; @@ -35,6 +37,8 @@ import resources.ResourceManager; */ public abstract class ByteSequenceAnalyzerProvider extends DialogComponentProvider { + private static final Color BG_DISABLED = new GColor("color.bg.uneditable"); + protected ByteSequenceTableModel byteSequenceTable; protected FunctionBitPatternsExplorerPlugin plugin; protected JPanel mainPanel; @@ -175,9 +179,9 @@ public abstract class ByteSequenceAnalyzerProvider extends DialogComponentProvid } mergedSeqTextField.setText(merged.getHexString()); bitsOfCheckField.setText(Integer.toString(merged.getNumFixedBits())); - mergedSeqTextField.setBackground(Color.WHITE); - bitsOfCheckField.setBackground(Color.WHITE); - noteField.setBackground(Color.WHITE); + mergedSeqTextField.setBackground(Colors.BACKGROUND); + bitsOfCheckField.setBackground(Colors.BACKGROUND); + noteField.setBackground(Colors.BACKGROUND); mergedToSend = true; } @@ -211,9 +215,9 @@ public abstract class ByteSequenceAnalyzerProvider extends DialogComponentProvid mergedInfo.setNote(note); plugin.addPattern(mergedInfo); plugin.updateClipboard(); - mergedSeqTextField.setBackground(Color.lightGray); - bitsOfCheckField.setBackground(Color.LIGHT_GRAY); - noteField.setBackground(Color.LIGHT_GRAY); + mergedSeqTextField.setBackground(BG_DISABLED); + bitsOfCheckField.setBackground(BG_DISABLED); + noteField.setBackground(BG_DISABLED); mergedToSend = false; } } diff --git a/Ghidra/Features/ByteViewer/data/byteviewer.theme.properties b/Ghidra/Features/ByteViewer/data/byteviewer.theme.properties index 30ee3e4c8f..bdf0b37724 100644 --- a/Ghidra/Features/ByteViewer/data/byteviewer.theme.properties +++ b/Ghidra/Features/ByteViewer/data/byteviewer.theme.properties @@ -1,6 +1,7 @@ [Defaults] color.bg.byteviewer = color.bg +color.bg.byteviewer.highlight = yellow color.fg.byteviewer.novalue = blue color.fg.byteviewer.changed = red @@ -8,7 +9,12 @@ color.cursor.focused.byteviewer.current = color.cursor.focused color.cursor.focused.byteviewer.noncurrent = black color.cursor.unfocused.byteviewer = color.cursor.unfocused + + [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 diff --git a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerComponent.java b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerComponent.java index f9eaf80da4..b798f81677 100644 --- a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerComponent.java +++ b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerComponent.java @@ -29,6 +29,7 @@ import docking.widgets.fieldpanel.Layout; import docking.widgets.fieldpanel.field.Field; import docking.widgets.fieldpanel.listener.*; import docking.widgets.fieldpanel.support.*; +import generic.theme.GColor; import ghidra.app.plugin.core.format.*; import ghidra.program.model.address.*; import ghidra.util.Msg; @@ -885,7 +886,7 @@ public class ByteViewerComponent extends FieldPanel implements FieldMouseListene private class ByteViewerBackgroundColorModel implements BackgroundColorModel { - private Color defaultBackgroundColor = Color.WHITE; + private Color defaultBackgroundColor = new GColor("color.bg.byteviewer"); @Override public Color getBackgroundColor(BigInteger index) { diff --git a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerHighlightProvider.java b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerHighlightProvider.java index d26bf8f0b2..0b85bed4c5 100644 --- a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerHighlightProvider.java +++ b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerHighlightProvider.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,18 +15,19 @@ */ package ghidra.app.plugin.core.byteviewer; -import ghidra.app.util.HighlightProvider; -import ghidra.app.util.viewer.field.FieldFactory; - import java.awt.Color; import docking.widgets.fieldpanel.support.Highlight; +import generic.theme.GColor; +import ghidra.app.util.HighlightProvider; +import ghidra.app.util.viewer.field.FieldFactory; public class ByteViewerHighlightProvider implements HighlightProvider { private static Highlight[] NO_HIGHLIGHTS = new Highlight[0]; private String highlightText; - private Color highlightColor = Color.YELLOW; + private Color highlightColor = new GColor("color.bg.byteviewer.highlight"); + @Override public Highlight[] getHighlights(String text, Object obj, Class fieldFactoryClass, int cursorTextOffset) { diff --git a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerOptionsDialog.java b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerOptionsDialog.java index f6c9f7e581..3a53335d29 100644 --- a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerOptionsDialog.java +++ b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerOptionsDialog.java @@ -15,12 +15,12 @@ */ package ghidra.app.plugin.core.byteviewer; -import java.awt.*; +import java.awt.Component; +import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.math.BigInteger; import java.util.*; -import java.util.List; import java.util.Map.Entry; import javax.swing.*; @@ -31,6 +31,8 @@ import javax.swing.event.ChangeListener; import docking.DialogComponentProvider; import docking.widgets.checkbox.GCheckBox; import docking.widgets.label.GLabel; +import generic.theme.GThemeDefaults.Colors; +import generic.theme.GThemeDefaults.Colors.Messages; import ghidra.app.plugin.core.format.ByteBlockSelection; import ghidra.app.plugin.core.format.DataFormatModel; import ghidra.app.util.AddressInput; @@ -266,10 +268,10 @@ public class ByteViewerOptionsDialog extends DialogComponentProvider JCheckBox checkBox = entry.getValue(); DataFormatModel model = provider.getDataFormatModel(entry.getKey()); if (model.validateBytesPerLine(bytesPerLine)) { - checkBox.setForeground(Color.BLACK); + checkBox.setForeground(Colors.FOREGROUND); } else { - checkBox.setForeground(Color.RED); + checkBox.setForeground(Messages.ERROR); isBad |= checkBox.isSelected(); } } diff --git a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerPanel.java b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerPanel.java index a07e014a22..84bc547ca6 100644 --- a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerPanel.java +++ b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerPanel.java @@ -23,7 +23,6 @@ import java.util.List; import javax.swing.*; import javax.swing.event.*; -import docking.help.HelpService; import docking.widgets.fieldpanel.*; import docking.widgets.fieldpanel.field.EmptyTextField; import docking.widgets.fieldpanel.field.Field; @@ -43,6 +42,7 @@ import ghidra.util.exception.InvalidInputException; import ghidra.util.layout.HorizontalLayout; import ghidra.util.layout.PairLayout; import help.Help; +import help.HelpService; /** * Top level component that contains has a scrolled pane for the panel of components that show the diff --git a/Ghidra/Features/ByteViewer/src/test.slow/java/ghidra/app/plugin/core/byteviewer/ByteViewerPlugin2Test.java b/Ghidra/Features/ByteViewer/src/test.slow/java/ghidra/app/plugin/core/byteviewer/ByteViewerPlugin2Test.java index a0962a6022..dc98e794e5 100644 --- a/Ghidra/Features/ByteViewer/src/test.slow/java/ghidra/app/plugin/core/byteviewer/ByteViewerPlugin2Test.java +++ b/Ghidra/Features/ByteViewer/src/test.slow/java/ghidra/app/plugin/core/byteviewer/ByteViewerPlugin2Test.java @@ -34,6 +34,7 @@ import docking.action.DockingActionIf; import docking.action.ToggleDockingAction; import docking.widgets.EventTrigger; import docking.widgets.fieldpanel.support.*; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin; import ghidra.app.plugin.core.format.*; import ghidra.app.plugin.core.navigation.*; @@ -1215,10 +1216,10 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { Options opt = tool.getOptions("ByteViewer"); // change the color for Current View Cursor Color - putColor(opt, ByteViewerComponentProvider.OPTION_CURRENT_VIEW_CURSOR_COLOR, Color.GREEN); + putColor(opt, ByteViewerComponentProvider.OPTION_CURRENT_VIEW_CURSOR_COLOR, Palette.GREEN); ByteViewerComponent c = panel.getCurrentComponent(); - assertEquals(Color.GREEN, c.getFocusedCursorColor()); + assertEquals(Palette.GREEN, c.getFocusedCursorColor()); } @Test @@ -1235,10 +1236,10 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { Options opt = tool.getOptions("ByteViewer"); // change the color for Current View Cursor Color - putColor(opt, ByteViewerComponentProvider.OPTION_CURSOR_COLOR, Color.GREEN); + putColor(opt, ByteViewerComponentProvider.OPTION_CURSOR_COLOR, Palette.GREEN); ByteViewerComponent c = findComponent(panel, "Octal"); - assertEquals(Color.GREEN, c.getNonFocusCursorColor()); + assertEquals(Palette.GREEN, c.getNonFocusCursorColor()); } @Test @@ -1254,10 +1255,10 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { Options opt = tool.getOptions("ByteViewer"); // change the color for Current View Cursor Color - putColor(opt, ByteViewerComponentProvider.OPTION_NONFOCUS_CURSOR_COLOR, Color.CYAN); + putColor(opt, ByteViewerComponentProvider.OPTION_NONFOCUS_CURSOR_COLOR, Palette.CYAN); ByteViewerComponent c = findComponent(panel, "Octal"); - assertEquals(Color.CYAN, c.getNonFocusCursorColor()); + assertEquals(Palette.CYAN, c.getNonFocusCursorColor()); } private void putFont(final Options options, final String optionName, final Font font) { @@ -1282,7 +1283,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { Options opt = tool.getOptions("ByteViewer"); // change the color for Edit Color - putColor(opt, ByteViewerComponentProvider.OPTION_EDIT_COLOR, Color.GREEN); + putColor(opt, ByteViewerComponentProvider.OPTION_EDIT_COLOR, Palette.GREEN); final FieldLocation loc = getFieldLocation(getAddr(0x01001000)); SwingUtilities.invokeAndWait(() -> { @@ -1302,7 +1303,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { program.flushEvents(); ByteViewerComponent c = panel.getCurrentComponent(); ByteField field = c.getField(loc.getIndex(), loc.getFieldNum()); - assertEquals(Color.GREEN, field.getForeground()); + assertEquals(Palette.GREEN, field.getForeground()); } @Test @@ -1340,12 +1341,12 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { Options opt = tool.getOptions("ByteViewer"); // change the color for block separator - putColor(opt, ByteViewerComponentProvider.OPTION_SEPARATOR_COLOR, Color.GREEN); + putColor(opt, ByteViewerComponentProvider.OPTION_SEPARATOR_COLOR, Palette.GREEN); ByteViewerComponent c = panel.getCurrentComponent(); FieldLocation loc = getFieldLocation(getAddr(0x0f001000)); ByteField field = c.getField(loc.getIndex().subtract(BigInteger.ONE), 0); - assertEquals(Color.GREEN, field.getForeground()); + assertEquals(Palette.GREEN, field.getForeground()); } @Test diff --git a/Ghidra/Features/Decompiler/data/decompiler.theme.properties b/Ghidra/Features/Decompiler/data/decompiler.theme.properties index d1cb359e89..2fe01e4b15 100644 --- a/Ghidra/Features/Decompiler/data/decompiler.theme.properties +++ b/Ghidra/Features/Decompiler/data/decompiler.theme.properties @@ -1,10 +1,12 @@ [Defaults] + color.bg.decompiler = color.bg color.fg.decompiler = color.fg color.fg.decompiler.keyword = #0001e6 color.fg.decompiler.function.name = blue color.fg.decompiler.comment = blueViolet +color.fg.decompiler.error = crimson color.fg.decompiler.variable = #999900 // close to oliveDrab color.fg.decompiler.constant = forestGreen color.fg.decompiler.type = mediumBlue @@ -37,6 +39,7 @@ color.bg.decompiler.pcode.dfg.edge.between.blocks = red color.fg.decompiler.keyword = peru color.fg.decompiler.function.name = cadetBlue color.fg.decompiler.comment = lightSlateGray +color.fg.decompiler.error = crimson color.fg.decompiler.variable = #999900 // close to oliveDrab color.fg.decompiler.constant = forestGreen color.fg.decompiler.type = blue diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileOptions.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileOptions.java index 889b9348dc..b9f026dab5 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileOptions.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileOptions.java @@ -354,7 +354,7 @@ public class DecompileOptions { private Color defaultSearchHighlightColor = SEARCH_HIGHLIGHT_DEF; // Color applied to a token to indicate warning/error - private final static Color ERROR_COLOR = new Color(204, 0, 51); // Dark Red + private final static Color ERROR_COLOR = new GColor("color.fg.decompiler.comment"); final static String FONT_MSG = "Display.Font"; final static Font DEFAULT_FONT = new Font(Font.MONOSPACED, Font.PLAIN, 12); diff --git a/Ghidra/Features/FunctionGraph/src/test.slow/java/ghidra/app/plugin/core/functiongraph/FunctionGraphGroupVertices1Test.java b/Ghidra/Features/FunctionGraph/src/test.slow/java/ghidra/app/plugin/core/functiongraph/FunctionGraphGroupVertices1Test.java index d42fcd6a24..793f4d9906 100644 --- a/Ghidra/Features/FunctionGraph/src/test.slow/java/ghidra/app/plugin/core/functiongraph/FunctionGraphGroupVertices1Test.java +++ b/Ghidra/Features/FunctionGraph/src/test.slow/java/ghidra/app/plugin/core/functiongraph/FunctionGraphGroupVertices1Test.java @@ -436,7 +436,7 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest { // The coloring algorithm: // 1) If the grouped vertices are not colored, then use the default group color // 2) If the grouped vertices are colored, but not all the same color, - // then use the default group color= + // then use the default group color // 3) If all grouped vertices share the same color, then make the group that color // // This test is for 1) @@ -472,7 +472,7 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest { // The coloring algorithm: // 1) If the grouped vertices are not colored, then use the default group color // 2) If the grouped vertices are colored, but not all the same color, - // then use the default group color= + // then use the default group color // 3) If all grouped vertices share the same color, then make the group that color // // This test is for 2) @@ -514,7 +514,7 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest { // The coloring algorithm: // 1) If the grouped vertices are not colored, then use the default group color // 2) If the grouped vertices are colored, but not all the same color, - // then use the default group color= + // then use the default group color // 3) If all grouped vertices share the same color, then make the group that color // // This test is for 3) diff --git a/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/FcgVertex.java b/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/FcgVertex.java index 76fe8770d0..e69ca9448c 100644 --- a/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/FcgVertex.java +++ b/Ghidra/Features/GraphFunctionCalls/src/main/java/functioncalls/graph/FcgVertex.java @@ -29,8 +29,8 @@ import javax.swing.border.LineBorder; import docking.widgets.EmptyBorderButton; import docking.widgets.label.GDLabel; import generic.theme.GColor; -import generic.theme.Gui; import generic.theme.GThemeDefaults.Colors.Palette; +import generic.theme.Gui; import ghidra.graph.viewer.vertex.AbstractVisualVertex; import ghidra.graph.viewer.vertex.VertexShapeProvider; import ghidra.program.model.address.Address; @@ -250,7 +250,7 @@ public class FcgVertex extends AbstractVisualVertex implements VertexShapeProvid compactShape = (Double) vertexShape.clone(); vertexImageLabel.setIcon(new ImageIcon(image)); - Border border = createDebugBorder(new LineBorder(Color.PINK, 1)); + Border border = createDebugBorder(new LineBorder(Palette.PINK, 1)); vertexImageLabel.setBorder(border); } @@ -299,7 +299,7 @@ public class FcgVertex extends AbstractVisualVertex implements VertexShapeProvid private void addNameLabel() { - Border border = createDebugBorder(new LineBorder(Color.GREEN, 1)); + Border border = createDebugBorder(new LineBorder(Palette.GREEN, 1)); nameLabel.setBorder(border); // assume the vertex label has been bounded diff --git a/Ghidra/Features/GraphFunctionCalls/src/screen/java/help/screenshot/FunctionCallGraphPluginScreenShots.java b/Ghidra/Features/GraphFunctionCalls/src/screen/java/help/screenshot/FunctionCallGraphPluginScreenShots.java index ea448159ba..3750614fd2 100644 --- a/Ghidra/Features/GraphFunctionCalls/src/screen/java/help/screenshot/FunctionCallGraphPluginScreenShots.java +++ b/Ghidra/Features/GraphFunctionCalls/src/screen/java/help/screenshot/FunctionCallGraphPluginScreenShots.java @@ -116,7 +116,7 @@ public class FunctionCallGraphPluginScreenShots extends GhidraScreenShotGenerato area.width += (2 * offset); area.height += (2 * offset); - // drawRectangle(Color.ORANGE, area, 5); + // drawRectangle(Palette.ORANGE, area, 5); crop(area); } diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/AttributeFilters.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/AttributeFilters.java index 8112de9a9c..5c41fb824f 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/AttributeFilters.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/AttributeFilters.java @@ -30,6 +30,7 @@ import javax.swing.event.EventListenerList; import com.google.common.collect.HashMultiset; import com.google.common.collect.Multiset; +import generic.theme.GThemeDefaults.Colors; import ghidra.service.graph.Attributed; /** @@ -60,8 +61,7 @@ public class AttributeFilters implements ItemSelectable { /** * a {@link Function} to allow custom coloring of the individual toolkit button foreground */ - private Function paintFunction = v -> Color.black; - + private Function paintFunction = v -> Colors.FOREGROUND; /** * @param excluded ignored keys diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java index 2af1108588..ad1dedf0e0 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java @@ -53,6 +53,7 @@ import docking.options.editor.OptionsDialog; import docking.widgets.EventTrigger; import docking.widgets.OptionDialog; import generic.theme.GColor; +import generic.theme.GThemeDefaults.Colors; import generic.util.WindowUtilities; import ghidra.framework.options.Options; import ghidra.framework.options.ToolOptions; @@ -1025,7 +1026,7 @@ public class DefaultGraphDisplay implements GraphDisplay { .elements(vertices) .maxFactor(.05) .buttonSupplier(JRadioButton::new) - .paintFunction(v -> Color.BLACK) + .paintFunction(v -> Colors.FOREGROUND) .build(); vertexFilters.addItemListener(item -> { @@ -1043,7 +1044,7 @@ public class DefaultGraphDisplay implements GraphDisplay { .elements(edges) .maxFactor(.01) .buttonSupplier(JRadioButton::new) - .paintFunction(e -> Color.BLACK) + .paintFunction(e -> Colors.FOREGROUND) .build(); edgeFilters.addItemListener(item -> { diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphRenderer.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphRenderer.java index a4bf465f4b..5cee638e1d 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphRenderer.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphRenderer.java @@ -37,6 +37,7 @@ import org.jungrapht.visualization.renderers.Renderer; import org.jungrapht.visualization.renderers.Renderer.VertexLabel.Position; import org.jungrapht.visualization.util.RectangleUtils; +import generic.theme.GThemeDefaults.Colors; import generic.util.image.ImageUtils; import ghidra.service.graph.*; import ghidra.util.HTMLUtilities; @@ -78,8 +79,8 @@ public class DefaultGraphRenderer implements GraphRenderer { this.options = options; renderingHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); label = new JLabel(); - label.setForeground(Color.black); - label.setBackground(Color.white); + label.setForeground(Colors.FOREGROUND); + label.setBackground(Colors.BACKGROUND); label.setOpaque(false); Border marginBorder = BorderFactory.createEmptyBorder(labelBorderSize, 2 * labelBorderSize, labelBorderSize, 2 * labelBorderSize); @@ -163,7 +164,7 @@ public class DefaultGraphRenderer implements GraphRenderer { } renderContext.setVertexFontFunction(this::getFont); - renderContext.setVertexLabelRenderer(new JLabelVertexLabelRenderer(Color.black)); + renderContext.setVertexLabelRenderer(new JLabelVertexLabelRenderer(Colors.FOREGROUND)); renderContext.setVertexDrawPaintFunction(this::getVertexColor); renderContext.setVertexFillPaintFunction(this::getVertexColor); renderContext.setVertexStrokeFunction(n -> new BasicStroke(3.0f)); @@ -290,7 +291,7 @@ public class DefaultGraphRenderer implements GraphRenderer { // shapes are centered at the origin, so translate the graphics to compensate graphics.translate(-bounds.x + strokeThickness, -bounds.y + strokeThickness); - graphics.setPaint(Color.WHITE); + graphics.setPaint(Colors.BACKGROUND); graphics.fill(scaledShape); graphics.setPaint(vertexColor); graphics.setStroke(new BasicStroke(strokeThickness)); @@ -304,7 +305,7 @@ public class DefaultGraphRenderer implements GraphRenderer { int yOffset = (int) ((iconHeight - label.getHeight()) * labelOffsetRatio); graphics.translate(xOffset, yOffset); - graphics.setPaint(Color.black); + graphics.setPaint(Colors.FOREGROUND); label.paint(graphics); graphics.setTransform(graphicsTransform); // restore the original transform diff --git a/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/ui/LoadPdbDialog.java b/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/ui/LoadPdbDialog.java index 4ce9f5d536..1255151e9c 100644 --- a/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/ui/LoadPdbDialog.java +++ b/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/ui/LoadPdbDialog.java @@ -42,6 +42,7 @@ import docking.widgets.label.GLabel; import docking.widgets.textfield.HexOrDecimalInput; import docking.widgets.textfield.HintTextField; import generic.theme.GThemeDefaults.Colors; +import generic.theme.GThemeDefaults.Colors.Messages; import generic.theme.TempColorUtils; import ghidra.app.util.bin.format.pdb.PdbParser; import ghidra.app.util.bin.format.pdb2.pdbreader.PdbIdentifiers; @@ -910,7 +911,7 @@ public class LoadPdbDialog extends DialogComponentProvider { } Graphics2D g2 = (Graphics2D) g; - g2.setColor(hintColor != null ? hintColor : Color.LIGHT_GRAY); + g2.setColor(hintColor != null ? hintColor : Messages.HINT); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); Dimension size = getSize(); diff --git a/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/ProgramDiffPlugin.java b/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/ProgramDiffPlugin.java index 1ac4dac656..9f92c21017 100644 --- a/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/ProgramDiffPlugin.java +++ b/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/ProgramDiffPlugin.java @@ -26,7 +26,6 @@ import javax.swing.text.*; import javax.swing.tree.TreeSelectionModel; import docking.DockingUtils; -import docking.help.HelpService; import docking.widgets.EventTrigger; import docking.widgets.OptionDialog; import docking.widgets.fieldpanel.FieldPanel; @@ -63,6 +62,7 @@ import ghidra.util.exception.CancelledException; import ghidra.util.exception.VersionException; import ghidra.util.task.*; import help.Help; +import help.HelpService; import resources.ResourceManager; /** diff --git a/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffTestAdapter.java b/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffTestAdapter.java index 95d9bbbf56..ac7f16fff2 100644 --- a/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffTestAdapter.java +++ b/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffTestAdapter.java @@ -33,6 +33,7 @@ import docking.action.ToggleDockingAction; import docking.tool.ToolConstants; import docking.widgets.fieldpanel.FieldPanel; import generic.test.AbstractGenericTest; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.events.ProgramLocationPluginEvent; import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin; import ghidra.app.plugin.core.marker.MarkerManagerPlugin; @@ -271,10 +272,10 @@ public class DiffTestAdapter extends AbstractGhidraHeadedIntegrationTest { builder.setIntProperty("10018ff", "Space", 1); builder.setIntProperty("100248c", "Space", 1); - builder.setObjectProperty("100248c", "testColor", new SaveableColor(Color.CYAN)); - builder.setObjectProperty("10039dd", "testColor", new SaveableColor(Color.BLACK)); - builder.setObjectProperty("10039f8", "testColor", new SaveableColor(Color.BLACK)); - builder.setObjectProperty("10039fe", "testColor", new SaveableColor(Color.RED)); + builder.setObjectProperty("100248c", "testColor", new SaveableColor(Palette.CYAN)); + builder.setObjectProperty("10039dd", "testColor", new SaveableColor(Palette.BLACK)); + builder.setObjectProperty("10039f8", "testColor", new SaveableColor(Palette.BLACK)); + builder.setObjectProperty("10039fe", "testColor", new SaveableColor(Palette.RED)); AbstractGenericTest.setInstanceField("recordChanges", builder.getProgram(), Boolean.TRUE); @@ -450,10 +451,10 @@ public class DiffTestAdapter extends AbstractGhidraHeadedIntegrationTest { builder.setIntProperty("1002428", "Space", 1); builder.setIntProperty("100248c", "Space", 1); - builder.setObjectProperty("100248c", "testColor", new SaveableColor(Color.WHITE)); - builder.setObjectProperty("10039f1", "testColor", new SaveableColor(Color.BLACK)); - builder.setObjectProperty("10039f8", "testColor", new SaveableColor(Color.BLACK)); - builder.setObjectProperty("10039fe", "testColor", new SaveableColor(Color.GREEN)); + builder.setObjectProperty("100248c", "testColor", new SaveableColor(Palette.WHITE)); + builder.setObjectProperty("10039f1", "testColor", new SaveableColor(Palette.BLACK)); + builder.setObjectProperty("10039f8", "testColor", new SaveableColor(Palette.BLACK)); + builder.setObjectProperty("10039fe", "testColor", new SaveableColor(Palette.GREEN)); AbstractGenericTest.setInstanceField("recordChanges", builder.getProgram(), Boolean.TRUE); diff --git a/Ghidra/Features/Python/certification.manifest b/Ghidra/Features/Python/certification.manifest index bbb9356524..412c40104c 100644 --- a/Ghidra/Features/Python/certification.manifest +++ b/Ghidra/Features/Python/certification.manifest @@ -2,6 +2,7 @@ ##MODULE IP: Jython License ##MODULE IP: LGPL 2.1 Module.manifest||GHIDRA||||END| +data/python.theme.properties||GHIDRA||||END| src/main/help/help/TOC_Source.xml||GHIDRA||||END| src/main/help/help/topics/Python/images/erase16.png||GHIDRA||||END| src/main/help/help/topics/Python/interpreter.html||GHIDRA||||END| diff --git a/Ghidra/Features/Python/data/python.theme.properties b/Ghidra/Features/Python/data/python.theme.properties new file mode 100644 index 0000000000..908b10a737 --- /dev/null +++ b/Ghidra/Features/Python/data/python.theme.properties @@ -0,0 +1,19 @@ + +[Defaults] + +color.fg.plugin.python.syntax.class = blue +color.fg.plugin.python.syntax.code = darkgreen +color.fg.plugin.python.syntax.function = green +color.fg.plugin.python.syntax.instance = purple +color.fg.plugin.python.syntax.map = steelblue +color.fg.plugin.python.syntax.method = teal +color.fg.plugin.python.syntax.null = red +color.fg.plugin.python.syntax.number = darkgray +color.fg.plugin.python.syntax.package = darkred +color.fg.plugin.python.syntax.sequence = rbg(128, 96, 64) +color.fg.plugin.python.syntax.special = darkgreen + + + +[Dark Defaults] + diff --git a/Ghidra/Features/Python/src/main/java/ghidra/python/PythonCodeCompletionFactory.java b/Ghidra/Features/Python/src/main/java/ghidra/python/PythonCodeCompletionFactory.java index 5e254f8efc..6943b2cbd2 100644 --- a/Ghidra/Features/Python/src/main/java/ghidra/python/PythonCodeCompletionFactory.java +++ b/Ghidra/Features/Python/src/main/java/ghidra/python/PythonCodeCompletionFactory.java @@ -25,6 +25,7 @@ import org.python.core.PyInstance; import org.python.core.PyObject; import docking.widgets.label.GDLabel; +import generic.theme.GColor; import ghidra.app.plugin.core.console.CodeCompletion; import ghidra.framework.options.Options; import ghidra.util.Msg; @@ -57,19 +58,21 @@ public class PythonCodeCompletionFactory { private final static boolean INCLUDE_TYPES_DEFAULT = true; private static boolean includeTypes = INCLUDE_TYPES_DEFAULT; - public static final Color NULL_COLOR = new Color(255, 0, 0); - public static final Color FUNCTION_COLOR = new Color(0, 128, 0); - public static final Color PACKAGE_COLOR = new Color(128, 0, 0); - public static final Color CLASS_COLOR = new Color(0, 0, 255); - public static final Color METHOD_COLOR = new Color(0, 128, 128); + //@formatter:off + public static final Color NULL_COLOR = new GColor("color.fg.plugin.python.syntax.null"); + public static final Color FUNCTION_COLOR = new GColor("color.fg.plugin.python.syntax.function"); + public static final Color PACKAGE_COLOR = new GColor("color.fg.plugin.python.syntax.package"); + public static final Color CLASS_COLOR = new GColor("color.fg.plugin.python.syntax.class"); + public static final Color METHOD_COLOR = new GColor("color.fg.plugin.python.syntax.method"); /* anonymous code chunks */ - public static final Color CODE_COLOR = new Color(0, 64, 0); - public static final Color INSTANCE_COLOR = new Color(128, 0, 128); - public static final Color SEQUENCE_COLOR = new Color(128, 96, 64); - public static final Color MAP_COLOR = new Color(64, 96, 128); - public static final Color NUMBER_COLOR = new Color(64, 64, 64); + public static final Color CODE_COLOR = new GColor("color.fg.plugin.python.syntax.code"); + public static final Color INSTANCE_COLOR = new GColor("color.fg.plugin.python.syntax.instance"); + public static final Color SEQUENCE_COLOR = new GColor("color.fg.plugin.python.syntax.sequence"); + public static final Color MAP_COLOR = new GColor("color.fg.plugin.python.syntax.map"); + public static final Color NUMBER_COLOR = new GColor("color.fg.plugin.python.syntax.number"); /* for weird Jython-specific stuff */ - public static final Color SPECIAL_COLOR = new Color(64, 96, 64); + public static final Color SPECIAL_COLOR = new GColor("color.fg.plugin.python.syntax.special"); + //@formatter:on static { /* Order matters! This is the order in which classes are checked for diff --git a/Ghidra/Framework/Docking/certification.manifest b/Ghidra/Framework/Docking/certification.manifest index 5141d01af6..a36f1a8561 100644 --- a/Ghidra/Framework/Docking/certification.manifest +++ b/Ghidra/Framework/Docking/certification.manifest @@ -9,21 +9,14 @@ ##MODULE IP: Tango Icons - Public Domain Module.manifest||GHIDRA||||END| data/ExtensionPoint.manifest||GHIDRA||||END| -src/main/help/help/TOC_Source.xml||GHIDRA||||END| -src/main/help/help/shared/arrow.gif||GHIDRA||||END| -src/main/help/help/shared/close16.gif||GHIDRA||||END| -src/main/help/help/shared/menu16.gif||GHIDRA||||END| -src/main/help/help/shared/note-red.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| -src/main/help/help/shared/note.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| -src/main/help/help/shared/note.yellow.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| -src/main/help/help/shared/redo.png||GHIDRA||||END| -src/main/help/help/shared/tip.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| -src/main/help/help/shared/undo.png||GHIDRA||||END| -src/main/help/help/shared/warning.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| -src/main/help/help/topics/PlacheholderTopic/Placeholder.htm||GHIDRA||||END| -data/docking.palette.material.theme.properties||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/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| +src/main/help/help/topics/Theming/images/ThemeDialog.png||GHIDRA||||END| src/main/java/docking/dnd/package.html||GHIDRA||reviewed||END| src/main/java/docking/options/editor/package.html||GHIDRA||reviewed||END| src/main/java/docking/widgets/fieldpanel/package.html||GHIDRA||reviewed||END| diff --git a/Ghidra/Framework/Docking/data/docking.palette.theme.properties b/Ghidra/Framework/Docking/data/docking.palette.theme.properties index ac6b3e892f..f645b4f5c7 100644 --- a/Ghidra/Framework/Docking/data/docking.palette.theme.properties +++ b/Ghidra/Framework/Docking/data/docking.palette.theme.properties @@ -6,17 +6,21 @@ color.palette.disabled = rgba(255,255,255,0) color.palette.black = black color.palette.blue = blue color.palate.cornflowerblue = cornflowerblue +color.palate.cornsilk = cornsilk color.palette.crimson = crimson color.palette.cyan = cyan color.palette.darkblue = DarkBlue color.palette.darkgray = DarkGray +color.palette.darkgreen = darkgreen color.palette.darkkhaki = DarkKhaki color.palette.darkred = DarkRed color.palette.darkslategray = darkslategray color.palette.dodgerblue = DodgerBlue +color.palette.fuchsia = fuchsia color.palette.gold = gold color.palette.gray = gray color.palette.green = green +color.palette.greenyellow = greenyellow color.palette.indigo = indigo color.palette.khaki = khaki color.palette.lavender = lavender @@ -36,10 +40,14 @@ color.palette.olive = olive color.palette.orange = orange color.palette.palegreen = palegreen color.palette.palevioletred = PaleVioletRed +color.palette.peachpuff = peachpuff color.palette.pink = pink color.palette.purple = purple color.palette.red = red color.palette.silver = silver +color.palette.steelblue = steelblue +color.palette.tan = tan +color.palette.teal = teal color.palette.yellow = yellow color.palette.yellowgreen = yellowgreen color.palette.white = white diff --git a/Ghidra/Framework/Docking/data/docking.theme.properties b/Ghidra/Framework/Docking/data/docking.theme.properties index 6f786a52ba..eb75e8f09c 100644 --- a/Ghidra/Framework/Docking/data/docking.theme.properties +++ b/Ghidra/Framework/Docking/data/docking.theme.properties @@ -73,7 +73,7 @@ color.bg.tree.drag.no.selection = rgb(204, 204, 255) color.bg.filterfield = color.bg.filtered color.fg.filterfield = black -color.bg.selection.help = lightSteelBlue +color.bg.selection.help = lightsteelblue // generic component items color.border.bevel.highlight = lightGray diff --git a/Ghidra/Framework/Docking/src/main/help/help/TOC_Source.xml b/Ghidra/Framework/Docking/src/main/help/help/TOC_Source.xml index 8a327c6107..9ec1fd5b9f 100644 --- a/Ghidra/Framework/Docking/src/main/help/help/TOC_Source.xml +++ b/Ghidra/Framework/Docking/src/main/help/help/TOC_Source.xml @@ -20,9 +20,9 @@ During the help build time, all TOC_Source.xml files will be parsed and validated to ensure that all tags point to valid tags. From these files will be generated _TOC.xml files, which are table of contents files written in the format - desired by the JavaHelp system. Additionally, the genated files will be merged together + desired by the JavaHelp system. Additionally, the generated files will be merged together as they are loaded by the JavaHelp system. In the end, when displaying help in the Ghidra - help GUI, there will be on table of contents that has been created from the definitions in + help GUI, there will be one table of contents that has been created from the definitions in all of the modules' TOC_Source.xml files. @@ -43,12 +43,14 @@ **The URL for the target is relative and should start with 'help/topics'. This text is used by the Ghidra help system to provide a universal starting point for all links so that they can be resolved at runtime, across modules. - + --> - - - + + + diff --git a/Ghidra/Framework/Docking/src/main/help/help/shared/arrow.gif b/Ghidra/Framework/Docking/src/main/help/help/shared/arrow.gif deleted file mode 100644 index bcb3db7057..0000000000 Binary files a/Ghidra/Framework/Docking/src/main/help/help/shared/arrow.gif and /dev/null differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/shared/close16.gif b/Ghidra/Framework/Docking/src/main/help/help/shared/close16.gif deleted file mode 100644 index f523864639..0000000000 Binary files a/Ghidra/Framework/Docking/src/main/help/help/shared/close16.gif and /dev/null differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/shared/menu16.gif b/Ghidra/Framework/Docking/src/main/help/help/shared/menu16.gif deleted file mode 100644 index 4350a523dd..0000000000 Binary files a/Ghidra/Framework/Docking/src/main/help/help/shared/menu16.gif and /dev/null differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/shared/note-red.png b/Ghidra/Framework/Docking/src/main/help/help/shared/note-red.png deleted file mode 100644 index b5f1d5cd1c..0000000000 Binary files a/Ghidra/Framework/Docking/src/main/help/help/shared/note-red.png and /dev/null differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/shared/note.png b/Ghidra/Framework/Docking/src/main/help/help/shared/note.png deleted file mode 100644 index 51e1c8f8c1..0000000000 Binary files a/Ghidra/Framework/Docking/src/main/help/help/shared/note.png and /dev/null differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/shared/note.yellow.png b/Ghidra/Framework/Docking/src/main/help/help/shared/note.yellow.png deleted file mode 100644 index f8ab6489f2..0000000000 Binary files a/Ghidra/Framework/Docking/src/main/help/help/shared/note.yellow.png and /dev/null differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/shared/redo.png b/Ghidra/Framework/Docking/src/main/help/help/shared/redo.png deleted file mode 100644 index 88035efeec..0000000000 Binary files a/Ghidra/Framework/Docking/src/main/help/help/shared/redo.png and /dev/null differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/shared/tip.png b/Ghidra/Framework/Docking/src/main/help/help/shared/tip.png deleted file mode 100644 index 209f1d28c8..0000000000 Binary files a/Ghidra/Framework/Docking/src/main/help/help/shared/tip.png and /dev/null differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/shared/undo.png b/Ghidra/Framework/Docking/src/main/help/help/shared/undo.png deleted file mode 100644 index edd57f5c15..0000000000 Binary files a/Ghidra/Framework/Docking/src/main/help/help/shared/undo.png and /dev/null differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/shared/warning.png b/Ghidra/Framework/Docking/src/main/help/help/shared/warning.png deleted file mode 100644 index 8e9133789b..0000000000 Binary files a/Ghidra/Framework/Docking/src/main/help/help/shared/warning.png and /dev/null differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/topics/PlacheholderTopic/Placeholder.htm b/Ghidra/Framework/Docking/src/main/help/help/topics/PlacheholderTopic/Placeholder.htm deleted file mode 100644 index 13961916f5..0000000000 --- a/Ghidra/Framework/Docking/src/main/help/help/topics/PlacheholderTopic/Placeholder.htm +++ /dev/null @@ -1,17 +0,0 @@ - - - - - Placholder Title - - - - -

Stub

- -

Blah blah

- -

Related Topics:

- - - diff --git a/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/Theming.htm b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/Theming.htm new file mode 100644 index 0000000000..7046251bc1 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/Theming.htm @@ -0,0 +1,302 @@ + + + + + + + Theming + + + + +

Theming

+ +

Overview

+ +

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 + light or dark defaults, and any custom colors, fonts, and icons that override the default + values. Users can can easily switch between any of the built-in themes or any saved themes from + their home application directory

+ +

Users can also edit and create their own themes using the Theme Editor. Custom themes are + stored in the users <application dir>/themes. These are simple text files that can also + 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.

+ +

Theme Dialog

+ +

The Theme Dialog is the primary means for creating, editing, and saving themes.

+ +


+  

+ +

The Theme Dialog consists of a theme comboBox and a tabbed set of tables that display the + values for every color property, font property, and icon property defined by either the Java + LookAndFeel or the Ghidra application. All Ghidra defined properties start with "color.", + "font.", or "icon." depending on whether the the property is a color, font, or icon + respectively. All other properties are defined by the Java LookAndFeel.

+ +

Each table entry shows the property id string and then the current value, the theme value, + and the default color. Most often, the three values are equal. If the theme value is different + from the default value, that means that the active theme has overridden the default value for + that property. If the current value is different from the theme value, that means the user has + changed that value, but not yet saved the changes back to the theme.

+ +

Individual values can be changed by double clicking the Id or Current Color column. This + will bring up an appropriate editor for changing the value. When editing a value, the change + takes place immediately in the application so you can see the effect. When you leave the + specific property editor, you have the choice of keeping the change or canceling and having it + revert back to its previous value.

+ +

If any values have been changed, the "Save" button will become enabled, allowing you to save + any changes you have made. (Hitting "Dismiss" will also give the the option to save.) If the + current theme is a built-in theme, you will first have to supply a new theme name. If the + current theme is a not a built-in theme, you will have the option to overwrite the existing + theme or supplying a new name to save it as a new theme.

+ +
+

Color Editor

+ +

When you double-click on a color value, the Edit Color dialog appears.

+ +


+  

+ +

Any change you make in the editor is applied to the application immediately. If you press + the OK button, the change will stay. If you press the Cancel button, the color will revert + back to the original color.

+ +

Font Editor

+ +

When you double-click on a font value, the Edit Font dialog appears.

+ +


+  

+ +

Any change you make in the editor is applied to the application immediately. If you press + the OK button, the change will stay. If you press the Cancel button, the font will revert + back to the original font.

+ +

Icon Editor

+ +

When you double-click on an Icon value, the Edit Icon dialog appears.

+ +


+  

+ +

The Edit Icon dialog has a drop down text field where you can find any existing icon on + the classpath. If you want to choose an Icon from the file system, press the "..." button and + a FileChooser will appear, allowing you to pick an icon file from anywhere in the filesystem. + Any change you make in the editor is applied to the application immediately. If you press the + OK button, the change will stay. If you press the Cancel button, the icon will revert back to + the original icon.

+
+ +

Theme Actions

+ +
+

Switching Themes

+ +

To change the current theme, first bring up the Theme Dialog. + The Theme Dialog can be invoked from the Ghidra Project Window menu using the + EditTheme menu. Then select + a theme from the combo box at the top of the Theme Editor dialog.

+ +

Modifying Theme Values

+ +

All the colors, fonts, and icons that have been externalized can be modified using the Theme Dialog. The Theme Dialog can be invoked from the + Ghidra Project Window using the + EditTheme menu. Choose the + tab for the appropriate type and double-click on the id column or current value column of the + item you want to change. An editor for that type will appear.

+ +

Reseting Theme Values

+ +

To reset an individual value back to its original theme value, invoke the Theme Dialog using the Edit Theme menu. Switch to the appropriate tab for either colors, fonts, or + icons. Right-click on the row of the value you want to reset and choose the Restore + Value menu item.

+ +

Reseting All Theme Values

+ +

To reset all values back to the original values established by the current theme, invoked + the EditTheme Actions Reset Theme Values menu.

+ +

Saving Themes

+ +

After making changes to one or more theme values, the Theme + Dialog's Save button will be enabled. Pressing the Save button will give + the user the option of creating a new theme or overwriting the current them (if the current + theme is not a built-in theme). Also, users will have the options of saving a theme if they + dismiss the Theme Dialog while there are changes to one or more theme values.

+ +

Deleting Themes

+ +

To delete a custom saved theme, invoked the EditTheme Actions Delete Theme... menu. This will bring up a dialog + with a list of themes that can be deleted. Select the theme to delete and press the Ok + button.

+ +

Exporting Themes>

+ +

To export a theme so that it can be shared with others, invoke the Edit Theme Actions Export Theme... menu. You will first be asked if + you want to export as a regular theme file or as a Zip file. The Zip file option is useful if + the current theme has icon values that are not included with standard Ghidra. In that case, + the Zip file will include those non standard icon files.

+ +

Importing Themes

+ +

To import a theme, invoke the Edit Theme Actions Import + Theme... menu. A file chooser dialog will appear allowing the user to choose a theme file + to import. The selected file can be either a standard theme file or a Zip file containing the + theme file and any non-standard icon files defined by that theme.

+ +

Reloading Default Values

+ +

XThis action causes Ghidra to reload all theme default values. It is really only useful + for developers who are actively making changes to theme.properties files. To activate this + action, press the refresh button in the top + right corner of the Theme Dialog.

+
+ +

Theme Property Names

+ +

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

+ +

The general format is:

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

Theme File Format

+ +
+

Saved theme files have the following format:

+
+     
+   
+        name = ThemeName
+        lookAndFeel = Nimbus
+        useDarkDefaults = false
+        
+        color.bg = Black
+        color.bg.foo = #012345
+        [color]Panel.background = Red
+        font.button = dialog-PLAIN-14
+        icon.refresh = images/reload3.png    
+        color.bg.bar = color.bg.foo   
+        color.bg.xxx = [color]Panel.background
+    
+   
+
+ +

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

+ +

Each property line is expected to begin with either "color.", "font.", or "icon." Since + java defined properties don't start with these prefixes, they will have "[color]", "[font]", + or "[icon]" prepended to their property name. These are just there for the purposes of + parsing this file. When the properties are used in Ghidra, those bracketed prefixes are + removed.

+ +

Also, note that the values of these properties can reference other property names. If the + right side of the assignment is a property name and not a value, then it must also use the + bracketed prefix if the property name doesn't start with "color.", "font.", or "icon."

+ +

Specifying Color Values

+ +

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

+ +
    +
  • Web Color Name - Examples: Blue, Red, Black, etc.
  • + +
  • Hex value - #rrggbb, Example: #ff01a4, where ff is the red value, 01 is the + green value, and a4 is the blue value
  • + +
  • Hex with alpha value -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
  • + +
  • RGB values - Example: rgb(12, 34, 56) where red is 12(decimal), green is 34, and + blue is 56
  • + +
  • RGBA values - Eample: rgba(12, 34, 56, 127) where red is 12(decimal), green is + 34, blue is 56, and alpha is 127
  • +
+ +

Specifying Font Values

+ +

Font values are specified as follows:

+
+        familyName-style-size
+   
+
+ +
    +
  • familyName: the font family name such as "monospace", "dialog", "courier"
  • + +
  • style:either PLAIN, BOLD, ITALIC, or BOLDITALIC
  • + +
  • size: the font size such as 12, 14, 22
  • +
+ +

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

+ +

Specifying Icon Values

+ +

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

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

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

+
+ + diff --git a/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/images/ColorEditor.png b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/images/ColorEditor.png new file mode 100644 index 0000000000..937e5a7b70 Binary files /dev/null and b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/images/ColorEditor.png differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/images/FontEditor.png b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/images/FontEditor.png new file mode 100644 index 0000000000..10e4350d97 Binary files /dev/null and b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/images/FontEditor.png differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/images/IconEditor.png b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/images/IconEditor.png new file mode 100644 index 0000000000..b806590033 Binary files /dev/null and b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/images/IconEditor.png differ diff --git a/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/images/ThemeDialog.png b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/images/ThemeDialog.png new file mode 100644 index 0000000000..5254f290aa Binary files /dev/null and b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/images/ThemeDialog.png differ diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DefaultHelpService.java b/Ghidra/Framework/Docking/src/main/java/docking/DefaultHelpService.java deleted file mode 100644 index 34bd0ec52b..0000000000 --- a/Ghidra/Framework/Docking/src/main/java/docking/DefaultHelpService.java +++ /dev/null @@ -1,118 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package docking; - -import java.awt.*; - -import javax.swing.JButton; - -import docking.help.HelpDescriptor; -import docking.help.HelpService; -import ghidra.util.HelpLocation; -import ghidra.util.Msg; - -public class DefaultHelpService implements HelpService { - - @Override - public void showHelp(Object helpObj, boolean infoOnly, Component parent) { - if (infoOnly) { - displayHelpInfo(helpObj); - return; - } - } - - @Override - public void showHelp(java.net.URL url) { - // no-op - } - - @Override - public void showHelp(HelpLocation location) { - // no-op - } - - @Override - public void excludeFromHelp(Object helpObject) { - // no-op - } - - @Override - public boolean isExcludedFromHelp(Object helpObject) { - return false; - } - - @Override - public void clearHelp(Object helpObject) { - // no-op - } - - @Override - public void registerHelp(Object helpObj, HelpLocation helpLocation) { - // no-op - } - - @Override - public HelpLocation getHelpLocation(Object object) { - return null; - } - - @Override - public boolean helpExists() { - return false; - } - - @Override - public void reload() { - // no-op - } - - private void displayHelpInfo(Object helpObj) { - String msg = getHelpInfo(helpObj); - Msg.showInfo(this, null, "Help Info", msg); - } - - private String getHelpInfo(Object helpObj) { - if (helpObj == null) { - return "Help Object is null"; - } - StringBuilder buffy = new StringBuilder(); - buffy.append("HELP OBJECT: " + helpObj.getClass().getName()); - buffy.append("\n"); - if (helpObj instanceof HelpDescriptor) { - HelpDescriptor helpDescriptor = (HelpDescriptor) helpObj; - buffy.append(helpDescriptor.getHelpInfo()); - - } - else if (helpObj instanceof JButton) { - JButton button = (JButton) helpObj; - buffy.append(" BUTTON: " + button.getText()); - buffy.append("\n"); - Component c = button; - while (c != null && !(c instanceof Window)) { - c = c.getParent(); - } - if (c instanceof Dialog) { - buffy.append(" DIALOG: " + ((Dialog) c).getTitle()); - buffy.append("\n"); - } - if (c instanceof Frame) { - buffy.append(" FRAME: " + ((Frame) c).getTitle()); - buffy.append("\n"); - } - } - return buffy.toString(); - } -} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/help/CustomTOCView.java b/Ghidra/Framework/Docking/src/main/java/docking/help/CustomTOCView.java deleted file mode 100644 index ff6b4e3ae9..0000000000 --- a/Ghidra/Framework/Docking/src/main/java/docking/help/CustomTOCView.java +++ /dev/null @@ -1,527 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package docking.help; - -import java.awt.Component; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Hashtable; -import java.util.Locale; - -import javax.help.*; -import javax.help.Map.ID; -import javax.help.event.HelpModelEvent; -import javax.help.plaf.HelpNavigatorUI; -import javax.help.plaf.basic.BasicTOCCellRenderer; -import javax.help.plaf.basic.BasicTOCNavigatorUI; -import javax.swing.*; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.TreePath; - -import ghidra.util.Msg; -import ghidra.util.SystemUtilities; - -/** - * A custom Table of Contents view that we specify in our JavaHelp xml documents. This view - * lets us install custom renderers and custom tree items for use by those renderers. These - * renderers let us display custom text defined by the TOC_Source.xml files. We also add some - * utility like: tooltips in development mode, node selection when pressing F1. - */ -public class CustomTOCView extends TOCView { - - private CustomTOCNavigatorUI ui; - - private boolean isSelectingNodeInternally; - - // Hashtable - public CustomTOCView(HelpSet hs, String name, String label, - @SuppressWarnings("rawtypes") Hashtable params) { - this(hs, name, label, hs.getLocale(), params); - } - - // Hashtable - public CustomTOCView(HelpSet hs, String name, String label, Locale locale, - @SuppressWarnings("rawtypes") Hashtable params) { - super(hs, name, label, locale, params); - } - - @Override - // overrode this method to install our custom UI, which lets us use our custom renderer - public Component createNavigator(HelpModel model) { - JHelpTOCNavigator helpTOCNavigator = new JHelpTOCNavigator(this, model) { - @Override - public void setUI(HelpNavigatorUI newUI) { - CustomTOCView.this.ui = new CustomTOCNavigatorUI(this); - super.setUI(CustomTOCView.this.ui); - } - }; - - return helpTOCNavigator; - } - - public HelpModel getHelpModel() { - if (ui == null) { - return null; - } - return ui.getHelpModel(); - } - - @Override - // overrode this method to install our custom factory - public DefaultMutableTreeNode getDataAsTree() { - - DefaultMutableTreeNode superNode = super.getDataAsTree(); - if (superNode.getChildCount() == 0) { - return superNode; // something is not initialized - } - - @SuppressWarnings("rawtypes") - Hashtable viewParameters = getParameters(); - String TOCData = (String) viewParameters.get("data"); - HelpSet helpSet = getHelpSet(); - URL helpSetURL = helpSet.getHelpSetURL(); - URL url; - try { - url = new URL(helpSetURL, TOCData); - } - catch (Exception ex) { - throw new Error("Unable to create tree for view data: " + ex); - } - - return parse(url, helpSet, helpSet.getLocale(), new CustomDefaultTOCFactory(), this); - } - - /** - * Our custom factory that knows how to look for extra XML attributes and how to - * create our custom tree items - */ - public static class CustomDefaultTOCFactory extends DefaultTOCFactory { - @Override - public TreeItem createItem(String tagName, @SuppressWarnings("rawtypes") Hashtable atts, - HelpSet hs, Locale locale) { - - try { - return doCreateItem(tagName, atts, hs, locale); - } - catch (Exception e) { - Msg.error(this, "Unexected error creating a TOC item", e); - throw new RuntimeException("Unexpected error creating a TOC item", e); - } - } - - private TreeItem doCreateItem(String tagName, @SuppressWarnings("rawtypes") Hashtable atts, - HelpSet hs, Locale locale) { - TreeItem item = super.createItem(tagName, atts, hs, locale); - - CustomTreeItemDecorator newItem = new CustomTreeItemDecorator((TOCItem) item); - - if (atts != null) { - String displayText = (String) atts.get("display"); - newItem.setDisplayText(displayText); - String tocID = (String) atts.get("toc_id"); - newItem.setTocID(tocID); - } - return newItem; - } - } - - /** - * Our hook to install our custom cell renderer. - */ - class CustomTOCNavigatorUI extends BasicTOCNavigatorUI { - public CustomTOCNavigatorUI(JHelpTOCNavigator b) { - super(b); - } - - @Override - public void installUI(JComponent c) { - super.installUI(c); - - tree.setExpandsSelectedPaths(true); - } - - @Override - protected void setCellRenderer(NavigatorView view, JTree tree) { - Map map = view.getHelpSet().getCombinedMap(); - tree.setCellRenderer(new CustomCellRenderer(map, (TOCView) view)); - ToolTipManager.sharedInstance().registerComponent(tree); - } - - public HelpModel getHelpModel() { - JHelpNavigator helpNavigator = getHelpNavigator(); - return helpNavigator.getModel(); - } - - // Overridden to change the value used for the 'historyName', which we want to be our - // display name and not the item's name - @Override - public void valueChanged(TreeSelectionEvent e) { - if (isSelectingNodeInternally) { - // ignore our own selection events, as this method will get called twice if we don't - return; - } - - JHelpNavigator navigator = getHelpNavigator(); - HelpModel helpModel = navigator.getModel(); - - TreeItem treeItem = getSelectedItem(e, navigator); - if (treeItem == null) { - return; // nothing selected - } - - TOCItem item = (TOCItem) treeItem; - ID itemID = item.getID(); - if (itemID == null) { - Msg.debug(this, "No help ID for " + item); - return; - } - - String presentation = item.getPresentation(); - if (presentation != null) { - return; // don't currently support presentations - } - - CustomTreeItemDecorator customItem = (CustomTreeItemDecorator) item; - String customDisplayText = customItem.getDisplayText(); - try { - helpModel.setCurrentID(itemID, customDisplayText, navigator); - } - catch (InvalidHelpSetContextException ex) { - Msg.error(this, "Exception setting new help item ID", ex); - } - } - - private TOCItem getSelectedItem(TreeSelectionEvent e, JHelpNavigator navigator) { - TreePath newLeadSelectionPath = e.getNewLeadSelectionPath(); - if (newLeadSelectionPath == null) { - navigator.setSelectedItems(null); - return null; - } - - DefaultMutableTreeNode node = - (DefaultMutableTreeNode) newLeadSelectionPath.getLastPathComponent(); - TOCItem treeItem = (TOCItem) node.getUserObject(); - navigator.setSelectedItems(new TreeItem[] { treeItem }); - - return treeItem; - } - - // Overridden to try to find a parent file for IDs that are based upon anchors within - // a file - @Override - public synchronized void idChanged(HelpModelEvent e) { - selectNodeForID(e.getURL(), e.getID()); - } - - private void selectNodeForID(URL url, ID ID) { - if (ID == null) { - ID = getClosestID(url); - } - - TreePath path = tree.getSelectionPath(); - if (isAlreadySelected(path, ID)) { - return; - } - - DefaultMutableTreeNode node = getNodeForID(topNode, ID); - if (node != null) { - isSelectingNodeInternally = true; - TreePath newPath = new TreePath(node.getPath()); - tree.setSelectionPath(newPath); - tree.scrollPathToVisible(newPath); - isSelectingNodeInternally = false; - return; - } - - // See if the given ID is based upon a URL with an anchor. If that is the case, then - // there may be a node for the parent file of that URL. In that case, select the - // parent file. - if (url == null) { - clearSelection(); - return; - } - - String urlString = url.toExternalForm(); - int anchorIndex = urlString.indexOf('#'); - if (anchorIndex < 0) { - clearSelection(); - return; - } - - urlString = urlString.substring(0, anchorIndex); - try { - URL newURL = new URL(urlString); - selectNodeForID(newURL, null); - } - catch (MalformedURLException e) { - // shouldn't happen, as we are starting with a valid URL - Msg.debug(this, - "Unexpected error create a help URL from an existing URL: " + urlString, e); - } - } - - private ID getClosestID(URL url) { - HelpModel helpModel = toc.getModel(); - HelpSet helpSet = helpModel.getHelpSet(); - Map combinedMap = helpSet.getCombinedMap(); - return combinedMap.getClosestID(url); - } - - private boolean isAlreadySelected(TreePath path, ID id) { - if (path == null) { - return false; - } - - Object pathComponent = path.getLastPathComponent(); - if (!(pathComponent instanceof DefaultMutableTreeNode)) { - return false; - } - - DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) pathComponent; - TOCItem item = (TOCItem) treeNode.getUserObject(); - if (item == null) { - return false; - } - - ID selectedID = item.getID(); - return selectedID != null && selectedID.equals(id); - } - - private DefaultMutableTreeNode getNodeForID(DefaultMutableTreeNode node, ID ID) { - if (ID == null) { - return null; - } - - if (isNodeID(node, ID)) { - return node; - } - - int childCount = node.getChildCount(); - for (int i = 0; i < childCount; i++) { - DefaultMutableTreeNode matchingNode = - getNodeForID((DefaultMutableTreeNode) node.getChildAt(i), ID); - if (matchingNode != null) { - return matchingNode; - } - } - - return null; - } - - private boolean isNodeID(DefaultMutableTreeNode node, ID ID) { - Object userObject = node.getUserObject(); - if (!(userObject instanceof TOCItem)) { - return false; - } - - TOCItem item = (TOCItem) userObject; - ID nodeID = item.getID(); - if (nodeID == null) { - return false; - } - - return nodeID.equals(ID); - } - - private void clearSelection() { - isSelectingNodeInternally = true; - tree.clearSelection(); - isSelectingNodeInternally = false; - } - } - - static class CustomCellRenderer extends BasicTOCCellRenderer { - - public CustomCellRenderer(Map map, TOCView view) { - super(map, view); - } - - @Override - public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, - boolean expanded, boolean leaf, int row, boolean isFocused) { - - CustomCellRenderer renderer = - (CustomCellRenderer) super.getTreeCellRendererComponent(tree, value, sel, expanded, - leaf, row, isFocused); - - TOCItem item = (TOCItem) ((DefaultMutableTreeNode) value).getUserObject(); - if (item == null) { - return renderer; - } - - CustomTreeItemDecorator customItem = (CustomTreeItemDecorator) item; - renderer.setText(customItem.getDisplayText()); - - if (!SystemUtilities.isInDevelopmentMode()) { - return renderer; - } - - URL url = customItem.getURL(); - if (url != null) { - renderer.setToolTipText(url.toExternalForm()); - return renderer; - } - - ID id = customItem.getID(); - if (id != null) { - renderer.setToolTipText("Missing Help - " + id.id + " in '" + id.hs + "' help set"); - return renderer; - } - - // this can happen if there is no 'target' attribute in the TOC - // (see TOCView.createItem()) - return renderer; - } - } - - /** - * A custom tree item that allows us to store and retrieve custom attributes that we parsed - * from the TOC xml document. - */ - public static class CustomTreeItemDecorator extends javax.help.TOCItem { - - private final TOCItem wrappedItem; - private String displayText; - private String tocID; - private URL cachedURL; - - public CustomTreeItemDecorator(javax.help.TOCItem wrappedItem) { - super(wrappedItem.getID(), wrappedItem.getImageID(), wrappedItem.getHelpSet(), - wrappedItem.getLocale()); - this.wrappedItem = wrappedItem; - } - - void setDisplayText(String text) { - this.displayText = text; - } - - public String getDisplayText() { - return displayText; - } - - void setTocID(String tocID) { - this.tocID = tocID; - } - - public String getTocID() { - return tocID; - } - - @Override - public boolean equals(Object obj) { - return wrappedItem.equals(obj); - } - - @Override - public int getExpansionType() { - return wrappedItem.getExpansionType(); - } - - @Override - public HelpSet getHelpSet() { - return wrappedItem.getHelpSet(); - } - - @Override - public ID getID() { - return wrappedItem.getID(); - } - - @Override - public ID getImageID() { - return wrappedItem.getImageID(); - } - - @Override - public Locale getLocale() { - return wrappedItem.getLocale(); - } - - @Override - public String getMergeType() { - return wrappedItem.getMergeType(); - } - - @Override - public String getName() { - return wrappedItem.getName(); - } - - @Override - public String getPresentation() { - return wrappedItem.getPresentation(); - } - - @Override - public String getPresentationName() { - return wrappedItem.getPresentationName(); - } - - @Override - public URL getURL() { - if (cachedURL == null) { - cachedURL = wrappedItem.getURL(); - } - return cachedURL; - } - - @Override - public int hashCode() { - return wrappedItem.hashCode(); - } - - @Override - public void setExpansionType(int type) { - wrappedItem.setExpansionType(type); - } - - @Override - public void setHelpSet(HelpSet hs) { - wrappedItem.setHelpSet(hs); - } - - @Override - public void setID(ID id) { - wrappedItem.setID(id); - } - - @Override - public void setMergeType(String mergeType) { - wrappedItem.setMergeType(mergeType); - } - - @Override - public void setName(String name) { - wrappedItem.setName(name); - } - - @Override - public void setPresentation(String presentation) { - wrappedItem.setPresentation(presentation); - } - - @Override - public void setPresentationName(String presentationName) { - wrappedItem.setPresentationName(presentationName); - } - - @Override - public String toString() { - return displayText; - } - } -} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/help/DockingHelpBroker.java b/Ghidra/Framework/Docking/src/main/java/docking/help/DockingHelpBroker.java index 04d8054c5d..7049358cdf 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/help/DockingHelpBroker.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/help/DockingHelpBroker.java @@ -37,6 +37,7 @@ import org.jdesktop.animation.timing.TimingTargetAdapter; import docking.framework.ApplicationInformationDisplayFactory; import docking.util.AnimationPainter; import docking.util.AnimationUtils; +import generic.theme.GColor; import ghidra.framework.preferences.Preferences; import ghidra.util.Msg; import ghidra.util.Swing; @@ -398,7 +399,7 @@ public class DockingHelpBroker extends GHelpBroker { private class LocationHintPainter implements AnimationPainter { - private Color color = new Color(100, 100, 255, 100); + private Color color = new GColor("color.bg.help.hint"); private Shape paintShape; LocationHintPainter(Shape paintShape) { @@ -450,11 +451,11 @@ public class DockingHelpBroker extends GHelpBroker { /* // Debug Shape box = scaler.createTransformedShape(b); - g2d.setColor(Color.GREEN); + g2d.setColor(Palette.GREEN); g2d.fill(box); - + box = transform.createTransformedShape(box); - g2d.setColor(Color.YELLOW); + g2d.setColor(Palette.YELLOW); g2d.fill(box); */ diff --git a/Ghidra/Framework/Docking/src/main/java/docking/help/GHelpBroker.java b/Ghidra/Framework/Docking/src/main/java/docking/help/GHelpBroker.java deleted file mode 100644 index 38d7deb8f6..0000000000 --- a/Ghidra/Framework/Docking/src/main/java/docking/help/GHelpBroker.java +++ /dev/null @@ -1,727 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package docking.help; - -import java.awt.*; -import java.awt.geom.*; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.io.IOException; -import java.net.URL; -import java.util.List; - -import javax.help.*; -import javax.help.event.HelpModelEvent; -import javax.help.event.HelpModelListener; -import javax.swing.*; -import javax.swing.text.*; -import javax.swing.text.html.HTML; -import javax.swing.text.html.HTMLDocument; - -import org.jdesktop.animation.timing.Animator; -import org.jdesktop.animation.timing.TimingTargetAdapter; - -import docking.framework.ApplicationInformationDisplayFactory; -import docking.util.AnimationPainter; -import docking.util.AnimationUtils; -import generic.theme.GColor; -import ghidra.framework.preferences.Preferences; -import ghidra.util.Msg; -import ghidra.util.Swing; -import ghidra.util.bean.GGlassPane; -import resources.ResourceManager; - -// NOTE: for JH 2.0, this class has been rewritten to not -// access the 'frame' and 'dialog' variable directly - -/** - * Ghidra help broker that displays the help set; sets the Ghidra icon on - * the help frame and attempts to maintain the user window size. - */ -public class GHelpBroker extends DefaultHelpBroker { - private static final List ICONS = ApplicationInformationDisplayFactory.getWindowIcons(); - private static final int MAX_CALLOUT_RETRIES = 3; - - private Dimension windowSize = new Dimension(1100, 700); - - private boolean initialized; - private JEditorPane htmlEditorPane; - private Animator lastAnimator; - private URL loadingURL; - private PropertyChangeListener pageLoadListener = new PageLoadingListener(); - private HelpModelListener helpModelListener = new HelpIDChangedListener(); - private Window activationWindow; - - // Create the zoom in/out icons that will be added to the default jHelp toolbar. - private static final ImageIcon ZOOM_OUT_ICON = - ResourceManager.loadImage("images/list-remove.png"); - private static final ImageIcon ZOOM_IN_ICON = ResourceManager.loadImage("images/list-add.png"); - - /** - * Construct a new GhidraHelpBroker. - * @param hs java help set associated with this help broker - */ - public GHelpBroker(HelpSet hs) { - super(hs); - } - - @Override - // Overridden so that we can call the preferred version of setCurrentURL on the HelpModel, - // which fixes a bug with the history list (SCR 7639) - public void setCurrentURL(final URL URL) { - - HelpModel model = getHelpModel(); - if (model != null) { - model.setCurrentURL(URL, getHistoryName(URL), null); - } - else { - super.setCurrentURL(URL); - } - } - - /* Perform some shenanigans to force Java Help to reload the given URL */ - void reloadHelpPage(URL url) { - clearContentViewer(); - prepareToCallout(url); - try { - htmlEditorPane.setPage(url); - } - catch (IOException e) { - Msg.error(this, "Unexpected error loading help page: " + url, e); - } - } - - private void clearContentViewer() { - htmlEditorPane.getDocument().putProperty(Document.StreamDescriptionProperty, null); - } - - private JScrollPane getScrollPane(JEditorPane editorPane) { - Container parent = editorPane.getParent(); - while (parent != null) { - if (parent instanceof JScrollPane) { - return (JScrollPane) parent; - } - parent = parent.getParent(); - } - return null; - } - - private JEditorPane getHTMLEditorPane(JHelpContentViewer contentViewer) { - // - // Intimate Knowledge - construction of the viewer: - // - // -BorderLayout - // -JScrollPane - // -Viewport - // -JHEditorPane extends JEditorPane - // - // - Component[] components = contentViewer.getComponents(); - JScrollPane scrollPane = (JScrollPane) components[0]; - JViewport viewport = scrollPane.getViewport(); - - return (JEditorPane) viewport.getView(); - } - - private HelpModel getHelpModel() { - // - // Unusual Code Alert!: We have opened up access to the help system's HelpModel by way - // of our CustomTOCView object that we install elsewhere. We need - // access to the model because of a bug in the help system - // (SCR 7639). Unfortunately, the Java Help system does not give us - // access to the model directly, but we have opened up the access from - // one of our overriding components. The following code is - // digging-out our custom component to get at the model. An - // alternative approach would be to just use reflection and violate - // security restrictions, but that seemed worse than this solution. - // - - WindowPresentation windowPresentation = getWindowPresentation(); - HelpSet helpSet = windowPresentation.getHelpSet(); - NavigatorView tocView = helpSet.getNavigatorView("TOC"); - if (!(tocView instanceof CustomTOCView)) { - // not sure how this could happen - Msg.debug(this, "The help system is not using the CustomTOCView class!"); - return null; - } - - CustomTOCView customTOCView = (CustomTOCView) tocView; - return customTOCView.getHelpModel(); - } - - @Override - public void setDisplayed(boolean b) { - if (!b) { - super.setDisplayed(b); - return; - } - - // this must be before any call that triggers the help system to create its window - initializeScreenDevice(); - - WindowPresentation windowPresentation = getWindowPresentation(); - updateWindowSize(windowPresentation); - - // this has to be before getHelpWindow() or the value returned will be null - super.setDisplayed(b); - - initializeUIWindowPresentation(windowPresentation); - } - - private void initializeScreenDevice() { - if (initialized) { - return; - } - - if (activationWindow == null) { - // This can happen when we show the 'What's New' help page on a fresh install. In - // that case, we were not activated from an existing window, thus, there may - // be no parent window. - return; - } - - GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - GraphicsDevice[] gs = ge.getScreenDevices(); - GraphicsConfiguration config = activationWindow.getGraphicsConfiguration(); - GraphicsDevice parentDevice = config.getDevice(); - for (int i = 0; i < gs.length; i++) { - if (gs[i] == parentDevice) { - // update the help window's screen to match that of the parent - setScreen(i); - } - } - } - - private void initializeUIWindowPresentation(WindowPresentation windowPresentation) { - - Window helpWindow = windowPresentation.getHelpWindow(); - Container contentPane = null; - if (helpWindow instanceof JFrame) { - JFrame frame = (JFrame) helpWindow; - installRootPane(frame); - frame.setIconImages(ICONS); - contentPane = frame.getContentPane(); - } - else if (helpWindow instanceof JDialog) { - JDialog dialog = (JDialog) helpWindow; - installRootPane(dialog); - contentPane = dialog.getContentPane(); - } - - initializeUIComponents(contentPane); - } - - private void initializeUIComponents(Container contentPane) { - - if (initialized) { - return; - } - - // the editor pane can be changed out from under us, such as when the UI is updated when - // the theme changes - Component[] components = contentPane.getComponents(); - JHelp jHelp = (JHelp) components[0]; - JHelpContentViewer contentViewer = jHelp.getContentViewer(); - JEditorPane activeHtmlPane = getHTMLEditorPane(contentViewer); - if (activeHtmlPane == htmlEditorPane && initialized) { - return; // already initialized - } - - addCustomToolbarItems(jHelp); - htmlEditorPane = getHTMLEditorPane(contentViewer); - - // just creating the search wires everything together - HelpModel helpModel = getHelpModel(); - helpModel.addHelpModelListener(helpModelListener); - new HelpViewSearcher(jHelp, helpModel); - - installActions(jHelp); - initialized = true; - } - - void reload() { - clearHighlights(); - initialized = false; - if (isDisplayed()) { - setDisplayed(false); - setDisplayed(true); - } - } - - private void clearHighlights() { - TextHelpModel helpModel = (TextHelpModel) getHelpModel(); - if (helpModel != null) { - helpModel.removeAllHighlights(); - } - } - - /** - * Create zoom in/out buttons on the default help window toolbar. - * @param jHelp the java help object used to retrieve the help components - */ - protected void addCustomToolbarItems(final JHelp jHelp) { - - for (Component component : jHelp.getComponents()) { - if (component instanceof JToolBar) { - JToolBar toolbar = (JToolBar) component; - toolbar.addSeparator(); - - ImageIcon zoomOutIcon = ResourceManager.getScaledIcon(ZOOM_OUT_ICON, 24, 24); - JButton zoomOutBtn = new JButton(zoomOutIcon); - zoomOutBtn.setToolTipText("Zoom out"); - zoomOutBtn.addActionListener(e -> { - GHelpHTMLEditorKit.zoomOut(); - - // Need to reload the page to force the scroll panes to resize properly. A - // simple revalidate/repaint won't do it. - reloadHelpPage(getCurrentURL()); - }); - toolbar.add(zoomOutBtn); - - ImageIcon zoomInIcon = ResourceManager.getScaledIcon(ZOOM_IN_ICON, 24, 24); - JButton zoomInBtn = new JButton(zoomInIcon); - zoomInBtn.setToolTipText("Zoom in"); - zoomInBtn.addActionListener(e -> { - GHelpHTMLEditorKit.zoomIn(); - - // Need to reload the page to force the scroll panes to resize properly. A - // simple revalidate/repaint won't do it. - reloadHelpPage(getCurrentURL()); - }); - toolbar.add(zoomInBtn); - - // Once we've found the toolbar we can break out of the loop and stop looking for it. - break; - } - } - } - - private void installActions(JHelp help) { - JToolBar toolbar = null; - Component[] components = help.getComponents(); - for (Component c : components) { - if (c instanceof JToolBar) { - toolbar = (JToolBar) c; - break; - } - } - - if (toolbar == null) { - // shouldn't happen - return; - } - - // separate the Java help stuff from our actions - toolbar.addSeparator(); - - ToggleNavigationAid action = new ToggleNavigationAid(); - toolbar.add(new JButton(action)); - } - - private String getHistoryName(URL URL) { - String text = URL.getFile(); - int index = text.lastIndexOf('/'); - if (index != -1) { - // we want just the filename - text = text.substring(index + 1); - } - - String ref = URL.getRef(); - if (ref != null) { - text += " - " + ref; - } - return text; - } - - private void installRootPane(JFrame frame) { - Component oldGlassPane = frame.getGlassPane(); - if (!(oldGlassPane instanceof GGlassPane)) { - GGlassPane gGlassPane = new GGlassPane(); - frame.setGlassPane(gGlassPane); - gGlassPane.setVisible(true); - } - } - - private void installRootPane(JDialog dialog) { - Component oldGlassPane = dialog.getGlassPane(); - if (!(oldGlassPane instanceof GGlassPane)) { - GGlassPane gGlassPane = new GGlassPane(); - dialog.setGlassPane(gGlassPane); - gGlassPane.setVisible(true); - } - } - - private void updateWindowSize(WindowPresentation presentation) { - if (windowSize == null) { - return; - } - - presentation.createHelpWindow(); - presentation.setSize(windowSize); - } - - @Override - public void setActivationWindow(Window window) { - WindowPresentation windowPresentation = getWindowPresentation(); - Window helpWindow = windowPresentation.getHelpWindow(); - if (helpWindow == null) { - activationWindow = window; - super.setActivationWindow(window); - return; - } - - windowSize = helpWindow.getSize();// remember the previous size - - boolean wasModal = isModalWindow(helpWindow); - boolean willBeModal = isModalWindow(window); - if (!wasModal && willBeModal) { - // in this condition, a new window will be shown, but the old one is not properly - // closed by JavaHelp - helpWindow.setVisible(false); - } - - super.setActivationWindow(window); - } - - private boolean isModalWindow(Window window) { - if (window instanceof Dialog) { - Dialog dialog = (Dialog) window; - if (dialog.isModal()) { - return true; - } - } - return false; - } - - private void showNavigationAid() { - String showAidString = Preferences.getProperty(HelpManager.SHOW_AID_KEY); - if (showAidString == null) { - return; - } - - boolean showAid = Boolean.parseBoolean(showAidString); - if (!showAid) { - return; - } - - calloutReferenceLater(); - } - - private void calloutReferenceLater() { - SwingUtilities.invokeLater(() -> calloutReference(loadingURL)); - } - - private void calloutReference(final URL url) { - String ref = url.getRef(); - if (ref == null) { - return; - } - - final Rectangle area = getReferenceArea(ref); - if (area == null) { - return; - } - - doCalloutReference(area, 0); - } - - private Rectangle getReferenceArea(String ref) { - HTMLDocument document = (HTMLDocument) htmlEditorPane.getDocument(); - HTMLDocument.Iterator iter = document.getIterator(HTML.Tag.A); - for (; iter.isValid(); iter.next()) { - AttributeSet attributes = iter.getAttributes(); - String name = (String) attributes.getAttribute(HTML.Attribute.NAME); - if (name == null || !name.equals(ref)) { - continue; - } - - try { - int start = iter.getStartOffset(); - Rectangle2D startArea = htmlEditorPane.modelToView2D(start); - return startArea.getBounds(); - } - catch (BadLocationException ble) { - Msg.trace(this, "Unexpected exception searching for help reference", ble); - } - } - return null; - } - - /** - * This method exists to address the threaded timing nature of how the help system loads - * help pages and when the UI is adjusted in response to those changes. - *

- * Note: this method will call itself if the view is not yet updated for the requested - * model change. In that case, this method will call itself again later. This may - * need to happen more than once. However, we will only try a few times and - * then just give up. - * - * @param area the area to call out - * @param callCount the number number of times this method has already been called - */ - private void doCalloutReference(final Rectangle area, int callCount) { - - if (callCount > MAX_CALLOUT_RETRIES) { - // this probably can't happen, but we don't want to keep calling this method - // forever. - return; - } - - WindowPresentation windowPresentation = getWindowPresentation(); - Window helpWindow = windowPresentation.getHelpWindow(); - Container contentPane = null; - if (helpWindow instanceof JDialog) { - contentPane = ((JDialog) helpWindow).getContentPane(); - } - else { - contentPane = ((JFrame) helpWindow).getContentPane(); - } - - JScrollPane scrollPane = getScrollPane(htmlEditorPane); - JViewport viewport = scrollPane.getViewport(); - Point viewPosition = viewport.getViewPosition(); - - final int numberOfCalls = callCount + 1; - if (viewPosition.x == 0 && viewPosition.y == 0) { - - // - // Unusual Code: Not yet rendered! Try again. - // - Swing.runLater(() -> doCalloutReference(area, numberOfCalls)); - - return; - } - - // - // The area of the HTML content is absolute inside of the entire document. - // However, the user is viewing the document inside of a scroll pane. So, we - // want the offset of the element within the viewer, not the absolute position. - // - area.y -= viewPosition.y; - - // - // Update the coordinates to be relative to the content pane, which is where we - // are doing the painting. - // - Rectangle relativeArea = SwingUtilities.convertRectangle(scrollPane, area, contentPane); - Shape star = new StarShape(relativeArea.getLocation()); - - Animator animator = - AnimationUtils.createPaintingAnimator(helpWindow, new LocationHintPainter(star)); - if (animator == null) { - return; - } - - lastAnimator = animator; - lastAnimator.addTarget(new TimingTargetAdapter() { - @Override - public void end() { - lastAnimator = null; - } - }); - } - - private void prepareToCallout(URL url) { - if (lastAnimator != null) { - // prevent animations from lingering when moving to new pages - lastAnimator.stop(); - } - - loadingURL = url; - - // TODO - // updateTitle(); - - if (isCurrentPage(loadingURL)) { - showNavigationAid(); - return;// page already loaded; no need to use the listener - } - - // listen for the page to be loaded, as it is asynchronous - htmlEditorPane.removePropertyChangeListener("page", pageLoadListener); - htmlEditorPane.addPropertyChangeListener("page", pageLoadListener); - } - - private boolean isCurrentPage(URL newURL) { - if (newURL == null) { - return false;// not sure if this can happen - } - - String newFile = newURL.getFile(); - URL currentURL = htmlEditorPane.getPage(); - if (currentURL == null) { - return false; - } - - String currentFile = currentURL.getFile(); - return newFile.equals(currentFile); - } - -//================================================================================================== -// Inner Classes -//================================================================================================== - - private class StarShape extends Path2D.Float { - - StarShape(Point location) { - this(5, location, 1, .3);// reasonable star qualities - } - - StarShape(int points, Point location, double outerRadius, double innerRadius) { - // note: location is the origin of the shape - - double angle = Math.PI / points; - GeneralPath path = new GeneralPath(); - - int scale = 20; - double lr = Math.max(outerRadius, innerRadius); - int width = (int) (scale * (2 * lr)); - int height = width;// square bounds - double cx = location.x + width / 2; - double cy = location.y + height / 2; - Point2D.Double center = new Point2D.Double(cx, cy); - - // start the first point... - double r = outerRadius; - double x = center.x + Math.cos(0 * angle) * r; - double y = center.y + Math.sin(0 * angle) * r; - path.moveTo(x, y); - - // ...the remaining points - for (int i = 1; i < 2 * points; i++) { - r = (i % 2) == 0 ? outerRadius : innerRadius; - x = center.x + Math.cos(i * angle) * r; - y = center.y + Math.sin(i * angle) * r; - path.lineTo(x, y); - } - - path.closePath(); - - // scaled center x/y - double scx = scale * cx; - double scy = scale * cy; - - // note: An offset of (width / 2) moves from center to 0. This didn't look quite - // right, so, through trial and error, we updated the offset so that the - // shape's location is just over the beginning of the text that follows the - // anchor, in most cases. - double offsetx = width / 4; - double offsety = height / 4; - - // scaled offset x/y - double sox = scx - offsetx;// move the x from center to 0 - double soy = scy - offsety;// ... - - // delta x/y - double dx = sox - location.x; - double dy = soy - location.y; - - // move the origin so that after we scale, it goes back to 0,0 - AffineTransform xform = AffineTransform.getTranslateInstance(-dx, -dy); - xform.scale(scale, scale); - - Shape shape = xform.createTransformedShape(path); - super.append(shape, true); - } - } - - private class PageLoadingListener implements PropertyChangeListener { - @Override - public void propertyChange(PropertyChangeEvent evt) { - showNavigationAid(); - htmlEditorPane.removePropertyChangeListener("page", pageLoadListener); - } - } - - private class HelpIDChangedListener implements HelpModelListener { - @Override - public void idChanged(HelpModelEvent e) { - prepareToCallout(e.getURL()); - } - } - - private class LocationHintPainter implements AnimationPainter { - - private Color color = new GColor("color.bg.help.hint"); - private Shape paintShape; - - LocationHintPainter(Shape paintShape) { - this.paintShape = paintShape; - } - - @Override - public void paint(GGlassPane glassPane, Graphics graphics, double percentComplete) { - - Graphics2D g2d = (Graphics2D) graphics; - g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, - RenderingHints.VALUE_INTERPOLATION_BILINEAR); - - // - // At 0%, with 100% opacity; at the end, paint with 0% opacity - // - Composite originalComposite = g2d.getComposite(); - AlphaComposite alphaComposite = AlphaComposite.getInstance( - AlphaComposite.SrcOver.getRule(), (float) (1 - percentComplete)); - g2d.setComposite(alphaComposite); - - double transition = 1 - percentComplete; - Color originalColor = g2d.getColor(); - - AffineTransform originalTransform = g2d.getTransform(); - - double scale = 4 * transition; - - int degrees = (int) (480 * transition); - double rad = Math.toRadians(transition * degrees); - - Rectangle b = paintShape.getBounds(); - double cx = b.getCenterX(); - double cy = b.getCenterY(); - double scx = cx * scale; - double scy = cy * scale; - double dcx = scx - cx; - double dcy = scy - cy; - - AffineTransform scaler = new AffineTransform(); - scaler.translate(-dcx, -dcy); - scaler.scale(scale, scale); - Shape scaled = scaler.createTransformedShape(paintShape); - - AffineTransform rotater = new AffineTransform(); - rotater.rotate(rad, cx, cy); - Shape finalShape = rotater.createTransformedShape(scaled); - - /* - // Debug - Shape box = scaler.createTransformedShape(b); - g2d.setColor(Palette.GREEN); - g2d.fill(box); - - box = transform.createTransformedShape(box); - g2d.setColor(Palette.YELLOW); - g2d.fill(box); - */ - - g2d.setColor(color); - g2d.fill(finalShape); - - g2d.setColor(originalColor); - g2d.setTransform(originalTransform); - g2d.setComposite(originalComposite); - } - - } -} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/help/GHelpHTMLEditorKit.java b/Ghidra/Framework/Docking/src/main/java/docking/help/GHelpHTMLEditorKit.java deleted file mode 100644 index 6f8a41c1a4..0000000000 --- a/Ghidra/Framework/Docking/src/main/java/docking/help/GHelpHTMLEditorKit.java +++ /dev/null @@ -1,588 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package docking.help; - -import java.awt.Desktop; -import java.awt.Image; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.io.*; -import java.net.*; -import java.util.*; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.swing.JEditorPane; -import javax.swing.event.HyperlinkEvent; -import javax.swing.event.HyperlinkListener; -import javax.swing.text.*; -import javax.swing.text.html.*; -import javax.swing.text.html.HTML.Tag; - -import generic.jar.ResourceFile; -import generic.theme.GColor; -import ghidra.framework.Application; -import ghidra.framework.preferences.Preferences; -import ghidra.util.Msg; -import resources.*; -import utilities.util.FileUtilities; - -/** - * A class that allows Ghidra to intercept JavaHelp navigation events in order to resolve them to - * Ghidra's help system. Without this class, contribution plugins have no way of referencing help - * documents within Ghidra's default help location. - *

- * This class is currently installed by the {@link GHelpSet}. - * - * @see GHelpSet - */ -public class GHelpHTMLEditorKit extends HTMLEditorKit { - - private static final String G_HELP_STYLE_SHEET = "help/shared/Frontpage.css"; - - private static final Pattern EXTERNAL_URL_PATTERN = Pattern.compile("https?://.*"); - - /** A pattern to strip the font size value from a line of CSS */ - private static final Pattern FONT_SIZE_PATTERN = Pattern.compile("font-size:\\s*(\\d{1,2})"); - private static final String HELP_WINDOW_ZOOM_FACTOR = "HELP.WINDOW.FONT.SIZE.MODIFIER"; - private static int fontSizeModifier; - - /** - * A mapping of known style sheet colors to convert from the values in the style sheet to colors - * defined in the system theme. - */ - private static final Map colorsById = new HashMap<>(); - static { - colorsById.put("h1", new GColor("color.fg.help.selector.h1")); - colorsById.put("h2", new GColor("color.fg.help.selector.h2")); - colorsById.put("h3", new GColor("color.fg.help.selector.h3")); - colorsById.put("p.providedbyplugin", - new GColor("color.fg.help.selector.p.provided.by.plugin")); - colorsById.put("p.relatedtopic", - new GColor("color.fg.help.selector.p.related.topic")); - colorsById.put("th", new GColor("color.fg.help.selector.th")); - colorsById.put("code", new GColor("color.fg.help.selector.code")); - colorsById.put("code.path", new GColor("color.fg.help.selector.code.path")); - } - private static final Pattern COLOR_PATTERN = Pattern.compile("(color:\\s*#{0,1}\\w+;)"); - - private HyperlinkListener[] delegateListeners = null; - private HyperlinkListener resolverHyperlinkListener; - - public GHelpHTMLEditorKit() { - fontSizeModifier = - Integer.valueOf(Preferences.getProperty(HELP_WINDOW_ZOOM_FACTOR, "0", true)); - } - - @Override - public ViewFactory getViewFactory() { - return new GHelpHTMLFactory(); - } - - @Override - public void install(JEditorPane c) { - super.install(c); - - delegateListeners = c.getHyperlinkListeners(); - for (HyperlinkListener listener : delegateListeners) { - c.removeHyperlinkListener(listener); - } - - resolverHyperlinkListener = new ResolverHyperlinkListener(); - c.addHyperlinkListener(resolverHyperlinkListener); - - // add a listener to report trace information - c.addPropertyChangeListener(new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - String propertyName = evt.getPropertyName(); - if ("page".equals(propertyName)) { - Msg.trace(this, "Page loaded: " + evt.getNewValue()); - } - } - }); - } - - @Override - public void deinstall(JEditorPane c) { - - c.removeHyperlinkListener(resolverHyperlinkListener); - - for (HyperlinkListener listener : delegateListeners) { - c.addHyperlinkListener(listener); - } - - super.deinstall(c); - } - - private class ResolverHyperlinkListener implements HyperlinkListener { - @Override - public void hyperlinkUpdate(HyperlinkEvent e) { - - if (delegateListeners == null) { - return; - } - - if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - if (isExternalLink(e)) { - browseExternalLink(e); - return; - } - Msg.trace(this, "Link activated: " + e.getURL()); - e = validateURL(e); - Msg.trace(this, "Validated event: " + e.getURL()); - } - - for (HyperlinkListener listener : delegateListeners) { - listener.hyperlinkUpdate(e); - } - } - } - - private boolean isExternalLink(HyperlinkEvent e) { - String description = e.getDescription(); - return description != null && EXTERNAL_URL_PATTERN.matcher(description).matches(); - } - - private void browseExternalLink(HyperlinkEvent e) { - String description = e.getDescription(); - if (!Desktop.isDesktopSupported()) { - Msg.info(this, "Unable to launch external browser for " + description); - return; - } - - try { - // use an external browser - URI uri = e.getURL().toURI(); - Desktop.getDesktop().browse(uri); - } - catch (URISyntaxException | IOException e1) { - Msg.error(this, "Error browsing to external URL " + description, e1); - } - } - - /** - * Tests the URL of the given event. If the URL is invalid, a new event may be created if - * a new, valid URL can be created. Creates a new event with a patched URL if - * the given event's URL is invalid. - */ - private HyperlinkEvent validateURL(HyperlinkEvent event) { - URL url = event.getURL(); - try { - url.openStream();// assume that this will fail if the file does not exist - } - catch (IOException ioe) { - // assume this means that the url is invalid - Msg.trace(this, "URL of link is invalid: " + url.toExternalForm()); - return maybeCreateNewHyperlinkEventWithUpdatedURL(event); - } - - return event;// url is fine - } - - /** Generates a new event with a URL based upon Ghidra's resources if needed. */ - private HyperlinkEvent maybeCreateNewHyperlinkEventWithUpdatedURL(HyperlinkEvent event) { - Element element = event.getSourceElement(); - if (element == null) { - return event;// this shouldn't happen since we were triggered from an A tag - } - - AttributeSet a = element.getAttributes(); - AttributeSet anchor = (AttributeSet) a.getAttribute(HTML.Tag.A); - if (anchor == null) { - return event;// this shouldn't happen since we were triggered from an A tag - } - - String HREF = (String) anchor.getAttribute(HTML.Attribute.HREF); - Msg.trace(this, "HREF of tag: " + HREF); - URL newUrl = getURLForHREFFromResources(HREF); - if (newUrl == null) { - return event;// unable to locate a resource by the name--bad link! - } - - return new HyperlinkEvent(event.getSource(), event.getEventType(), newUrl, - event.getDescription(), event.getSourceElement()); - } - - private URL getURLForHREFFromResources(String originalHREF) { - int anchorIndex = originalHREF.indexOf("#"); - String HREF = originalHREF; - String anchor = null; - if (anchorIndex != -1) { - HREF = HREF.substring(0, anchorIndex); - anchor = originalHREF.substring(anchorIndex); - } - - // look for a URL using an installation environment setup... - URL newUrl = ResourceManager.getResource(HREF); - if (newUrl != null) { - return createURLWithAnchor(newUrl, anchor); - } - - // - // The item was not found by the ResourceManager (i.e., it is not in a 'resources' - // directory). See if it may be a relative link to a build's installation root (like - // a file in /docs). - // - newUrl = findApplicationfile(HREF); - return newUrl; - } - - private URL createURLWithAnchor(URL anchorlessURL, String anchor) { - if (anchorlessURL == null) { - return anchorlessURL; - } - - if (anchor == null) { - // nothing to do - return anchorlessURL; - } - - try { - // put the anchor back into the URL - return new URL(anchorlessURL, anchor); - } - catch (MalformedURLException e) { - // shouldn't happen, since the file exists - Msg.showError(this, null, "Unexpected Error", - "Unexpected error creating a valid URL: " + anchorlessURL + "#" + anchor); - return null; - } - } - - @Override - public void read(Reader in, Document doc, int pos) throws IOException, BadLocationException { - - super.read(in, doc, pos); - - HTMLDocument htmlDoc = (HTMLDocument) doc; - loadGHelpStyleSheet(htmlDoc); - } - - private void loadGHelpStyleSheet(HTMLDocument doc) { - - Reader reader = getGStyleSheetReader(); - if (reader == null) { - return; - } - - StyleSheet ss = doc.getStyleSheet(); - try { - ss.loadRules(reader, null); - } - catch (IOException e) { - // shouldn't happen - Msg.debug(this, "Unable to load help style sheet"); - } - } - - private Reader getGStyleSheetReader() { - URL url = getGStyleSheetURL(); - if (url == null) { - return null; - } - - StringBuilder buffy = new StringBuilder(); - try { - List lines = FileUtilities.getLines(url); - for (String line : lines) { - - StringBuilder lineBuilder = new StringBuilder(); - changePixels(line, fontSizeModifier, lineBuilder); - - String updatedLine = lineBuilder.toString(); - lineBuilder.delete(0, lineBuilder.length()); - changeColor(updatedLine, lineBuilder); - - buffy.append(lineBuilder.toString()); - buffy.append('\n'); - } - } - catch (IOException e) { - // shouldn't happen - Msg.debug(this, "Unable to read the lines of the help style sheet: " + url); - } - - StringReader reader = new StringReader(buffy.toString()); - return reader; - } - - private void changeColor(String line, StringBuilder buffy) { - - int blockStart = line.indexOf("{"); - if (blockStart == -1) { - buffy.append(line); - return; - } - - String cssSelector = line.substring(0, blockStart).trim(); - cssSelector = cssSelector.toLowerCase(); // normalize - GColor gColor = colorsById.get(cssSelector); - if (gColor == null) { - buffy.append(line); - return; - } - - Matcher matcher = COLOR_PATTERN.matcher(line); - if (matcher.find()) { - matcher.appendReplacement(buffy, "color: " + gColor.toHexString() + ";"); - } - - matcher.appendTail(buffy); - } - - private void changePixels(String line, int amount, StringBuilder buffy) { - - Matcher matcher = FONT_SIZE_PATTERN.matcher(line); - while (matcher.find()) { - String oldFontSize = matcher.group(1); - String adjustFontSize = adjustFontSize(oldFontSize); - matcher.appendReplacement(buffy, "font-size: " + adjustFontSize); - } - - matcher.appendTail(buffy); - } - - private String adjustFontSize(String sizeString) { - try { - int size = Integer.parseInt(sizeString); - String adjusted = Integer.toString(size + fontSizeModifier); - return adjusted; - } - catch (NumberFormatException e) { - Msg.debug(this, "Unable to parse font size string '" + sizeString + "'"); - } - return sizeString; - } - - private URL getGStyleSheetURL() { - URL GStyleSheetURL = ResourceManager.getResource(G_HELP_STYLE_SHEET); - if (GStyleSheetURL != null) { - return GStyleSheetURL; - } - - return findModuleFile("help/shared/FrontPage.css"); - } - - private URL findApplicationfile(String relativePath) { - ResourceFile installDir = Application.getInstallationDirectory(); - ResourceFile file = new ResourceFile(installDir, relativePath); - if (file.exists()) { - try { - return file.toURL(); - } - catch (MalformedURLException e) { - Msg.showError(this, null, "Unexpected Error", - "Unexpected error parsing file to URL: " + file); - } - } - return null; - } - - private URL findModuleFile(String relativePath) { - Collection moduleDirs = Application.getModuleRootDirectories(); - for (ResourceFile dir : moduleDirs) { - ResourceFile file = new ResourceFile(dir, relativePath); - if (file.exists()) { - try { - return file.toURL(); - } - catch (MalformedURLException e) { - Msg.showError(this, null, "Unexpected Error", - "Unexpected error parsing file to URL: " + file); - return null; - } - } - } - return null; - } - - public static void zoomOut() { - fontSizeModifier -= 2; - saveZoomFactor(); - } - - public static void zoomIn() { - fontSizeModifier += 2; - saveZoomFactor(); - } - - private static void saveZoomFactor() { - Preferences.setProperty(HELP_WINDOW_ZOOM_FACTOR, Integer.toString(fontSizeModifier)); - Preferences.store(); - } - -//================================================================================================== -// Inner Classes -//================================================================================================== - - private class GHelpHTMLFactory extends HTMLFactory { - @Override - public View create(Element e) { - - AttributeSet attributes = e.getAttributes(); - Object elementName = attributes.getAttribute(AbstractDocument.ElementNameAttribute); - if (elementName != null) { - // not an HTML element - return super.create(e); - } - - Object html = attributes.getAttribute(StyleConstants.NameAttribute); - if (html instanceof HTML.Tag) { - HTML.Tag tag = (Tag) html; - if (tag == HTML.Tag.IMG) { - return new GHelpImageView(e); - } - } - - return super.create(e); - } - - } - - /** - * Overridden to allow us to find images that are defined as constants in places like - * {@link Icons} - */ - private class GHelpImageView extends ImageView { - - /* - * Unusual Code Alert! - * This class exists to enable our help system to find custom icons defined in source - * code. The default behavior herein is to supply a URL to the base class to load. This - * works fine. - * - * There is another use case where we wish to have the base class load an image of our - * choosing. Why? Well, we modify, in memory, some icons we use. We do this for things - * like overlays and rotations. - * - * In order to have our base class use the image that we want (and not the one - * it loads via a URL), we have to play a small game. We have to allow the base class - * to load the image it wants, which is done asynchronously. If we install our custom - * image during that process, the loading will throw away the image and not render - * anything. - * - * To get the base class to use our image, we override getImage(). However, we should - * only return our image when the base class is finished loading. (See the base class' - * paint() method for why we need to do this.) - * - * Note: if we start seeing unusual behavior, like images not rendering, or any size - * issues, then we can revert this code. - */ - private Image image; - private float spanX; - private float spanY; - - public GHelpImageView(Element elem) { - super(elem); - } - - @Override - public Image getImage() { - Image superImage = super.getImage(); - if (image == null) { - // no custom image - return superImage; - } - - if (isLoading()) { - return superImage; - } - - return image; - } - - private boolean isLoading() { - return spanX < 1 || spanY < 1; - } - - @Override - public float getPreferredSpan(int axis) { - float span = super.getPreferredSpan(axis); - if (axis == View.X_AXIS) { - spanX = span; - } - else { - spanY = span; - } - return span; - } - - @Override - public URL getImageURL() { - - AttributeSet attributes = getElement().getAttributes(); - Object src = attributes.getAttribute(HTML.Attribute.SRC); - if (src == null) { - return null; - } - - String srcString = src.toString(); - if (isJavaCode(srcString)) { - return installImageFromJavaCode(srcString); - } - - URL url = doGetImageURL(srcString); - return url; - } - - private URL installImageFromJavaCode(String srcString) { - - IconProvider iconProvider = getIconFromJavaCode(srcString); - if (iconProvider == null || iconProvider.isInvalid()) { - return null; - } - - this.image = iconProvider.getImage(); - - URL url = iconProvider.getOrCreateUrl(); - return url; - } - - private URL doGetImageURL(String srcString) { - - HTMLDocument htmlDocument = (HTMLDocument) getDocument(); - URL context = htmlDocument.getBase(); - try { - URL url = new URL(context, srcString); - if (FileUtilities.exists(url.toURI())) { - // it's a good one, let it through - return url; - } - } - catch (MalformedURLException | URISyntaxException e) { - // check below - } - - // Try the ResourceManager. This will work for images that start with GHelp - // relative link syntax such as 'help/', 'help/topics/' and 'images/' - URL resource = ResourceManager.getResource(srcString); - return resource; - } - - private boolean isJavaCode(String src) { - // not sure of the best way to handle this--be exact for now - return Icons.isIconsReference(src); - } - - private IconProvider getIconFromJavaCode(String src) { - return Icons.getIconForIconsReference(src); - } - - } - -} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/help/HelpService.java b/Ghidra/Framework/Docking/src/main/java/docking/help/HelpService.java deleted file mode 100644 index 699d12a995..0000000000 --- a/Ghidra/Framework/Docking/src/main/java/docking/help/HelpService.java +++ /dev/null @@ -1,121 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package docking.help; - -import java.awt.Component; -import java.net.URL; - -import ghidra.util.HelpLocation; - -/** - * HelpService defines a service for displaying Help content by an ID or URL. - */ -public interface HelpService { - - public static final String DUMMY_HELP_SET_NAME = "Dummy_HelpSet.hs"; - - /** - * Display the Help content identified by the help object. - * - * @param helpObject the object to which help was previously registered - * @param infoOnly display {@link HelpLocation} information only, not the help UI - * @param parent requesting component - * - * @see #registerHelp(Object, HelpLocation) - */ - public void showHelp(Object helpObject, boolean infoOnly, Component parent); - - /** - * Display the help page for the given URL. This is a specialty method for displaying - * help when a specific file is desired, like an introduction page. Showing help for - * objects within the system is accomplished by calling - * {@link #showHelp(Object, boolean, Component)}. - * - * @param url the URL to display - * @see #showHelp(Object, boolean, Component) - */ - public void showHelp(URL url); - - /** - * Display the help page for the given help location. - * - * @param location the location to display. - * @see #showHelp(Object, boolean, Component) - */ - public void showHelp(HelpLocation location); - - /** - * Signals to the help system to ignore the given object when searching for and validating - * help. Once this method has been called, no help can be registered for the given object. - * - * @param helpObject the object to exclude from the help system. - */ - public void excludeFromHelp(Object helpObject); - - /** - * Returns true if the given object is meant to be ignored by the help system - * - * @param helpObject the object to check - * @return true if ignored - * @see #excludeFromHelp(Object) - */ - public boolean isExcludedFromHelp(Object helpObject); - - /** - * Register help for a specific object. - * - *

Do not call this method will a null help location. Instead, to signal that - * an item has no help, call {@link #excludeFromHelp(Object)}. - * - * @param helpObject the object to associate the specified help location with - * @param helpLocation help content location - */ - public void registerHelp(Object helpObject, HelpLocation helpLocation); - - /** - * Removes this object from the help system. This method is useful, for example, - * when a single Java {@link Component} will have different help locations - * assigned over its lifecycle. - * - * @param helpObject the object for which to clear help - */ - public void clearHelp(Object helpObject); - - /** - * Returns the registered (via {@link #registerHelp(Object, HelpLocation)} help - * location for the given object; null if there is no registered - * help. - * - * @param object The object for which to find a registered HelpLocation. - * @return the registered HelpLocation - * @see #registerHelp(Object, HelpLocation) - */ - public HelpLocation getHelpLocation(Object object); - - /** - * Returns true if the help system has been initialized properly; false if help does not - * exist or is not working. - * - * @return true if the help system has found the applications help content and has finished - * initializing - */ - public boolean helpExists(); - - /** - * Called when a major system even happens, such as changing the system theme. - */ - public void reload(); -} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeColorTable.java b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeColorTable.java new file mode 100644 index 0000000000..fa27f8e86a --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeColorTable.java @@ -0,0 +1,121 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.theme.gui; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.event.*; +import java.beans.PropertyChangeEvent; + +import javax.swing.JPanel; +import javax.swing.ListSelectionModel; +import javax.swing.table.TableColumn; + +import docking.ActionContext; +import docking.action.ActionContextProvider; +import docking.widgets.table.GFilterTable; +import docking.widgets.table.GTable; +import generic.theme.ColorValue; +import generic.theme.Gui; +import ghidra.util.Swing; + +/** + * Color Table for Theme Dialog + */ +public class ThemeColorTable extends JPanel implements ActionContextProvider { + + private ThemeColorTableModel colorTableModel; + private ColorValueEditor colorEditor = new ColorValueEditor(this::colorValueChanged); + private GTable table; + private GFilterTable filterTable; + + public ThemeColorTable() { + super(new BorderLayout()); + colorTableModel = new ThemeColorTableModel(); + + filterTable = new GFilterTable<>(colorTableModel); + table = filterTable.getTable(); + table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + + table.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + ColorValue colorValue = filterTable.getSelectedRowObject(); + if (colorValue != null) { + colorEditor.editValue(colorValue); + } + e.consume(); + } + } + }); + + table.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + ColorValue value = filterTable.getItemAt(e.getPoint()); + + int col = filterTable.getColumn(e.getPoint()); + TableColumn column = table.getColumnModel().getColumn(col); + Object identifier = column.getIdentifier(); + if ("Current Color".equals(identifier) || "Id".equals(identifier)) { + colorEditor.editValue(value); + } + } + } + }); + + add(filterTable, BorderLayout.CENTER); + + } + + void colorValueChanged(PropertyChangeEvent event) { + // run later - don't rock the boat in the middle of a listener callback + Swing.runLater(() -> { + ColorValue newValue = (ColorValue) event.getNewValue(); + Gui.setColor(newValue); + }); + } + + /** + * Returns the current values displayed in the table + */ + public void reloadCurrent() { + colorTableModel.reloadCurrent(); + } + + /** + * Reloads all the values displayed in the table + */ + public void reloadAll() { + colorTableModel.reloadAll(); + } + + @Override + public ActionContext getActionContext(MouseEvent e) { + if (e.getSource() == table) { + ColorValue currentValue = filterTable.getSelectedRowObject(); + if (currentValue == null) { + return null; + } + String id = currentValue.getId(); + ColorValue themeValue = colorTableModel.getThemeValue(id); + return new ThemeTableContext(currentValue, themeValue); + } + return null; + } +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeColorTableModel.java b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeColorTableModel.java index 0b95e002e8..e65591431f 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeColorTableModel.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeColorTableModel.java @@ -66,6 +66,13 @@ public class ThemeColorTableModel extends GDynamicColumnTableModel"; } Color color = resolvedColor.color(); - String text = WebColors.toString(color, false); String name = WebColors.toWebColorName(color); if (resolvedColor.refId() != null) { - return "[" + resolvedColor.refId() + "] " + text; + return "[" + resolvedColor.refId() + "] "; } + String text = WebColors.toString(color, false); if (name != null) { text += " (" + name + ")"; } @@ -250,4 +257,5 @@ public class ThemeColorTableModel extends GDynamicColumnTableModel combo; private ItemListener comboListener = this::themeComboChanged; private ThemeListener listener = new DialogThemeListener(); + private JTabbedPane tabbedPane; + + private ThemeColorTable colorTable; + private ThemeFontTable fontTable; + private ThemeIconTable iconTable; public ThemeDialog() { super("Theme Dialog", false); @@ -69,14 +62,26 @@ public class ThemeDialog extends DialogComponentProvider { updateButtons(); createActions(); Gui.addThemeListener(listener); + setHelpLocation(new HelpLocation("Theming", "Edit_Theme")); } private void createActions() { DockingAction reloadDefaultsAction = new ActionBuilder("Reload Ghidra Defaults", getTitle()) .toolBarIcon(new GIcon("icon.refresh")) + .helpLocation(new HelpLocation("Theming", "Reload_Ghidra_Defaults")) .onAction(e -> reloadDefaultsCallback()) .build(); addAction(reloadDefaultsAction); + + DockingAction resetValueAction = new ActionBuilder("Restore Value", getTitle()) + .popupMenuPath("Restore Value") + .withContext(ThemeTableContext.class) + .enabledWhen(c -> c.isChanged()) + .popupWhen(c -> true) + .helpLocation(new HelpLocation("Theming", "Restore_Value")) + .onAction(c -> c.getThemeValue().makeCurrentValue()) + .build(); + addAction(resetValueAction); } @Override @@ -129,9 +134,9 @@ public class ThemeDialog extends DialogComponentProvider { } private void reset() { - colorTableModel.reloadAll(); - fontTableModel.reloadAll(); - iconTableModel.reloadAll(); + colorTable.reloadAll(); + fontTable.reloadAll(); + iconTable.reloadAll(); updateButtons(); updateCombo(); } @@ -159,45 +164,9 @@ public class ThemeDialog extends DialogComponentProvider { else { setStatusText(""); } - colorTableModel.reloadAll(); - fontTableModel.reloadAll(); - iconTableModel.reloadAll(); - }); - } - - protected void editColor(ColorValue value) { - colorEditor.editValue(value); - } - - protected void editFont(FontValue value) { - fontEditor.editValue(value); - } - - protected void editIcon(IconValue value) { - iconEditor.editValue(value); - } - - void colorValueChanged(PropertyChangeEvent event) { - // run later - don't rock the boat in the middle of a listener callback - Swing.runLater(() -> { - ColorValue newValue = (ColorValue) event.getNewValue(); - Gui.setColor(newValue); - }); - } - - void fontValueChanged(PropertyChangeEvent event) { - // run later - don't rock the boat in the middle of a listener callback - Swing.runLater(() -> { - FontValue newValue = (FontValue) event.getNewValue(); - Gui.setFont(newValue); - }); - } - - void iconValueChanged(PropertyChangeEvent event) { - // run later - don't rock the boat in the middle of a listener callback - Swing.runLater(() -> { - IconValue newValue = (IconValue) event.getNewValue(); - Gui.setIcon(newValue); + colorTable.reloadAll(); + fontTable.reloadAll(); + iconTable.reloadAll(); }); } @@ -253,130 +222,16 @@ public class ThemeDialog extends DialogComponentProvider { } private Component buildTabedTables() { - JTabbedPane tabbedPane = new JTabbedPane(); - tabbedPane.add("Colors", buildColorTable()); - tabbedPane.add("Fonts", buildFontTable()); - tabbedPane.add("Icons", buildIconTable()); + tabbedPane = new JTabbedPane(); + colorTable = new ThemeColorTable(); + fontTable = new ThemeFontTable(); + iconTable = new ThemeIconTable(); + tabbedPane.add("Colors", colorTable); + tabbedPane.add("Fonts", fontTable); + tabbedPane.add("Icons", iconTable); return tabbedPane; } - private JComponent buildFontTable() { - fontTableModel = new ThemeFontTableModel(); - GFilterTable filterTable = new GFilterTable<>(fontTableModel); - GTable table = filterTable.getTable(); - table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - - table.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_ENTER) { - FontValue fontValue = filterTable.getSelectedRowObject(); - if (fontValue != null) { - editFont(fontValue); - } - e.consume(); - } - } - }); - - table.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2) { - FontValue value = filterTable.getItemAt(e.getPoint()); - - int col = filterTable.getColumn(e.getPoint()); - TableColumn column = table.getColumnModel().getColumn(col); - Object identifier = column.getIdentifier(); - if ("Current Font".equals(identifier) || "Id".equals(identifier)) { - editFont(value); - } - } - } - }); - - return filterTable; - - } - - private JComponent buildIconTable() { - iconTableModel = new ThemeIconTableModel(); - GFilterTable filterTable = new GFilterTable<>(iconTableModel); - GTable table = filterTable.getTable(); - table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - - table.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_ENTER) { - IconValue iconValue = filterTable.getSelectedRowObject(); - if (iconValue != null) { - editIcon(iconValue); - } - e.consume(); - } - } - }); - - table.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2) { - IconValue value = filterTable.getItemAt(e.getPoint()); - - int col = filterTable.getColumn(e.getPoint()); - TableColumn column = table.getColumnModel().getColumn(col); - Object identifier = column.getIdentifier(); - if ("Current Icon".equals(identifier) || "Id".equals(identifier)) { - editIcon(value); - } - } - } - }); - - return filterTable; - - } - - private JComponent buildColorTable() { - colorTableModel = new ThemeColorTableModel(); - - GFilterTable filterTable = new GFilterTable<>(colorTableModel); - GTable table = filterTable.getTable(); - table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - - table.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_ENTER) { - ColorValue colorValue = filterTable.getSelectedRowObject(); - if (colorValue != null) { - editColor(colorValue); - } - e.consume(); - } - } - }); - - table.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2) { - ColorValue value = filterTable.getItemAt(e.getPoint()); - - int col = filterTable.getColumn(e.getPoint()); - TableColumn column = table.getColumnModel().getColumn(col); - Object identifier = column.getIdentifier(); - if ("Current Color".equals(identifier) || "Id".equals(identifier)) { - editColor(value); - } - } - } - }); - - return filterTable; - } - private JButton createRestoreButton() { restoreButton = new JButton("Restore"); restoreButton.setMnemonic('R'); @@ -411,6 +266,13 @@ public class ThemeDialog extends DialogComponentProvider { super.close(); } + @Override + public ActionContext getActionContext(MouseEvent event) { + ActionContextProvider contextProvider = + (ActionContextProvider) tabbedPane.getSelectedComponent(); + return contextProvider.getActionContext(event); + } + class DialogThemeListener implements ThemeListener { @Override public void themeChanged(ThemeEvent event) { @@ -419,13 +281,13 @@ public class ThemeDialog extends DialogComponentProvider { return; } if (event.hasAnyColorChanged()) { - colorTableModel.reloadCurrent(); + colorTable.reloadCurrent(); } if (event.hasAnyFontChanged()) { - fontTableModel.reloadCurrent(); + fontTable.reloadCurrent(); } if (event.hasAnyIconChanged()) { - iconTableModel.reloadCurrent(); + iconTable.reloadCurrent(); } updateButtons(); } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeFontTable.java b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeFontTable.java new file mode 100644 index 0000000000..6f9293e8f9 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeFontTable.java @@ -0,0 +1,120 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.theme.gui; + +import java.awt.BorderLayout; +import java.awt.Font; +import java.awt.event.*; +import java.beans.PropertyChangeEvent; + +import javax.swing.JPanel; +import javax.swing.ListSelectionModel; +import javax.swing.table.TableColumn; + +import docking.ActionContext; +import docking.action.ActionContextProvider; +import docking.widgets.table.GFilterTable; +import docking.widgets.table.GTable; +import generic.theme.FontValue; +import generic.theme.Gui; +import ghidra.util.Swing; + +/** + * Font Table for Theme Dialog + */ +public class ThemeFontTable extends JPanel implements ActionContextProvider { + + private ThemeFontTableModel fontTableModel; + private FontValueEditor fontEditor = new FontValueEditor(this::fontValueChanged); + private GTable table; + private GFilterTable filterTable; + + public ThemeFontTable() { + super(new BorderLayout()); + + fontTableModel = new ThemeFontTableModel(); + filterTable = new GFilterTable<>(fontTableModel); + table = filterTable.getTable(); + table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + + table.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + FontValue fontValue = filterTable.getSelectedRowObject(); + if (fontValue != null) { + fontEditor.editValue(fontValue); + } + e.consume(); + } + } + }); + + table.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + FontValue value = filterTable.getItemAt(e.getPoint()); + + int col = filterTable.getColumn(e.getPoint()); + TableColumn column = table.getColumnModel().getColumn(col); + Object identifier = column.getIdentifier(); + if ("Current Font".equals(identifier) || "Id".equals(identifier)) { + fontEditor.editValue(value); + } + } + } + }); + add(filterTable, BorderLayout.CENTER); + + } + + void fontValueChanged(PropertyChangeEvent event) { + // run later - don't rock the boat in the middle of a listener callback + Swing.runLater(() -> { + FontValue newValue = (FontValue) event.getNewValue(); + Gui.setFont(newValue); + }); + } + + /** + * Reloads all the values displayed in the table + */ + public void reloadAll() { + fontTableModel.reloadAll(); + } + + /** + * Returns the current values displayed in the table + */ + public void reloadCurrent() { + fontTableModel.reloadCurrent(); + } + + @Override + public ActionContext getActionContext(MouseEvent e) { + if (e.getSource() == table) { + FontValue currentValue = filterTable.getSelectedRowObject(); + if (currentValue == null) { + return null; + } + String id = currentValue.getId(); + FontValue themeValue = fontTableModel.getThemeValue(id); + return new ThemeTableContext(currentValue, themeValue); + } + return null; + } +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeFontTableModel.java b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeFontTableModel.java index c01b8ebff7..05e229dc90 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeFontTableModel.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeFontTableModel.java @@ -100,7 +100,7 @@ public class ThemeFontTableModel extends GDynamicColumnTableModel"; } if (fontValue.getReferenceId() != null) { - return fontValue.getReferenceId(); + return "[" + fontValue.getReferenceId() + "]"; } Font font = fontValue.getRawValue(); @@ -178,8 +178,6 @@ public class ThemeFontTableModel extends GDynamicColumnTableModel { - private Font regularFont = new Font("Monospaced", Font.BOLD, 12); - private Font indirectFont = new Font("Monospaced", Font.ITALIC, 12); @Override public Component getTableCellRendererComponent(GTableCellRenderingData data) { @@ -187,12 +185,6 @@ public class ThemeFontTableModel extends GDynamicColumnTableModel filterTable; + + public ThemeIconTable() { + super(new BorderLayout()); + iconTableModel = new ThemeIconTableModel(); + filterTable = new GFilterTable<>(iconTableModel); + table = filterTable.getTable(); + table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + + table.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + IconValue iconValue = filterTable.getSelectedRowObject(); + if (iconValue != null) { + iconEditor.editValue(iconValue); + } + e.consume(); + } + } + }); + + table.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + IconValue value = filterTable.getItemAt(e.getPoint()); + + int col = filterTable.getColumn(e.getPoint()); + TableColumn column = table.getColumnModel().getColumn(col); + Object identifier = column.getIdentifier(); + if ("Current Icon".equals(identifier) || "Id".equals(identifier)) { + iconEditor.editValue(value); + } + } + } + }); + add(filterTable, BorderLayout.CENTER); + } + + void iconValueChanged(PropertyChangeEvent event) { + // run later - don't rock the boat in the middle of a listener callback + Swing.runLater(() -> { + IconValue newValue = (IconValue) event.getNewValue(); + Gui.setIcon(newValue); + }); + } + + /** + * Reloads all the values displayed in the table + */ + public void reloadAll() { + iconTableModel.reloadAll(); + } + + /** + * Returns the current values displayed in the table + */ + public void reloadCurrent() { + iconTableModel.reloadCurrent(); + } + + @Override + public ActionContext getActionContext(MouseEvent e) { + if (e.getSource() == table) { + IconValue currentValue = filterTable.getSelectedRowObject(); + if (currentValue == null) { + return null; + } + String id = currentValue.getId(); + IconValue themeValue = iconTableModel.getThemeValue(id); + return new ThemeTableContext(currentValue, themeValue); + } + return null; + } +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeIconTableModel.java b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeIconTableModel.java index 5deb69a4b6..e4888b8368 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeIconTableModel.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeIconTableModel.java @@ -229,8 +229,16 @@ public class ThemeIconTableModel extends GDynamicColumnTableModel the resource type (Color, Font, or Icon) + */ +public class ThemeTableContext extends ActionContext { + + private ThemeValue currentValue; + private ThemeValue themeValue; + + public ThemeTableContext(ThemeValue currentValue, ThemeValue themeValue) { + this.currentValue = currentValue; + this.themeValue = themeValue; + } + + /** + * Returns the currentValue of the selected table row + * @return the currentValue of the selected table row + */ + public ThemeValue getCurrentValue() { + return currentValue; + } + + /** + * Returns the original theme value of the selected table row + * @return the original theme value of the selected table row + */ + public ThemeValue getThemeValue() { + return themeValue; + } + + /** + * Returns true if the current value is not the same as the original theme value for the + * selected table row + * @return true if the current value is not the same as the original theme value for the + * selected table row + */ + public boolean isChanged() { + return !currentValue.equals(themeValue); + } +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/conditiontestpanel/ConditionTestPanel.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/conditiontestpanel/ConditionTestPanel.java index 0f11262225..6942ae9c87 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/conditiontestpanel/ConditionTestPanel.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/conditiontestpanel/ConditionTestPanel.java @@ -365,7 +365,7 @@ public class ConditionTestPanel extends JPanel { public TestPanel(ConditionTester conditionTest) { super(new PairLayout()); backgroundColor = getBackground(); - selectedColor = Color.LIGHT_GRAY; + selectedColor = Palette.LIGHT_GRAY; this.test = conditionTest; checkbox = new GCheckBox(); checkbox.setSelected(true); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/dialogs/MultiLineInputDialog.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/dialogs/MultiLineInputDialog.java index da402f4c5d..b7bfb1848e 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/dialogs/MultiLineInputDialog.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/dialogs/MultiLineInputDialog.java @@ -25,6 +25,7 @@ import docking.DialogComponentProvider; import docking.DockingUtils; import docking.widgets.label.GDLabel; import docking.widgets.label.GLabel; +import generic.theme.GThemeDefaults.Colors.Messages; import ghidra.framework.OperatingSystem; import ghidra.framework.Platform; @@ -87,7 +88,7 @@ public class MultiLineInputDialog extends DialogComponentProvider { Font smallerFont = font.deriveFont(12F); Font smallItalicFont = smallerFont.deriveFont(Font.ITALIC); hintLabel.setFont(smallItalicFont); - hintLabel.setForeground(Color.LIGHT_GRAY); + hintLabel.setForeground(Messages.HINT); dataPanel.add(messageLabel, BorderLayout.NORTH); dataPanel.add(new JScrollPane(inputTextArea), BorderLayout.CENTER); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/textfield/HexOrDecimalInput.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/textfield/HexOrDecimalInput.java index 9614fa62ad..224fbf091d 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/textfield/HexOrDecimalInput.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/textfield/HexOrDecimalInput.java @@ -23,6 +23,7 @@ import javax.swing.JTextField; import javax.swing.text.*; import docking.util.GraphicsUtils; +import generic.theme.GThemeDefaults.Colors.Messages; public class HexOrDecimalInput extends JTextField { private boolean isHexMode = false; @@ -130,7 +131,7 @@ public class HexOrDecimalInput extends JTextField { Font font = new Font("Monospaced", Font.PLAIN, 10); Font savedFont = g.getFont(); g.setFont(font); - g.setColor(Color.LIGHT_GRAY); + g.setColor(Messages.HINT); FontMetrics fontMetrics = getFontMetrics(font); String mode = isHexMode ? "Hex" : "Dec"; int stringWidth = fontMetrics.stringWidth(mode); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/textfield/IntegerTextField.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/textfield/IntegerTextField.java index 80cd18942a..6a22570d44 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/textfield/IntegerTextField.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/textfield/IntegerTextField.java @@ -15,35 +15,19 @@ */ package docking.widgets.textfield; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.Insets; -import java.awt.event.ActionListener; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; +import java.awt.*; +import java.awt.event.*; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; -import javax.swing.JComponent; -import javax.swing.JTextField; -import javax.swing.ToolTipManager; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import javax.swing.text.AbstractDocument; -import javax.swing.text.AttributeSet; -import javax.swing.text.BadLocationException; -import javax.swing.text.Document; -import javax.swing.text.DocumentFilter; +import javax.swing.*; +import javax.swing.event.*; +import javax.swing.text.*; import docking.DockingUtils; import docking.util.GraphicsUtils; +import generic.theme.GThemeDefaults.Colors.Messages; import ghidra.util.SystemUtilities; /** @@ -699,7 +683,7 @@ public class IntegerTextField { Font savedFont = g.getFont(); g.setFont(hintFont); - g.setColor(Color.LIGHT_GRAY); + g.setColor(Messages.HINT); Dimension size = getSize(); Insets insets = getInsets(); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/textfield/LocalDateTextField.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/textfield/LocalDateTextField.java index 9b0d8a96f6..bdf9e96a16 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/textfield/LocalDateTextField.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/textfield/LocalDateTextField.java @@ -31,6 +31,7 @@ import javax.swing.JTextField; import javax.swing.event.*; import docking.util.GraphicsUtils; +import generic.theme.GThemeDefaults.Colors.Messages; import ghidra.util.SystemUtilities; /** @@ -234,7 +235,7 @@ public class LocalDateTextField { Font font = new Font("Monospaced", Font.PLAIN, 10); Font savedFont = g.getFont(); g.setFont(font); - g.setColor(Color.LIGHT_GRAY); + g.setColor(Messages.HINT); FontMetrics fontMetrics = getFontMetrics(font); String label = isMonthMode ? MONTH_LABEL : DAY_LABEL; int stringWidth = fontMetrics.stringWidth(label); diff --git a/Ghidra/Framework/Docking/src/test/java/docking/theme/gui/ThemeUtilsTest.java b/Ghidra/Framework/Docking/src/test/java/docking/theme/gui/ThemeUtilsTest.java index b796e24a7a..79948be124 100644 --- a/Ghidra/Framework/Docking/src/test/java/docking/theme/gui/ThemeUtilsTest.java +++ b/Ghidra/Framework/Docking/src/test/java/docking/theme/gui/ThemeUtilsTest.java @@ -32,12 +32,13 @@ import docking.widgets.OptionDialog; import docking.widgets.SelectFromListDialog; import docking.widgets.dialogs.InputDialog; import generic.theme.*; +import generic.theme.GThemeDefaults.Colors.Palette; import generic.theme.builtin.MetalTheme; import generic.theme.builtin.NimbusTheme; public class ThemeUtilsTest extends AbstractDockingTest { - private Color testColor = Color.RED; + private Color testColor = Palette.RED; @Before public void setup() { diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/ColorValue.java b/Ghidra/Framework/Generic/src/main/java/generic/theme/ColorValue.java index 764b740305..7b869230d2 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/theme/ColorValue.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/theme/ColorValue.java @@ -149,4 +149,9 @@ public class ColorValue extends ThemeValue { return outputString; } + @Override + public void makeCurrentValue() { + Gui.setColor(this); + } + } diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/FontValue.java b/Ghidra/Framework/Generic/src/main/java/generic/theme/FontValue.java index 51ce630368..89f514a580 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/theme/FontValue.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/theme/FontValue.java @@ -223,4 +223,9 @@ public class FontValue extends ThemeValue { return "PLAIN"; } + @Override + public void makeCurrentValue() { + Gui.setFont(this); + } + } diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/IconValue.java b/Ghidra/Framework/Generic/src/main/java/generic/theme/IconValue.java index ffdf7220a6..92fe807611 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/theme/IconValue.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/theme/IconValue.java @@ -146,4 +146,9 @@ public class IconValue extends ThemeValue { return iconToString(value); } + @Override + public void makeCurrentValue() { + Gui.setIcon(this); + } + } diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeValue.java b/Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeValue.java index c1fa9c9ed8..85dd49b9b3 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeValue.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeValue.java @@ -202,4 +202,9 @@ public abstract class ThemeValue implements Comparable> { return name + " (" + id + ", " + referenceId + ")"; } + /** + * Makes this value the current value for the application + */ + public abstract void makeCurrentValue(); + } diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/ComponentFontRegistry.java b/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/ComponentFontRegistry.java index 4a58430d43..9ddc2dca6d 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/ComponentFontRegistry.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/ComponentFontRegistry.java @@ -17,6 +17,7 @@ package generic.theme.laf; import java.awt.Component; import java.awt.Font; +import java.util.Objects; import generic.theme.Gui; import ghidra.util.datastruct.WeakDataStructureFactory; @@ -54,7 +55,10 @@ public class ComponentFontRegistry { public void updateComponentFonts() { Font font = Gui.getFont(fontId); for (Component component : components) { - component.setFont(font); + Font existingFont = component.getFont(); + if (!Objects.equals(existingFont, font)) { + component.setFont(font); + } } } } diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/LookAndFeelManager.java b/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/LookAndFeelManager.java index 12ece6a4e4..6b2afa1b26 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/LookAndFeelManager.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/LookAndFeelManager.java @@ -105,7 +105,7 @@ public abstract class LookAndFeelManager { updateComponentUis(); } - private void updateAllRegisteredComponentFonts() { + protected void updateAllRegisteredComponentFonts() { for (ComponentFontRegistry register : fontRegistryMap.values()) { register.updateComponentFonts(); } @@ -178,21 +178,12 @@ public abstract class LookAndFeelManager { Font font = Gui.getFont(javaFontId); defaults.put(javaFontId, new FontUIResource(font)); } - updateComponentFonts(changedJavaFontIds); updateComponentUis(); } + updateAllRegisteredComponentFonts(); repaintAll(); } - protected void updateComponentFonts(Set changedFontIds) { - for (String javaFontId : changedFontIds) { - ComponentFontRegistry register = fontRegistryMap.get(javaFontId); - if (register != null) { - register.updateComponentFonts(); - } - } - } - protected void updateComponentUis() { for (Window window : Window.getWindows()) { SwingUtilities.updateComponentTreeUI(window); diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/NimbusLookAndFeelManager.java b/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/NimbusLookAndFeelManager.java index 7f17b9bdeb..da432acb63 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/NimbusLookAndFeelManager.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/NimbusLookAndFeelManager.java @@ -48,8 +48,8 @@ public class NimbusLookAndFeelManager extends LookAndFeelManager { public void fontsChanged(Set affectedJavaIds) { if (!affectedJavaIds.isEmpty()) { reinstallNimubus(); - updateComponentFonts(affectedJavaIds); } + updateAllRegisteredComponentFonts(); repaintAll(); } diff --git a/Ghidra/Framework/Generic/src/main/java/resources/IconProvider.java b/Ghidra/Framework/Generic/src/main/java/resources/IconProvider.java index e47046c6b9..1ea123f154 100644 --- a/Ghidra/Framework/Generic/src/main/java/resources/IconProvider.java +++ b/Ghidra/Framework/Generic/src/main/java/resources/IconProvider.java @@ -21,10 +21,10 @@ import java.io.IOException; import java.net.URISyntaxException; import java.net.URL; +import javax.swing.Icon; import javax.swing.ImageIcon; import generic.Images; -import generic.theme.GIcon; import generic.util.image.ImageUtils; import ghidra.util.Msg; @@ -37,18 +37,19 @@ import ghidra.util.Msg; */ public class IconProvider { - private GIcon icon; + private Icon icon; private URL url; private URL tempUrl; private boolean tempFileFailed; - public IconProvider(GIcon icon, URL url) { + public IconProvider(Icon icon, URL url) { this.icon = icon; this.url = url; } public Image getImage() { - return icon.getImageIcon().getImage(); + ImageIcon imageIcon = ResourceManager.getImageIcon(icon); + return imageIcon.getImage(); } public boolean isInvalid() { @@ -96,7 +97,7 @@ public class IconProvider { try { File imageFile = File.createTempFile("temp.help.icon", null); imageFile.deleteOnExit(); // don't let this linger - ImageIcon imageIcon = icon.getImageIcon(); + ImageIcon imageIcon = ResourceManager.getImageIcon(icon); ImageUtils.writeFile(imageIcon.getImage(), imageFile); return imageFile.toURI().toURL(); } diff --git a/Ghidra/Framework/Docking/src/main/java/resources/Icons.java b/Ghidra/Framework/Generic/src/main/java/resources/Icons.java similarity index 95% rename from Ghidra/Framework/Docking/src/main/java/resources/Icons.java rename to Ghidra/Framework/Generic/src/main/java/resources/Icons.java index 478311eb67..87aac38ca0 100644 --- a/Ghidra/Framework/Docking/src/main/java/resources/Icons.java +++ b/Ghidra/Framework/Generic/src/main/java/resources/Icons.java @@ -113,7 +113,7 @@ public class Icons { return null; } - GIcon icon = getIconByFieldName(fieldName); + Icon icon = getIconByFieldName(fieldName); if (icon == null) { return null; } @@ -165,12 +165,12 @@ public class Icons { return fieldName; } - private static GIcon getIconByFieldName(String fieldName) { + private static Icon getIconByFieldName(String fieldName) { try { Field field = Icons.class.getField(fieldName); Object object = field.get(Icons.class); - GIcon icon = (GIcon) object; + Icon icon = (Icon) object; return icon; } catch (Exception e) { @@ -180,16 +180,14 @@ public class Icons { } } - private static URL getUrlFromIcon(GIcon icon) { - if (icon == null) { - return null; + private static URL getUrlFromIcon(Icon icon) { + if (icon instanceof GIcon gIcon) { + URL url = gIcon.getUrl(); + if (url != null) { + return url; + } + Msg.debug(Icons.class, "Unable to get URL for icon"); } - - URL url = icon.getUrl(); - if (url != null) { - return url; - } - Msg.debug(Icons.class, "Unable to get URL for icon"); return null; } diff --git a/Ghidra/Framework/Generic/src/test/java/generic/theme/GuiTest.java b/Ghidra/Framework/Generic/src/test/java/generic/theme/GuiTest.java index 535860d49b..5a7ec20ae4 100644 --- a/Ghidra/Framework/Generic/src/test/java/generic/theme/GuiTest.java +++ b/Ghidra/Framework/Generic/src/test/java/generic/theme/GuiTest.java @@ -24,6 +24,7 @@ import java.net.URL; import java.util.*; import javax.swing.Icon; +import javax.swing.JLabel; import javax.swing.plaf.UIResource; import org.junit.Before; @@ -343,6 +344,17 @@ public class GuiTest { assertEquals(expected, Gui.getApplicationDarkDefaults()); } + @Test + public void testRegisterFont() { + Gui.setFont(new FontValue("font.test", SMALL_FONT)); + JLabel label = new JLabel("Test"); + assertNotEquals(SMALL_FONT, label.getFont()); + Gui.registerFont(label, "font.test"); + assertEquals(SMALL_FONT, label.getFont()); + Gui.setFont(new FontValue("font.test", FONT)); + assertEquals(FONT, label.getFont()); + } + private void assertColor(Color color, GColor gColor) { if (color.getRGB() != gColor.getRGB()) { fail("RGB values don't match! Expected " + color + " but got " + gColor); diff --git a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphComponent.java b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphComponent.java index 199541898d..169c2e6656 100644 --- a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphComponent.java +++ b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/GraphComponent.java @@ -27,7 +27,6 @@ import com.google.common.base.Function; import docking.DockingUtils; import docking.DockingWindowManager; import docking.actions.KeyBindingUtils; -import docking.help.HelpService; import docking.widgets.EmptyBorderButton; import docking.widgets.PopupWindow; import docking.widgets.label.GIconLabel; diff --git a/Ghidra/Framework/Graph/src/test/java/ghidra/graph/algo/viewer/AlgorithmTestSteppingVertex.java b/Ghidra/Framework/Graph/src/test/java/ghidra/graph/algo/viewer/AlgorithmTestSteppingVertex.java index 557e7d2b53..407a2933ec 100644 --- a/Ghidra/Framework/Graph/src/test/java/ghidra/graph/algo/viewer/AlgorithmTestSteppingVertex.java +++ b/Ghidra/Framework/Graph/src/test/java/ghidra/graph/algo/viewer/AlgorithmTestSteppingVertex.java @@ -88,7 +88,7 @@ public class AlgorithmTestSteppingVertex extends AbstractTestVertex private void buildShapes() { - defaultShape = buildCircleShape(Color.LIGHT_GRAY, "default"); + defaultShape = buildCircleShape(Palette.LIGHT_GRAY, "default"); defaultWithPathShape = buildCircleShape(new GColor("color.palette.yellowgreen"), "default; was in path"); scheduledShape = buildCircleShape(new GColor("color.palette.khaki"), "scheduled"); diff --git a/Ghidra/Framework/Graph/src/test/java/ghidra/service/graph/GraphDisplayOptionsTest.java b/Ghidra/Framework/Graph/src/test/java/ghidra/service/graph/GraphDisplayOptionsTest.java index 17f33d0678..193033bc38 100644 --- a/Ghidra/Framework/Graph/src/test/java/ghidra/service/graph/GraphDisplayOptionsTest.java +++ b/Ghidra/Framework/Graph/src/test/java/ghidra/service/graph/GraphDisplayOptionsTest.java @@ -28,7 +28,6 @@ import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.framework.options.Options; import ghidra.framework.options.ToolOptions; import ghidra.util.HelpLocation; -import ghidra.util.WebColors; public class GraphDisplayOptionsTest { @@ -154,9 +153,9 @@ public class GraphDisplayOptionsTest { vertex.setVertexType("V1"); assertEquals(Palette.RED, options.getVertexColor(vertex)); - vertex.setAttribute("Color", WebColors.toString(Palette.BLUE)); + vertex.setAttribute("Color", Palette.BLUE.toString()); - assertEquals(Palette.BLUE, options.getVertexColor(vertex)); + assertEquals(Palette.BLUE.getRGB(), options.getVertexColor(vertex).getRGB()); } @Test @@ -184,9 +183,9 @@ public class GraphDisplayOptionsTest { edge.setEdgeType("E1"); assertEquals(Palette.RED, options.getEdgeColor(edge)); - edge.setAttribute("Color", WebColors.toString(Palette.BLUE)); + edge.setAttribute("Color", Palette.BLUE.toString()); - assertEquals(Palette.BLUE, options.getEdgeColor(edge)); + assertEquals(Palette.BLUE.getRGB(), options.getEdgeColor(edge).getRGB()); } @Test @@ -269,7 +268,7 @@ public class GraphDisplayOptionsTest { AttributedVertex vertex = new AttributedVertex("Foo"); vertex.setVertexType("V1"); - assertEquals(Palette.BLUE, options.getVertexColor(vertex)); + assertEquals(Palette.BLUE.getRGB(), options.getVertexColor(vertex).getRGB()); Options graphDisplayOptions = toolOptions.getOptions(options.getRootOptionsName()); Options vertexColorOptions = graphDisplayOptions.getOptions("Vertex Colors"); diff --git a/Ghidra/Framework/Help/src/main/java/docking/DefaultHelpService.java b/Ghidra/Framework/Help/src/main/java/docking/DefaultHelpService.java index 42ff57ade0..b103ee06d0 100644 --- a/Ghidra/Framework/Help/src/main/java/docking/DefaultHelpService.java +++ b/Ghidra/Framework/Help/src/main/java/docking/DefaultHelpService.java @@ -74,6 +74,11 @@ public class DefaultHelpService implements HelpService { return false; } + @Override + public void reload() { + // no-op + } + private void displayHelpInfo(Object helpObj) { String msg = getHelpInfo(helpObj); Msg.showInfo(this, null, "Help Info", msg); diff --git a/Ghidra/Framework/Help/src/main/java/help/GHelpBroker.java b/Ghidra/Framework/Help/src/main/java/help/GHelpBroker.java index 2912226ba5..54484b9c1d 100644 --- a/Ghidra/Framework/Help/src/main/java/help/GHelpBroker.java +++ b/Ghidra/Framework/Help/src/main/java/help/GHelpBroker.java @@ -46,6 +46,7 @@ public class GHelpBroker extends DefaultHelpBroker { protected JEditorPane htmlEditorPane; private Window activationWindow; + private boolean initialized; /** * Construct a new GhidraHelpBroker. @@ -89,6 +90,22 @@ public class GHelpBroker extends DefaultHelpBroker { } } + public void reload() { + clearHighlights(); + initialized = false; + if (isDisplayed()) { + setDisplayed(false); + setDisplayed(true); + } + } + + private void clearHighlights() { + TextHelpModel helpModel = (TextHelpModel) getCustomHelpModel(); + if (helpModel != null) { + helpModel.removeAllHighlights(); + } + } + protected void showNavigationAid(URL url) { // this base class does not have a navigation aid } @@ -134,7 +151,7 @@ public class GHelpBroker extends DefaultHelpBroker { } private void initializeScreenDevice() { - if (isInitialized()) { + if (initialized) { return; } @@ -179,20 +196,21 @@ public class GHelpBroker extends DefaultHelpBroker { initializeUIComponents(contentPane); } - private boolean isInitialized() { - return htmlEditorPane != null; - } - private void initializeUIComponents(Container contentPane) { - if (isInitialized()) { + if (initialized) { return;// already initialized } Component[] components = contentPane.getComponents(); JHelp jHelp = (JHelp) components[0]; - addCustomToolbarItems(jHelp); JHelpContentViewer contentViewer = jHelp.getContentViewer(); + JEditorPane activeHtmlPane = getHTMLEditorPane(contentViewer); + if (activeHtmlPane == htmlEditorPane && initialized) { + return; // already initialized + } + + addCustomToolbarItems(jHelp); htmlEditorPane = getHTMLEditorPane(contentViewer); // just creating the search wires everything together @@ -203,6 +221,7 @@ public class GHelpBroker extends DefaultHelpBroker { } installActions(jHelp); + initialized = true; } protected void installHelpSearcher(JHelp jHelp, HelpModel helpModel) { diff --git a/Ghidra/Framework/Help/src/main/java/help/GHelpHTMLEditorKit.java b/Ghidra/Framework/Help/src/main/java/help/GHelpHTMLEditorKit.java index 9598c6100a..59b58ebec9 100644 --- a/Ghidra/Framework/Help/src/main/java/help/GHelpHTMLEditorKit.java +++ b/Ghidra/Framework/Help/src/main/java/help/GHelpHTMLEditorKit.java @@ -26,7 +26,6 @@ import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.swing.ImageIcon; import javax.swing.JEditorPane; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; @@ -496,8 +495,7 @@ public class GHelpHTMLEditorKit extends HTMLEditorKit { return null; } - ImageIcon imageIcon = iconProvider.getIcon(); - this.image = imageIcon.getImage(); + this.image = iconProvider.getImage(); URL url = iconProvider.getOrCreateUrl(); return url; diff --git a/Ghidra/Framework/Help/src/main/java/help/HelpService.java b/Ghidra/Framework/Help/src/main/java/help/HelpService.java index bdf2e643be..969c97730a 100644 --- a/Ghidra/Framework/Help/src/main/java/help/HelpService.java +++ b/Ghidra/Framework/Help/src/main/java/help/HelpService.java @@ -113,4 +113,9 @@ public interface HelpService { * initializing */ public boolean helpExists(); + + /** + * Called when a major system even happens, such as changing the system theme. + */ + public void reload(); } diff --git a/Ghidra/Framework/Project/build.gradle b/Ghidra/Framework/Project/build.gradle index 0805a5b938..d13ff51ca6 100644 --- a/Ghidra/Framework/Project/build.gradle +++ b/Ghidra/Framework/Project/build.gradle @@ -18,6 +18,7 @@ apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle" apply from: "$rootProject.projectDir/gradle/javadoc.gradle" + apply plugin: 'eclipse' eclipse.project.name = 'Framework Project' diff --git a/Ghidra/Framework/Project/certification.manifest b/Ghidra/Framework/Project/certification.manifest index 642d3e7b64..87a4a528ff 100644 --- a/Ghidra/Framework/Project/certification.manifest +++ b/Ghidra/Framework/Project/certification.manifest @@ -9,6 +9,12 @@ Module.manifest||GHIDRA||||END| data/ExtensionPoint.manifest||GHIDRA||||END| data/project.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/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| +src/main/help/help/topics/Theming/images/ThemeDialog.png||GHIDRA||||END| src/main/java/ghidra/framework/cmd/package.html||GHIDRA||reviewed||END| src/main/java/ghidra/framework/data/package.html||GHIDRA||reviewed||END| src/main/java/ghidra/framework/model/package.html||GHIDRA||||END| diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/app/plugin/gui/ThemeManagerPlugin.java b/Ghidra/Framework/Project/src/main/java/ghidra/app/plugin/gui/ThemeManagerPlugin.java index c71d9ed133..764974e0e3 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/app/plugin/gui/ThemeManagerPlugin.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/app/plugin/gui/ThemeManagerPlugin.java @@ -23,6 +23,7 @@ import ghidra.framework.main.ApplicationLevelOnlyPlugin; import ghidra.framework.main.UtilityPluginPackage; import ghidra.framework.plugintool.*; import ghidra.framework.plugintool.util.PluginStatus; +import ghidra.util.HelpLocation; //@formatter:off @PluginInfo( @@ -49,31 +50,35 @@ public class ThemeManagerPlugin extends Plugin implements ApplicationLevelOnlyPl new ActionBuilder("Edit Theme", owner) .menuPath("Edit", "Theme") .menuGroup(group, "1") + .helpLocation(new HelpLocation("Theming", "Edit_Theme")) .onAction(e -> ThemeDialog.editTheme()) .buildAndInstall(tool); - new ActionBuilder("Reset To Default", owner) - .menuPath("Edit", themeSubMenu, "Reset To Default") + new ActionBuilder("Reset", owner) + .menuPath("Edit", themeSubMenu, "Reset Theme Values") .menuGroup(group, "2") + .helpLocation(new HelpLocation("Theming", "Reset_Theme_Values")) .onAction(e -> ThemeUtils.resetThemeToDefault()) .buildAndInstall(tool); new ActionBuilder("Import Theme", owner) .menuPath("Edit", themeSubMenu, "Import...") .menuGroup(group, "3") + .helpLocation(new HelpLocation("Theming", "Import_Theme")) .onAction(e -> ThemeUtils.importTheme()) .buildAndInstall(tool); new ActionBuilder("Export Theme", owner) .menuPath("Edit", themeSubMenu, "Export...") .menuGroup(group, "4") + .helpLocation(new HelpLocation("Theming", "Export_Theme")) .onAction(e -> ThemeUtils.exportTheme()) .buildAndInstall(tool); new ActionBuilder("Delete Theme", owner) .menuPath("Edit", themeSubMenu, "Delete...") .menuGroup(group, "5") -// .enabledWhen(e -> Gui.getActiveTheme() instanceof FileGTheme) + .helpLocation(new HelpLocation("Theming", "Delete_Theme")) .onAction(e -> ThemeUtils.deleteTheme()) .buildAndInstall(tool); diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ImportGhidraToolsDialog.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ImportGhidraToolsDialog.java index 58b05bc612..235f27074f 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ImportGhidraToolsDialog.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ImportGhidraToolsDialog.java @@ -31,6 +31,7 @@ import docking.tool.ToolConstants; import docking.widgets.checkbox.GCheckBox; import docking.widgets.list.ListPanel; import generic.theme.GThemeDefaults.Colors; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.framework.ToolUtils; import ghidra.framework.model.ToolTemplate; import ghidra.util.HelpLocation; @@ -183,7 +184,7 @@ class ImportGhidraToolsDialog extends DialogComponentProvider { while (itr.hasNext()) { tools[count] = itr.next(); checkboxes[count] = new GCheckBox(tools[count], false); - checkboxes[count].setBackground(Color.LIGHT_GRAY); + checkboxes[count].setBackground(Palette.LIGHT_GRAY); count++; } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/SetToolAssociationsDialog.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/SetToolAssociationsDialog.java index f706036933..0ffa03142a 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/SetToolAssociationsDialog.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/SetToolAssociationsDialog.java @@ -15,15 +15,16 @@ */ package ghidra.framework.main; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Component; import java.util.*; -import java.util.List; import javax.swing.*; import docking.DialogComponentProvider; import docking.tool.ToolConstants; import docking.widgets.table.*; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.framework.data.ContentHandler; import ghidra.framework.model.*; import ghidra.framework.project.tool.GhidraToolTemplate; @@ -239,8 +240,10 @@ class SetToolAssociationsDialog extends DialogComponentProvider { private class ContentHandlerComparator implements Comparator { @Override public int compare(ToolAssociationInfo o1, ToolAssociationInfo o2) { - return o1.getContentHandler().getContentType().compareTo( - o2.getContentHandler().getContentType()); + return o1.getContentHandler() + .getContentType() + .compareTo( + o2.getContentHandler().getContentType()); } } @@ -298,7 +301,7 @@ class SetToolAssociationsDialog extends DialogComponentProvider { return; } - renderer.setForeground(Color.LIGHT_GRAY); + renderer.setForeground(Palette.LIGHT_GRAY); Icon icon = null; if (template.getName().equals(info.getAssociatedToolName())) { diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/AbstractSearchScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/AbstractSearchScreenShots.java index 3e0d03cbdc..eec2c8d5c8 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/AbstractSearchScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/AbstractSearchScreenShots.java @@ -19,12 +19,14 @@ import java.awt.Color; import javax.swing.JFrame; +import generic.theme.GThemeDefaults.Colors.Palette; + /*package*/ abstract class AbstractSearchScreenShots extends GhidraScreenShotGenerator { - protected static final Color YELLOW_ORANGE = new Color(155, 150, 50); - protected static final Color BLUE_GREEN = new Color(0, 128, 64); - protected static final Color DARK_BLUE = new Color(0, 0, 128); - protected static final Color DARK_GREEN = new Color(0, 128, 0); + protected static final Color YELLOW_ORANGE = Palette.getColor("darkkhaki"); + protected static final Color BLUE_GREEN = Palette.GREEN; + protected static final Color DARK_BLUE = Palette.getColor("navy"); + protected static final Color DARK_GREEN = Palette.getColor("darkgreen"); @Override protected String getHelpTopicName() { diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/AutoAnalysisPluginScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/AutoAnalysisPluginScreenShots.java index e7512c51e6..0817d08c90 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/AutoAnalysisPluginScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/AutoAnalysisPluginScreenShots.java @@ -22,6 +22,8 @@ import java.util.concurrent.CountDownLatch; import org.junit.Test; import docking.DialogComponentProvider; +import generic.theme.GThemeDefaults.Colors; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.framework.cmd.BackgroundCommand; import ghidra.framework.model.DomainObject; import ghidra.util.task.TaskMonitor; @@ -37,29 +39,29 @@ public class AutoAnalysisPluginScreenShots extends GhidraScreenShotGenerator { // not tool for this test } -@Test - public void testAutoAnalysis() { - Color darkGreen = new Color(20, 154, 65); - Color darkBlue = new Color(10, 62, 149); + @Test + public void testAutoAnalysis() { + Color darkGreen = Palette.GREEN; + Color darkBlue = Palette.getColor("darkblue"); image = new BufferedImage(700, 400, BufferedImage.TYPE_INT_ARGB); Graphics g = image.getGraphics(); - g.setColor(Color.WHITE); + g.setColor(Colors.BACKGROUND); g.fillRect(0, 0, 700, 400); - drawText("(1) User Disassembles Code", Color.BLACK, new Point(160, 30), 24); + drawText("(1) User Disassembles Code", Colors.FOREGROUND, new Point(160, 30), 24); drawArrow(darkBlue, new Point(325, 35), new Point(325, 70)); drawText("(new code)", darkGreen, new Point(270, 90), 24); - drawText("(2) Function Analyzer", Color.BLACK, new Point(0, 150), 24); + drawText("(2) Function Analyzer", Colors.FOREGROUND, new Point(0, 150), 24); drawArrow(darkBlue, new Point(265, 82), new Point(180, 120)); drawText("(new function)", darkGreen, new Point(100, 190), 24); - drawText("(3) Stack Analyzer", Color.BLACK, new Point(10, 230), 24); + drawText("(3) Stack Analyzer", Colors.FOREGROUND, new Point(10, 230), 24); drawArrow(darkBlue, new Point(50, 155), new Point(50, 205)); - drawText("(4) Operand Analyzer", Color.BLACK, new Point(180, 290), 24); + drawText("(4) Operand Analyzer", Colors.FOREGROUND, new Point(180, 290), 24); drawArrow(darkBlue, new Point(300, 94), new Point(300, 260)); - drawText("(5) Data Reference Analyzer", Color.BLACK, new Point(280, 350), 24); + drawText("(5) Data Reference Analyzer", Colors.FOREGROUND, new Point(280, 350), 24); drawArrow(darkBlue, new Point(350, 94), new Point(490, 325)); Point p1 = new Point(447, 355); @@ -71,14 +73,14 @@ public class AutoAnalysisPluginScreenShots extends GhidraScreenShotGenerator { drawArrow(darkBlue, p3, new Point(404, 88)); } -@Test - public void testCaptureAutoAnalysisOptions() { + @Test + public void testCaptureAutoAnalysisOptions() { showAnalysisOptions("Data Reference"); captureDialog(800, 400); } -@Test - public void testCaptureBackgroundAnalysisTasks() throws InterruptedException { + @Test + public void testCaptureBackgroundAnalysisTasks() throws InterruptedException { CountDownLatch start = new CountDownLatch(1); CountDownLatch end = new CountDownLatch(1); TestBackgroundCommand cmd = new TestBackgroundCommand(start, end); @@ -92,8 +94,8 @@ public class AutoAnalysisPluginScreenShots extends GhidraScreenShotGenerator { crop(new Rectangle(width - 400, height - 120, 400, 120)); } -@Test - public void testCaptureProgramOptions() { + @Test + public void testCaptureProgramOptions() { showProgramOptions("Analyzers"); DialogComponentProvider dialog = getDialog(); Component comp = findComponentByName(dialog.getComponent(), "Analysis Panel"); @@ -122,12 +124,7 @@ public class AutoAnalysisPluginScreenShots extends GhidraScreenShotGenerator { monitor.initialize(100); monitor.setProgress(65); monitor.setMessage("Applying Function Signatures"); - runSwing(new Runnable() { - @Override - public void run() { - invokeInstanceMethod("update", monitor); - } - }); + runSwing(() -> invokeInstanceMethod("update", monitor)); start.countDown(); try { diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/BlockModelScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/BlockModelScreenShots.java index a2be1190e3..d111e8c4b1 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/BlockModelScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/BlockModelScreenShots.java @@ -21,6 +21,7 @@ import java.util.List; import org.junit.Test; +import generic.theme.TempColorUtils; import ghidra.GhidraOptions; import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin; import ghidra.app.plugin.core.colorizer.ColorizingService; @@ -38,7 +39,7 @@ import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSet; import ghidra.program.model.block.*; import ghidra.util.exception.CancelledException; -import ghidra.util.task.TaskMonitorAdapter; +import ghidra.util.task.TaskMonitor; public class BlockModelScreenShots extends GhidraScreenShotGenerator { @@ -95,16 +96,16 @@ public class BlockModelScreenShots extends GhidraScreenShotGenerator { ColorizingService colorizer = tool.getService(ColorizingService.class); - Color c1 = new Color(0xE8F2FE); - - Color c2 = new Color(170, 204, 245); + // note: 2 colors that look good together and are just used for this example + Color c1 = TempColorUtils.fromRgb(232, 242, 254); // alice blue; + Color c2 = TempColorUtils.fromRgb(170, 204, 245); // light sky blue Color color = c1; BasicBlockModel basicBlockModel = new BasicBlockModel(program); CodeBlockIterator iterator; try { iterator = basicBlockModel.getCodeBlocksContaining(addressSet, - TaskMonitorAdapter.DUMMY_MONITOR); + TaskMonitor.DUMMY); while (iterator.hasNext()) { CodeBlock block = iterator.next(); @@ -176,8 +177,9 @@ public class BlockModelScreenShots extends GhidraScreenShotGenerator { if (fieldFactory.getFieldName().indexOf("XRef") != -1) { formatModel.removeFactory(row, col); } - else if (fieldFactory.getFieldName().equals( - EolCommentFieldFactory.FIELD_NAME)) { + else if (fieldFactory.getFieldName() + .equals( + EolCommentFieldFactory.FIELD_NAME)) { formatModel.removeFactory(row, col); } else if (fieldFactory.getFieldName().equals(AddressFieldFactory.FIELD_NAME)) { diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ClipboardPluginScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ClipboardPluginScreenShots.java index 12cf132b93..676a77304a 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ClipboardPluginScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ClipboardPluginScreenShots.java @@ -28,6 +28,7 @@ import docking.DialogComponentProvider; import docking.action.DockingAction; import docking.action.DockingActionIf; import docking.widgets.fieldpanel.FieldPanel; +import generic.theme.GThemeDefaults.Colors.Java; import ghidra.app.plugin.core.clipboard.*; import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin; import ghidra.app.plugin.core.codebrowser.CodeViewerProvider; @@ -74,7 +75,7 @@ public class ClipboardPluginScreenShots extends GhidraScreenShotGenerator { captureListingCallMnemonic(start, end); placeImagesSideBySide(image, menuImage); - drawBorder(Color.BLACK); + drawBorder(Java.BORDER); } private void cropCopyMenu() { @@ -149,21 +150,18 @@ public class ClipboardPluginScreenShots extends GhidraScreenShotGenerator { Object listPanel = getInstanceField("listPanel", copySpecialDialog); final JList list = (JList) getInstanceField("list", listPanel); - runSwing(new Runnable() { - @Override - public void run() { - ListModel model = list.getModel(); - int size = model.getSize(); - for (int i = 0; i < size; i++) { - Object value = model.getElementAt(i); - if ("Labels and Comments".equals(value.toString())) { - list.setSelectedIndex(i); - return; - } + runSwing(() -> { + ListModel model = list.getModel(); + int size = model.getSize(); + for (int i = 0; i < size; i++) { + Object value = model.getElementAt(i); + if ("Labels and Comments".equals(value.toString())) { + list.setSelectedIndex(i); + return; } - - throw new RuntimeException("Could not find 'Labels and Comments' copy action"); } + + throw new RuntimeException("Could not find 'Labels and Comments' copy action"); }); waitForSwing(); } diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/CodeBrowserPluginScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/CodeBrowserPluginScreenShots.java index 758592eec5..6bac7e2829 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/CodeBrowserPluginScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/CodeBrowserPluginScreenShots.java @@ -28,6 +28,9 @@ import org.junit.Test; import docking.DockableComponent; import docking.widgets.fieldpanel.FieldPanel; +import generic.theme.GThemeDefaults.Colors; +import generic.theme.GThemeDefaults.Colors.Java; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.GhidraOptions; import ghidra.app.cmd.comments.SetCommentCmd; import ghidra.app.cmd.data.CreateDataCmd; @@ -71,7 +74,7 @@ public class CodeBrowserPluginScreenShots extends GhidraScreenShotGenerator { Rectangle cursor = getCursorBounds(); captureListingRange(0x0040be40, 0x0040be56, 600); - drawBorder(Color.BLACK); + drawBorder(Java.BORDER); drawTextWithArrowNearOpenStructureIcon("Closed", cursor); @@ -92,7 +95,7 @@ public class CodeBrowserPluginScreenShots extends GhidraScreenShotGenerator { Rectangle cursor = getCursorBounds(); captureListingRange(0x0040be40, 0x0040be56, 600); - drawBorder(Color.BLACK); + drawBorder(Java.BORDER); drawTextWithArrowNearOpenStructureIcon("Open", cursor); } @@ -102,7 +105,7 @@ public class CodeBrowserPluginScreenShots extends GhidraScreenShotGenerator { // Make some room to draw our annotations (text and an arrow) // Dimension whitespace = new Dimension(150, 10); - padImage(Color.WHITE, whitespace.height, whitespace.width, 10, 10); + padImage(Colors.BACKGROUND, whitespace.height, whitespace.width, 10, 10); // // Draw text inside of the newly padded space @@ -112,14 +115,14 @@ public class CodeBrowserPluginScreenShots extends GhidraScreenShotGenerator { int textStartY = arrowStartY - 4;// up just a bit Point textPoint = new Point(textStartX, textStartY); int size = 24; - Color textColor = Color.MAGENTA.darker(); + Color textColor = Palette.PURPLE; drawText(text, textColor, textPoint, size); // // Draw an arrow from the text above to the 'open structure' icon // int arrowStartX = 60; - Color arrowColor = Color.GREEN.darker(); + Color arrowColor = Palette.GREEN; Point arrowStart = new Point(arrowStartX, arrowStartY); int addressFieldStartX = 40; int listingOffsetX = whitespace.width; @@ -205,14 +208,14 @@ public class CodeBrowserPluginScreenShots extends GhidraScreenShotGenerator { captureListingRange(topAddr, bottomAddr, 600); int padX = 100; - padImage(Color.LIGHT_GRAY, 0, padX, 0, 0); + padImage(Palette.LIGHT_GRAY, 0, padX, 0, 0); int y = conditional.y + 10; - drawText("Conditional", Color.BLACK, new Point(10, y), 12); - drawText(" Jump", Color.BLACK, new Point(10, y + 15), 12); + drawText("Conditional", Colors.FOREGROUND, new Point(10, y), 12); + drawText(" Jump", Colors.FOREGROUND, new Point(10, y + 15), 12); y = unconditional.y + 10; - drawText("Unconditional", Color.BLACK, new Point(10, y), 12); - drawText(" Jump", Color.BLACK, new Point(10, y + 15), 12); + drawText("Unconditional", Colors.FOREGROUND, new Point(10, y), 12); + drawText(" Jump", Colors.FOREGROUND, new Point(10, y + 15), 12); } @@ -288,7 +291,7 @@ public class CodeBrowserPluginScreenShots extends GhidraScreenShotGenerator { int width = image.getWidth(null); crop(new Rectangle(0, 0, width, 30)); - drawOval(new Color(107, 47, 109), + drawOval(Palette.PURPLE, new Rectangle(p.x - 13, p.y - 1, bounds.width + 26, bounds.height + 2), 4); } @@ -318,7 +321,7 @@ public class CodeBrowserPluginScreenShots extends GhidraScreenShotGenerator { int y = p.y - 2; int height = bounds.height + 12; int width = bounds.width + 34; - Color color = new Color(120, 0, 64); + Color color = Palette.PURPLE; drawOval(color, new Rectangle(x, y, width, height), 5); int arrowHeadX = x + (width / 4); diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/DecompilePluginScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/DecompilePluginScreenShots.java index 86e3c8a3b2..b068e7fb28 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/DecompilePluginScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/DecompilePluginScreenShots.java @@ -24,15 +24,16 @@ import org.junit.Test; import docking.ComponentProvider; import docking.DockableComponent; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.plugin.core.codebrowser.CodeViewerProvider; import ghidra.app.plugin.core.datamgr.DataTypesProvider; import ghidra.app.plugin.core.programtree.ViewManagerComponentProvider; public class DecompilePluginScreenShots extends GhidraScreenShotGenerator { - private static final Color DARK_BLUE = new Color(0, 0, 128); - private static final Color DARK_GREEN = new Color(0, 128, 0); - private static final Color YELLOW_ORANGE = new Color(155, 150, 50); - private static final Color PURPLE = new Color(155, 50, 155); + private static final Color DARK_BLUE = Palette.getColor("navy"); + private static final Color DARK_GREEN = Palette.GREEN; + private static final Color YELLOW_ORANGE = Palette.getColor("darkkhaki"); + private static final Color PURPLE = Palette.PURPLE; public DecompilePluginScreenShots() { super(); @@ -57,12 +58,12 @@ public class DecompilePluginScreenShots extends GhidraScreenShotGenerator { @Test public void testDefuse() { TextFormatter tf = new TextFormatter(17, 400, 4, 5, 0); - TextFormatterContext hl = new TextFormatterContext(Color.BLACK, Color.YELLOW); - TextFormatterContext red = new TextFormatterContext(Color.RED, Color.WHITE); - TextFormatterContext blue = new TextFormatterContext(Color.BLUE, Color.WHITE); - TextFormatterContext green = new TextFormatterContext(Color.GREEN, Color.WHITE); + TextFormatterContext hl = new TextFormatterContext(Palette.BLACK, Palette.YELLOW); + TextFormatterContext red = new TextFormatterContext(Palette.RED, Palette.WHITE); + TextFormatterContext blue = new TextFormatterContext(Palette.BLUE, Palette.WHITE); + TextFormatterContext green = new TextFormatterContext(Palette.GREEN, Palette.WHITE); TextFormatterContext cursorhl = - new TextFormatterContext(Color.BLACK, Color.YELLOW, Color.RED); + new TextFormatterContext(Palette.BLACK, Palette.YELLOW, Palette.RED); tf.writeln("|void| |max_retry|(node *ptr)", blue, red); tf.writeln(""); @@ -87,12 +88,12 @@ public class DecompilePluginScreenShots extends GhidraScreenShotGenerator { @Test public void testForwardSlice() { TextFormatter tf = new TextFormatter(16, 500, 4, 5, 0); - TextFormatterContext hl = new TextFormatterContext(Color.BLACK, Color.YELLOW); - TextFormatterContext red = new TextFormatterContext(Color.RED); - TextFormatterContext blue = new TextFormatterContext(Color.BLUE); - TextFormatterContext green = new TextFormatterContext(Color.GREEN); + TextFormatterContext hl = new TextFormatterContext(Palette.BLACK, Palette.YELLOW); + TextFormatterContext red = new TextFormatterContext(Palette.RED); + TextFormatterContext blue = new TextFormatterContext(Palette.BLUE); + TextFormatterContext green = new TextFormatterContext(Palette.GREEN); TextFormatterContext cursorhl = - new TextFormatterContext(Color.BLACK, Color.YELLOW, Color.RED); + new TextFormatterContext(Palette.BLACK, Palette.YELLOW, Palette.RED); tf.writeln(" a = psParm2->id;"); tf.writeln(" |b| = |max_alpha|(psParm1->next,psParm1->id);", cursorhl, red); @@ -117,13 +118,13 @@ public class DecompilePluginScreenShots extends GhidraScreenShotGenerator { @Test public void testBackwardSlice() { TextFormatter tf = new TextFormatter(16, 500, 4, 5, 0); - TextFormatterContext hl = new TextFormatterContext(Color.BLACK, Color.YELLOW); - TextFormatterContext red = new TextFormatterContext(Color.RED, Color.WHITE); - TextFormatterContext blue = new TextFormatterContext(Color.BLUE, Color.WHITE); - TextFormatterContext green = new TextFormatterContext(Color.GREEN, Color.WHITE); - TextFormatterContext greenhl = new TextFormatterContext(Color.GREEN, Color.YELLOW); + TextFormatterContext hl = new TextFormatterContext(Palette.BLACK, Palette.YELLOW); + TextFormatterContext red = new TextFormatterContext(Palette.RED, Palette.WHITE); + TextFormatterContext blue = new TextFormatterContext(Palette.BLUE, Palette.WHITE); + TextFormatterContext green = new TextFormatterContext(Palette.GREEN, Palette.WHITE); + TextFormatterContext greenhl = new TextFormatterContext(Palette.GREEN, Palette.YELLOW); TextFormatterContext cursorhl = - new TextFormatterContext(Color.BLACK, Color.YELLOW, Color.RED); + new TextFormatterContext(Palette.BLACK, Palette.YELLOW, Palette.RED); tf.writeln(" |a| = |psParm2|->id;", hl, hl); tf.writeln(" b = |max_alpha|(|psParm1|->next,|psParm1|->id);", red, hl, hl); @@ -188,12 +189,12 @@ public class DecompilePluginScreenShots extends GhidraScreenShotGenerator { Font font = new Font("Monospaced", Font.PLAIN, 12); TextFormatter tf = new TextFormatter(font, 15, 400, 4, 14, 1); - TextFormatterContext blue = new TextFormatterContext(Color.BLUE); + TextFormatterContext blue = new TextFormatterContext(Palette.BLUE); TextFormatterContext darkBlue = new TextFormatterContext(DARK_BLUE); TextFormatterContext darkGreen = new TextFormatterContext(DARK_GREEN); TextFormatterContext orange = new TextFormatterContext(YELLOW_ORANGE); TextFormatterContext purple = new TextFormatterContext(PURPLE); - tf.colorLines(new Color(180, 255, 180), 9, 1); + tf.colorLines(Palette.getColor("palegreen"), 9, 1); // @formatter:off tf.writeln("|8b 40 0c| |MOV| |EAX|,|Oxc|[|EAX|]", blue, darkBlue, orange, darkGreen, orange ); @@ -220,11 +221,12 @@ public class DecompilePluginScreenShots extends GhidraScreenShotGenerator { Font font = new Font("Monospaced", Font.PLAIN, 13); TextFormatter tf = new TextFormatter(font, 15, 400, 4, 2, 0); - TextFormatterContext blue = new TextFormatterContext(Color.BLUE); - TextFormatterContext green = new TextFormatterContext(Color.GREEN); - TextFormatterContext hl = new TextFormatterContext(Color.BLACK, Color.YELLOW); - TextFormatterContext greenhl = new TextFormatterContext(Color.GREEN, Color.YELLOW); - TextFormatterContext cursor = new TextFormatterContext(Color.WHITE, Color.WHITE, Color.RED); + TextFormatterContext blue = new TextFormatterContext(Palette.BLUE); + TextFormatterContext green = new TextFormatterContext(Palette.GREEN); + TextFormatterContext hl = new TextFormatterContext(Palette.BLACK, Palette.YELLOW); + TextFormatterContext greenhl = new TextFormatterContext(Palette.GREEN, Palette.YELLOW); + TextFormatterContext cursor = + new TextFormatterContext(Palette.WHITE, Palette.WHITE, Palette.RED); // @formatter:off tf.writeln(" dword dVar1:"); @@ -252,10 +254,11 @@ public class DecompilePluginScreenShots extends GhidraScreenShotGenerator { Font font = new Font("Monospaced", Font.PLAIN, 13); TextFormatter tf = new TextFormatter(font, 15, 400, 4, 2, 0); - TextFormatterContext blue = new TextFormatterContext(Color.BLUE); - TextFormatterContext green = new TextFormatterContext(Color.GREEN); - TextFormatterContext hl = new TextFormatterContext(Color.BLACK, Color.YELLOW); - TextFormatterContext cursor = new TextFormatterContext(Color.WHITE, Color.WHITE, Color.RED); + TextFormatterContext blue = new TextFormatterContext(Palette.BLUE); + TextFormatterContext green = new TextFormatterContext(Palette.GREEN); + TextFormatterContext hl = new TextFormatterContext(Palette.BLACK, Palette.YELLOW); + TextFormatterContext cursor = + new TextFormatterContext(Palette.WHITE, Palette.WHITE, Palette.RED); // @formatter:off tf.writeln(" dword dVar1:"); diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/DiffScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/DiffScreenShots.java index f7d35e946c..bbcbab9d2e 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/DiffScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/DiffScreenShots.java @@ -15,7 +15,6 @@ */ package help.screenshot; -import java.awt.Color; import java.awt.Font; import javax.swing.*; @@ -24,6 +23,8 @@ import org.junit.Test; import docking.ComponentProvider; import docking.DialogComponentProvider; +import generic.theme.GThemeDefaults.Colors; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.nav.ListingPanelContainer; import ghidra.app.plugin.core.codebrowser.CodeViewerProvider; import ghidra.app.services.ProgramManager; @@ -135,8 +136,8 @@ public class DiffScreenShots extends GhidraScreenShotGenerator { JMenu jMenu = new JMenu(); Font font = jMenu.getFont().deriveFont(11f); TextFormatter tf = new TextFormatter(font, 3, 220, 0, 20, 3); - TextFormatterContext white = new TextFormatterContext(Color.WHITE); - tf.colorLines(new Color(60, 115, 200), 2, 1); + TextFormatterContext white = new TextFormatterContext(Colors.BACKGROUND); + tf.colorLines(Palette.getColor("cornflowerblue"), 2, 1); tf.writeln("Set Ignore for All Apply Settings"); tf.writeln("Set Replace for All Apply Settings"); diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/DisassembledViewPluginScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/DisassembledViewPluginScreenShots.java index 12b044b152..33724166b0 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/DisassembledViewPluginScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/DisassembledViewPluginScreenShots.java @@ -22,6 +22,7 @@ import javax.swing.SwingUtilities; import org.junit.Test; import docking.ComponentProvider; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.plugin.core.datamgr.DataTypesProvider; import ghidra.app.plugin.core.programtree.ViewManagerComponentProvider; @@ -60,7 +61,7 @@ public class DisassembledViewPluginScreenShots extends GhidraScreenShotGenerator size.height -= (2 * offset);// up r.setSize(size); - drawRectangle(Color.YELLOW, r, 10); + drawRectangle(Palette.YELLOW, r, 10); } } diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/FrontEndPluginScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/FrontEndPluginScreenShots.java index 34622e93ec..d26eb3a9b2 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/FrontEndPluginScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/FrontEndPluginScreenShots.java @@ -33,6 +33,7 @@ import docking.widgets.filechooser.GhidraFileChooser; import docking.widgets.table.GTable; import docking.wizard.WizardManager; import docking.wizard.WizardPanel; +import generic.theme.GThemeDefaults.Colors; import ghidra.app.plugin.core.archive.RestoreDialog; import ghidra.framework.data.GhidraFileData; import ghidra.framework.main.*; @@ -712,7 +713,7 @@ public class FrontEndPluginScreenShots extends GhidraScreenShotGenerator { private void captureIconAndText(Icon labelImage, String text) { final JLabel label = new JLabel(text); - label.setBackground(Color.WHITE); + label.setBackground(Colors.BACKGROUND); label.setOpaque(true); label.setIcon(labelImage); label.setHorizontalAlignment(SwingConstants.CENTER); diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/FunctionGraphPluginScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/FunctionGraphPluginScreenShots.java index 811e2cd876..5d8ef59385 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/FunctionGraphPluginScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/FunctionGraphPluginScreenShots.java @@ -41,6 +41,7 @@ import edu.uci.ics.jung.graph.Graph; import edu.uci.ics.jung.visualization.VisualizationServer; import edu.uci.ics.jung.visualization.VisualizationViewer; import generic.test.TestUtils; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.cmd.function.DeleteFunctionCmd; import ghidra.app.cmd.label.AddLabelCmd; import ghidra.app.plugin.core.functiongraph.AbstractFunctionGraphTest; @@ -318,7 +319,7 @@ public class FunctionGraphPluginScreenShots extends AbstractFunctionGraphTest { int h = (graphImage1.getHeight(null) - 10) - y1; - g.setColor(Color.BLACK); + g.setColor(Palette.BLACK); g.fillRect(x1, y1, w, h); screen.image = fullImage; @@ -530,13 +531,13 @@ public class FunctionGraphPluginScreenShots extends AbstractFunctionGraphTest { Rectangle rect = new Rectangle(x, y, w, h); // drop shadow - Color color = Color.GRAY; + Color color = Palette.GRAY; screen.drawRectangle(color, rect, boxThickness); // box x -= 1; y -= 2; - color = new Color(0xB5, 0xDE, 0x2F); + color = Palette.getColor("greenyellow"); rect.x = x; rect.y = y; screen.drawRectangle(color, rect, boxThickness); diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/GlossaryScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/GlossaryScreenShots.java index 4140205f7d..7c6ed8a43f 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/GlossaryScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/GlossaryScreenShots.java @@ -15,24 +15,28 @@ */ package help.screenshot; -import java.awt.*; +import java.awt.Graphics; +import java.awt.Point; import java.awt.image.BufferedImage; import org.junit.Test; +import generic.theme.GThemeDefaults.Colors; +import generic.theme.GThemeDefaults.Colors.Palette; + public class GlossaryScreenShots extends GhidraScreenShotGenerator { public GlossaryScreenShots() { super(); } -@Test - public void testBigEndian() { + @Test + public void testBigEndian() { //Draw empty white rectangle image = new BufferedImage(450, 100, BufferedImage.TYPE_INT_ARGB); Graphics g = image.getGraphics(); - g.setColor(Color.WHITE); + g.setColor(Colors.BACKGROUND); g.fillRect(0, 0, 450, 125); //Draw box with line in the middle @@ -44,16 +48,16 @@ public class GlossaryScreenShots extends GhidraScreenShotGenerator { Point p5 = new Point(225, 10); Point p6 = new Point(225, 50); - drawLine(Color.BLACK, 1, p1, p2); - drawLine(Color.BLACK, 1, p2, p3); - drawLine(Color.BLACK, 1, p3, p4); - drawLine(Color.BLACK, 1, p4, p1); + drawLine(Palette.BLACK, 1, p1, p2); + drawLine(Palette.BLACK, 1, p2, p3); + drawLine(Palette.BLACK, 1, p3, p4); + drawLine(Palette.BLACK, 1, p4, p1); - drawLine(Color.BLACK, 1, p5, p6); + drawLine(Palette.BLACK, 1, p5, p6); //Draw Text in boxes - drawText("high-order byte", Color.BLACK, new Point(80, 35), 12); - drawText("low-order byte", Color.BLACK, new Point(285, 35), 12); + drawText("high-order byte", Colors.FOREGROUND, new Point(80, 35), 12); + drawText("low-order byte", Colors.FOREGROUND, new Point(285, 35), 12); //Draw arrows Point p7 = new Point(30, 50); @@ -61,22 +65,22 @@ public class GlossaryScreenShots extends GhidraScreenShotGenerator { Point p9 = new Point(225, 50); Point p10 = new Point(225, 80); - drawArrow(Color.BLACK, 1, p8, p7, 6); - drawArrow(Color.BLACK, 1, p10, p9, 6); + drawArrow(Palette.BLACK, 1, p8, p7, 6); + drawArrow(Palette.BLACK, 1, p10, p9, 6); //Draw arrow text - drawText("addr A", Color.BLACK, new Point(15, 93), 12); - drawText("addr A+1", Color.BLACK, new Point(200, 93), 12); + drawText("addr A", Colors.FOREGROUND, new Point(15, 93), 12); + drawText("addr A+1", Colors.FOREGROUND, new Point(200, 93), 12); } -@Test - public void testLittleEndian() { + @Test + public void testLittleEndian() { //Draw empty white rectangle image = new BufferedImage(450, 100, BufferedImage.TYPE_INT_ARGB); Graphics g = image.getGraphics(); - g.setColor(Color.WHITE); + g.setColor(Palette.WHITE); g.fillRect(0, 0, 450, 125); //Draw box with line in the middle @@ -88,16 +92,16 @@ public class GlossaryScreenShots extends GhidraScreenShotGenerator { Point p5 = new Point(225, 10); Point p6 = new Point(225, 50); - drawLine(Color.BLACK, 1, p1, p2); - drawLine(Color.BLACK, 1, p2, p3); - drawLine(Color.BLACK, 1, p3, p4); - drawLine(Color.BLACK, 1, p4, p1); + drawLine(Palette.BLACK, 1, p1, p2); + drawLine(Palette.BLACK, 1, p2, p3); + drawLine(Palette.BLACK, 1, p3, p4); + drawLine(Palette.BLACK, 1, p4, p1); - drawLine(Color.BLACK, 1, p5, p6); + drawLine(Palette.BLACK, 1, p5, p6); //Draw Text in boxes - drawText("high-order byte", Color.BLACK, new Point(80, 35), 12); - drawText("low-order byte", Color.BLACK, new Point(285, 35), 12); + drawText("high-order byte", Colors.FOREGROUND, new Point(80, 35), 12); + drawText("low-order byte", Colors.FOREGROUND, new Point(285, 35), 12); //Draw arrows Point p7 = new Point(430, 50); @@ -105,12 +109,12 @@ public class GlossaryScreenShots extends GhidraScreenShotGenerator { Point p9 = new Point(225, 50); Point p10 = new Point(225, 80); - drawArrow(Color.BLACK, 1, p8, p7, 6); - drawArrow(Color.BLACK, 1, p10, p9, 6); + drawArrow(Palette.BLACK, 1, p8, p7, 6); + drawArrow(Palette.BLACK, 1, p10, p9, 6); //Draw arrow text - drawText("addr A+1", Color.BLACK, new Point(200, 93), 12); - drawText("addr A", Color.BLACK, new Point(413, 93), 12); + drawText("addr A+1", Colors.FOREGROUND, new Point(200, 93), 12); + drawText("addr A", Colors.FOREGROUND, new Point(413, 93), 12); } } diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/MemoryMapPluginScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/MemoryMapPluginScreenShots.java index 646804c486..f6f89d1991 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/MemoryMapPluginScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/MemoryMapPluginScreenShots.java @@ -15,7 +15,8 @@ */ package help.screenshot; -import java.awt.*; +import java.awt.Graphics; +import java.awt.Point; import java.awt.image.BufferedImage; import javax.swing.JComponent; @@ -27,6 +28,8 @@ import docking.ComponentProvider; import docking.DialogComponentProvider; import docking.action.DockingAction; import docking.widgets.combobox.GhidraComboBox; +import generic.theme.GThemeDefaults.Colors; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.util.exception.AssertException; import ghidra.util.table.GhidraTable; @@ -36,8 +39,8 @@ public class MemoryMapPluginScreenShots extends GhidraScreenShotGenerator { super(); } -@Test - public void testMemoryMap() { + @Test + public void testMemoryMap() { performAction("Memory Map", "DockingWindows", true); @@ -48,52 +51,52 @@ public class MemoryMapPluginScreenShots extends GhidraScreenShotGenerator { captureIsolatedComponent(component, 800, 225); } -@Test - public void testAddMemoryBlock() { + @Test + public void testAddMemoryBlock() { performAction("Add Block", "MemoryMapPlugin", false); captureDialog(); } -@Test - public void testBitOverlayAddresses() { + @Test + public void testBitOverlayAddresses() { //Draw empty white rectangle image = new BufferedImage(450, 175, BufferedImage.TYPE_INT_ARGB); Graphics g = image.getGraphics(); - g.setColor(Color.WHITE); + g.setColor(Colors.BACKGROUND); g.fillRect(0, 0, 450, 175); //Draw Title and subtitle - drawText("Bit Overlay Addresses", Color.BLACK, new Point(160, 30), 18); - drawText("Byte Memory", Color.BLACK, new Point(15, 30), 10); - drawText("Addresses", Color.BLACK, new Point(20, 40), 10); + drawText("Bit Overlay Addresses", Colors.FOREGROUND, new Point(160, 30), 18); + drawText("Byte Memory", Colors.FOREGROUND, new Point(15, 30), 10); + drawText("Addresses", Colors.FOREGROUND, new Point(20, 40), 10); //Draw text inside and next to boxes - drawText("00008100", Color.BLACK, new Point(15, 80), 12); - drawText("00008100", Color.BLACK, new Point(15, 130), 12); + drawText("00008100", Colors.FOREGROUND, new Point(15, 80), 12); + drawText("00008100", Colors.FOREGROUND, new Point(15, 130), 12); - drawText("MSB", Color.BLACK, new Point(90, 60), 10); - drawText("LSB", Color.BLACK, new Point(370, 60), 10); + drawText("MSB", Colors.FOREGROUND, new Point(90, 60), 10); + drawText("LSB", Colors.FOREGROUND, new Point(370, 60), 10); - drawText("0007", Color.BLACK, new Point(90, 80), 10); - drawText("0006", Color.BLACK, new Point(130, 80), 10); - drawText("0005", Color.BLACK, new Point(170, 80), 10); - drawText("0004", Color.BLACK, new Point(210, 80), 10); - drawText("0003", Color.BLACK, new Point(250, 80), 10); - drawText("0002", Color.BLACK, new Point(290, 80), 10); - drawText("0001", Color.BLACK, new Point(330, 80), 10); - drawText("0000", Color.BLACK, new Point(370, 80), 10); + drawText("0007", Colors.FOREGROUND, new Point(90, 80), 10); + drawText("0006", Colors.FOREGROUND, new Point(130, 80), 10); + drawText("0005", Colors.FOREGROUND, new Point(170, 80), 10); + drawText("0004", Colors.FOREGROUND, new Point(210, 80), 10); + drawText("0003", Colors.FOREGROUND, new Point(250, 80), 10); + drawText("0002", Colors.FOREGROUND, new Point(290, 80), 10); + drawText("0001", Colors.FOREGROUND, new Point(330, 80), 10); + drawText("0000", Colors.FOREGROUND, new Point(370, 80), 10); - drawText("000f", Color.BLACK, new Point(90, 130), 10); - drawText("000e", Color.BLACK, new Point(130, 130), 10); - drawText("000d", Color.BLACK, new Point(170, 130), 10); - drawText("000c", Color.BLACK, new Point(210, 130), 10); - drawText("000b", Color.BLACK, new Point(250, 130), 10); - drawText("000a", Color.BLACK, new Point(290, 130), 10); - drawText("0009", Color.BLACK, new Point(330, 130), 10); - drawText("0008", Color.BLACK, new Point(370, 130), 10); + drawText("000f", Colors.FOREGROUND, new Point(90, 130), 10); + drawText("000e", Colors.FOREGROUND, new Point(130, 130), 10); + drawText("000d", Colors.FOREGROUND, new Point(170, 130), 10); + drawText("000c", Colors.FOREGROUND, new Point(210, 130), 10); + drawText("000b", Colors.FOREGROUND, new Point(250, 130), 10); + drawText("000a", Colors.FOREGROUND, new Point(290, 130), 10); + drawText("0009", Colors.FOREGROUND, new Point(330, 130), 10); + drawText("0008", Colors.FOREGROUND, new Point(370, 130), 10); //Draw boxes Point p1 = new Point(80, 65); @@ -106,24 +109,24 @@ public class MemoryMapPluginScreenShots extends GhidraScreenShotGenerator { Point p7 = new Point(400, 140); Point p8 = new Point(80, 140); - drawLine(Color.BLACK, 1, p1, p2); - drawLine(Color.BLACK, 1, p2, p3); - drawLine(Color.BLACK, 1, p3, p4); - drawLine(Color.BLACK, 1, p4, p1); + drawLine(Palette.BLACK, 1, p1, p2); + drawLine(Palette.BLACK, 1, p2, p3); + drawLine(Palette.BLACK, 1, p3, p4); + drawLine(Palette.BLACK, 1, p4, p1); - drawLine(Color.BLACK, 1, p5, p6); - drawLine(Color.BLACK, 1, p6, p7); - drawLine(Color.BLACK, 1, p7, p8); - drawLine(Color.BLACK, 1, p8, p5); + drawLine(Palette.BLACK, 1, p5, p6); + drawLine(Palette.BLACK, 1, p6, p7); + drawLine(Palette.BLACK, 1, p7, p8); + drawLine(Palette.BLACK, 1, p8, p5); for (int i = 1; i < 8; i++) { - drawLine(Color.BLACK, 1, new Point(80 + i * 40, 65), new Point(80 + i * 40, 90)); - drawLine(Color.BLACK, 1, new Point(80 + i * 40, 115), new Point(80 + i * 40, 140)); + drawLine(Palette.BLACK, 1, new Point(80 + i * 40, 65), new Point(80 + i * 40, 90)); + drawLine(Palette.BLACK, 1, new Point(80 + i * 40, 115), new Point(80 + i * 40, 140)); } } -@Test - public void testAddMappedBlock() { + @Test + public void testAddMappedBlock() { performAction("Add Block", "MemoryMapPlugin", false); @@ -133,11 +136,11 @@ public class MemoryMapPluginScreenShots extends GhidraScreenShotGenerator { captureDialog(); - drawRectangleAround(comboBox, Color.GREEN, 10); + drawRectangleAround(comboBox, Palette.GREEN, 10); } -@Test - public void testMoveMemory() { + @Test + public void testMoveMemory() { performAction("Memory Map", "DockingWindows", true); @@ -155,8 +158,8 @@ public class MemoryMapPluginScreenShots extends GhidraScreenShotGenerator { captureDialog(); } -@Test - public void testSplitMemoryBlock() { + @Test + public void testSplitMemoryBlock() { performAction("Memory Map", "DockingWindows", true); @@ -174,8 +177,8 @@ public class MemoryMapPluginScreenShots extends GhidraScreenShotGenerator { captureDialog(); } -@Test - public void testMemoryExpandUp() { + @Test + public void testMemoryExpandUp() { performAction("Memory Map", "DockingWindows", true); @@ -193,8 +196,8 @@ public class MemoryMapPluginScreenShots extends GhidraScreenShotGenerator { captureDialog(); } -@Test - public void testMemoryExpandDown() { + @Test + public void testMemoryExpandDown() { performAction("Memory Map", "DockingWindows", true); @@ -212,8 +215,8 @@ public class MemoryMapPluginScreenShots extends GhidraScreenShotGenerator { captureDialog(); } -@Test - public void testSetImageBaseDialog() { + @Test + public void testSetImageBaseDialog() { performAction("Memory Map", "DockingWindows", true); @@ -234,55 +237,48 @@ public class MemoryMapPluginScreenShots extends GhidraScreenShotGenerator { private void selectRow(final GhidraTable table, final String text) { final TableModel model = table.getModel(); - runSwing(new Runnable() { - - @Override - public void run() { - int columnCount = model.getColumnCount(); - int columnIndex = -1; - int rowIndex = -1; - for (int i = 0; i < columnCount; i++) { - if (model.getColumnName(i).equals("Name")) { - columnIndex = i; + runSwing(() -> { + int columnCount = model.getColumnCount(); + int columnIndex = -1; + int rowIndex = -1; + for (int i = 0; i < columnCount; i++) { + if (model.getColumnName(i).equals("Name")) { + columnIndex = i; + break; + } + } + if (columnIndex != -1) { + int rowCount = model.getRowCount(); + for (int i = 0; i < rowCount; i++) { + if (model.getValueAt(i, columnIndex).equals(text)) { + rowIndex = i; break; } } - if (columnIndex != -1) { - int rowCount = model.getRowCount(); - for (int i = 0; i < rowCount; i++) { - if (model.getValueAt(i, columnIndex).equals(text)) { - rowIndex = i; - break; - } - } - } - if (rowIndex == -1) { - throw new AssertException(); - } - table.selectRow(rowIndex); - } + if (rowIndex == -1) { + throw new AssertException(); + } + table.selectRow(rowIndex); + }); } private void selectItem(final GhidraComboBox comboBox, final String text) { - runSwing(new Runnable() { - @Override - public void run() { - int itemCount = comboBox.getItemCount(); - Object item = null; - for (int i = 0; i < itemCount; i++) { - Object itemAt = comboBox.getItemAt(i); - if (itemAt.toString().equals(text)) { - item = itemAt; - break; - } + runSwing(() -> { + int itemCount = comboBox.getItemCount(); + Object item = null; + for (int i = 0; i < itemCount; i++) { + Object itemAt = comboBox.getItemAt(i); + if (itemAt.toString().equals(text)) { + item = itemAt; + break; } - if (item == null) { - throw new AssertException(); - } - comboBox.setSelectedItem(item); } + if (item == null) { + throw new AssertException(); + } + comboBox.setSelectedItem(item); }); } } diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/MemorySearchScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/MemorySearchScreenShots.java index 5911fefa89..800d162147 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/MemorySearchScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/MemorySearchScreenShots.java @@ -24,6 +24,7 @@ import org.junit.Test; import docking.DialogComponentProvider; import docking.action.DockingActionIf; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin; import ghidra.app.plugin.core.codebrowser.CodeViewerProvider; import ghidra.app.plugin.core.searchmem.mask.MnemonicSearchPlugin; @@ -168,9 +169,9 @@ public class MemorySearchScreenShots extends AbstractSearchScreenShots { @Test public void testSearchInstructions() { Font font = new Font("Monospaced", Font.PLAIN, 14); - Color selectionColor = new Color(180, 255, 180); + Color selectionColor = Palette.getColor("palegreen"); TextFormatter tf = new TextFormatter(font, 8, 500, 4, 5, 2); - TextFormatterContext blue = new TextFormatterContext(Color.BLUE); + TextFormatterContext blue = new TextFormatterContext(Palette.BLUE); TextFormatterContext darkBlue = new TextFormatterContext(DARK_BLUE); TextFormatterContext darkGreen = new TextFormatterContext(DARK_GREEN); TextFormatterContext orange = new TextFormatterContext(YELLOW_ORANGE); @@ -194,7 +195,7 @@ public class MemorySearchScreenShots extends AbstractSearchScreenShots { public void testSearchInstructionsIncludeOperands() { Font font = new Font("Monospaced", Font.PLAIN, 14); TextFormatter tf = new TextFormatter(font, 4, 300, 4, 5, 2); - TextFormatterContext blue = new TextFormatterContext(Color.BLUE); + TextFormatterContext blue = new TextFormatterContext(Palette.BLUE); TextFormatterContext darkBlue = new TextFormatterContext(DARK_BLUE); TextFormatterContext darkGreen = new TextFormatterContext(DARK_GREEN); TextFormatterContext orange = new TextFormatterContext(YELLOW_ORANGE); @@ -258,7 +259,7 @@ public class MemorySearchScreenShots extends AbstractSearchScreenShots { performAction(action, provider, false); // And capture the error dialog. - Window errorDialog = waitForWindow("Mnemonic Search Error", 2000); + Window errorDialog = waitForWindow("Mnemonic Search Error"); captureWindow(errorDialog); } } diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/OverviewPluginScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/OverviewPluginScreenShots.java index 6503c9df64..7b03cd72bd 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/OverviewPluginScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/OverviewPluginScreenShots.java @@ -19,6 +19,8 @@ import java.awt.*; import org.junit.Test; +import generic.theme.GThemeDefaults.Colors; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.plugin.core.codebrowser.CodeViewerProvider; import ghidra.app.plugin.core.overview.OverviewColorLegendDialog; import ghidra.app.plugin.core.overview.OverviewColorPlugin; @@ -54,9 +56,9 @@ public class OverviewPluginScreenShots extends GhidraScreenShotGenerator { }); captureIsolatedProvider(CodeViewerProvider.class, 700, 400); - padImage(new Color(0, 0, 0, 0), 10, 0, 50, 0); - drawOval(Color.RED, new Rectangle(630, 2, 40, 40), 3); - drawOval(Color.RED, new Rectangle(668, 55, 40, 240), 3); + padImage(Palette.NO_COLOR, 10, 0, 50, 0); + drawOval(Palette.RED, new Rectangle(630, 2, 40, 40), 3); + drawOval(Palette.RED, new Rectangle(668, 55, 40, 240), 3); } @Test @@ -126,18 +128,18 @@ public class OverviewPluginScreenShots extends GhidraScreenShotGenerator { image = createEmptyImage(width + margin * 2, height + margin * 2); Point p = new Point(margin, margin + smallFontHeight); - drawText(sumTop, Color.BLACK, p, smallFont); + drawText(sumTop, Colors.FOREGROUND, p, smallFont); p.y += bigMetrics.getAscent() - bigMetrics.getDescent() / 2; - drawText(sum, Color.BLACK, p, bigFont); + drawText(sum, Colors.FOREGROUND, p, bigFont); p.y += smallFontHeight; - drawText(sumBottom, Color.BLACK, p, smallFont); + drawText(sumBottom, Colors.FOREGROUND, p, smallFont); p.x += bigMetrics.stringWidth(sum); p.y = margin + smallFontHeight + bigFontHeight / 2 + metrics.getHeight() / 2 - bigMetrics.getDescent() / 2; - drawText(equation, Color.BLACK, p, mediumFont); + drawText(equation, Colors.FOREGROUND, p, mediumFont); } diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ProgramGraphPluginScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ProgramGraphPluginScreenShots.java index f05807334b..ab457a9702 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ProgramGraphPluginScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ProgramGraphPluginScreenShots.java @@ -15,11 +15,14 @@ */ package help.screenshot; -import java.awt.*; +import java.awt.Point; +import java.awt.Rectangle; import org.junit.Test; import docking.action.DockingActionIf; +import generic.theme.GThemeDefaults.Colors; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.util.viewer.field.*; import ghidra.graph.visualization.DefaultGraphDisplayComponentProvider; @@ -110,9 +113,10 @@ public class ProgramGraphPluginScreenShots extends GhidraScreenShotGenerator { Point p2 = new Point(STARTX + WIDTH, startY); Point p3 = new Point(STARTX, endY); Point p4 = new Point(STARTX + WIDTH, endY); - drawLine(Color.BLACK, 3, p1, p2); - drawLine(Color.BLACK, 3, p2, p4); - drawLine(Color.BLACK, 3, p3, p4); - drawText(string, Color.BLACK, new Point(STARTX + WIDTH + 10, (startY + endY) / 2), 12); + drawLine(Palette.BLACK, 3, p1, p2); + drawLine(Palette.BLACK, 3, p2, p4); + drawLine(Palette.BLACK, 3, p3, p4); + drawText(string, Colors.FOREGROUND, new Point(STARTX + WIDTH + 10, (startY + endY) / 2), + 12); } } diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ProgramManagerPluginScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ProgramManagerPluginScreenShots.java index 26dd3b18f9..0593c26f14 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ProgramManagerPluginScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ProgramManagerPluginScreenShots.java @@ -34,6 +34,7 @@ import docking.options.editor.OptionsDialog; import docking.widgets.OptionDialog; import docking.widgets.tree.GTree; import docking.widgets.tree.GTreeNode; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.plugin.core.codebrowser.CodeViewerProvider; import ghidra.app.plugin.core.datamgr.DataTypesProvider; import ghidra.app.plugin.core.progmgr.MultiTabPlugin; @@ -49,7 +50,7 @@ import ghidra.program.model.listing.Program; import ghidra.program.model.symbol.SourceType; import ghidra.util.exception.CancelledException; import ghidra.util.task.TaskLauncher; -import ghidra.util.task.TaskMonitorAdapter; +import ghidra.util.task.TaskMonitor; public class ProgramManagerPluginScreenShots extends GhidraScreenShotGenerator implements CheckinHandler { @@ -65,7 +66,7 @@ public class ProgramManagerPluginScreenShots extends GhidraScreenShotGenerator createAndOpenPrograms(2, 1); closeProvider(DataTypesProvider.class); captureToolWindow(900, 400); - drawOval(new Color(108, 0, 0), new Rectangle(280, 92, 190, 60), 8); + drawOval(Palette.PURPLE, new Rectangle(280, 92, 190, 60), 8); } @@ -113,7 +114,7 @@ public class ProgramManagerPluginScreenShots extends GhidraScreenShotGenerator ProjectData projectData = project.getProjectData(); projectData.getRootFolder() .createFile("WinHelloCpp.exe", program, - TaskMonitorAdapter.DUMMY_MONITOR); + TaskMonitor.DUMMY); DomainFile df = program.getDomainFile(); @@ -146,7 +147,7 @@ public class ProgramManagerPluginScreenShots extends GhidraScreenShotGenerator runSwing(() -> invokeInstanceMethod("advancedButtonCallback", dialog)); captureDialog(850, 400); - closeAllWindowsAndFrames(); + closeAllWindows(); } @Test @@ -156,7 +157,7 @@ public class ProgramManagerPluginScreenShots extends GhidraScreenShotGenerator performAction("Open File", "ProgramManagerPlugin", false); captureDialog(500, 400); - closeAllWindowsAndFrames(); + closeAllWindows(); } @@ -176,7 +177,7 @@ public class ProgramManagerPluginScreenShots extends GhidraScreenShotGenerator rightClick(jTree, rowBounds.x + 25, rowBounds.y + 10); waitForSwing(); captureDialog(); - closeAllWindowsAndFrames(); + closeAllWindows(); } @Test @@ -231,7 +232,7 @@ public class ProgramManagerPluginScreenShots extends GhidraScreenShotGenerator waitForSwing(); createAndOpenPrograms(6, 3); captureProvider(CodeViewerProvider.class); - drawOval(new Color(108, 0, 0), new Rectangle(440, 16, 70, 50), 8); + drawOval(Palette.PURPLE, new Rectangle(440, 16, 70, 50), 8); } @Test @@ -273,7 +274,7 @@ public class ProgramManagerPluginScreenShots extends GhidraScreenShotGenerator }); captureProvider(CodeViewerProvider.class); - drawOval(new Color(108, 0, 0), new Rectangle(221, 16, 140, 50), 8); + drawOval(Palette.PURPLE, new Rectangle(221, 16, 140, 50), 8); } @Test @@ -310,7 +311,7 @@ public class ProgramManagerPluginScreenShots extends GhidraScreenShotGenerator String programName = "Program" + (i + 1) + ".exe"; list.add(projectData.getRootFolder() .createFile(programName, program, - TaskMonitorAdapter.DUMMY_MONITOR)); + TaskMonitor.DUMMY)); } program.flushEvents(); @@ -350,7 +351,7 @@ public class ProgramManagerPluginScreenShots extends GhidraScreenShotGenerator TaskLauncher.launchModal(comment, () -> { try { domainFile.addToVersionControl(comment, keepItCheckedOut, - TaskMonitorAdapter.DUMMY_MONITOR); + TaskMonitor.DUMMY); } catch (CancelledException | IOException e) { throw new RuntimeException(e); @@ -365,17 +366,11 @@ public class ProgramManagerPluginScreenShots extends GhidraScreenShotGenerator return space.getAddress(offset); } - /* - * @see ghidra.framework.data.CheckinHandler#getComment() - */ @Override public String getComment() { return checkinComment; } - /* - * @see ghidra.framework.data.CheckinHandler#keepCheckedOut() - */ @Override public boolean keepCheckedOut() { return keepCheckedOut; diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ReferencesPluginScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ReferencesPluginScreenShots.java index d351aeb5a7..41d1476bfd 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ReferencesPluginScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ReferencesPluginScreenShots.java @@ -25,6 +25,8 @@ import javax.swing.*; import org.junit.Test; +import generic.theme.GThemeDefaults.Colors; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.plugin.core.codebrowser.CodeViewerProvider; import ghidra.app.plugin.core.references.*; import ghidra.app.util.importer.*; @@ -84,19 +86,19 @@ public class ReferencesPluginScreenShots extends GhidraScreenShotGenerator { captureProvider(provider); int topMargin = 60; int leftMargin = 10; - padImage(Color.WHITE, topMargin, leftMargin, 10, 10); + padImage(Colors.BACKGROUND, topMargin, leftMargin, 10, 10); JComponent rootComp = getDockableComponent(EditReferencesProvider.class); JComponent comp = (JComponent) findComponentByName(provider.getComponent(), "operandLabels[0]"); Point origin = new Point(leftMargin, topMargin); - explainComponent(rootComp, comp, Color.GREEN, origin, new Point(250, 20), + explainComponent(rootComp, comp, Palette.GREEN, origin, new Point(250, 20), "Operand-specific Drop Zones"); comp = (JComponent) findComponentByName(provider.getComponent(), "mnemonicLabel"); - explainComponent(rootComp, comp, Color.GREEN, origin, new Point(250, 20), + explainComponent(rootComp, comp, Palette.GREEN, origin, new Point(250, 20), "Operand-specific Drop Zones"); comp = (JComponent) findComponentByName(provider.getComponent(), "RefsTable"); - explainComponent(rootComp, comp, Color.GREEN, origin, new Point(450, 40), + explainComponent(rootComp, comp, Palette.GREEN, origin, new Point(450, 40), "Active-operand Drop Zones"); } @@ -113,7 +115,7 @@ public class ReferencesPluginScreenShots extends GhidraScreenShotGenerator { Point p2 = new Point(point.x + 20, point.y); drawLine(color, 2, point, p2); Point p3 = new Point(p2.x + 4, p2.y + 5); - drawText(text, Color.BLACK, p3, 12f); + drawText(text, Colors.FOREGROUND, p3, 12f); } @Test @@ -270,7 +272,7 @@ public class ReferencesPluginScreenShots extends GhidraScreenShotGenerator { RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g2.drawImage(image1, 0, 0, null); g2.drawImage(image2, 0, height + gap, null); - g2.setColor(Color.BLACK); + g2.setColor(Colors.FOREGROUND); String label = "Address History"; int x = 150; int y = height + gap / 2; @@ -293,8 +295,11 @@ public class ReferencesPluginScreenShots extends GhidraScreenShotGenerator { programNameOverride, OptionChooser.DEFAULT_OPTIONS, MultipleProgramsStrategy.ALL_PROGRAMS); Program p = programs.get(0); - env.getProject().getProjectData().getRootFolder().createFile(p.getName(), p, - TaskMonitor.DUMMY); + env.getProject() + .getProjectData() + .getRootFolder() + .createFile(p.getName(), p, + TaskMonitor.DUMMY); } } diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/RepositoryCustomScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/RepositoryCustomScreenShots.java index 8ff6735d58..f198fbac9a 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/RepositoryCustomScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/RepositoryCustomScreenShots.java @@ -15,7 +15,7 @@ */ package help.screenshot; -import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.*; import java.awt.*; import java.awt.image.BufferedImage; @@ -25,6 +25,7 @@ import javax.swing.*; import org.junit.Test; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.merge.MergeProgressPanel; import ghidra.util.layout.VerticalLayout; import resources.ResourceManager; @@ -38,8 +39,8 @@ public class RepositoryCustomScreenShots extends GhidraScreenShotGenerator { @Test public void testMultiUser() { image = createEmptyImage(800, 600); - Color purple = new Color(255, 0, 255); - Color green = new Color(100, 255, 100); + Color purple = Palette.getColor("fuchsia"); + Color green = Palette.LIME; int y = 50; int x = 450; int spacing = 100; @@ -69,12 +70,12 @@ public class RepositoryCustomScreenShots extends GhidraScreenShotGenerator { Point p_leg3_text = new Point(p_leg3.x + indent, p_leg3.y); drawLine(purple, p_v0, p_v3, false); - drawLine(Color.BLACK, p_v1, p_co_v1, true); - drawLine(Color.BLACK, p_v1, p_co_v2, true); + drawLine(Palette.BLACK, p_v1, p_co_v1, true); + drawLine(Palette.BLACK, p_v1, p_co_v2, true); drawLine(green, p_co_v1, p_box1, false); drawLine(green, p_box1, p_box2, false); - drawLine(Color.BLUE, p_co_v2, p_v2, false); - drawLine(Color.BLUE, p_box2, p_v3, false); + drawLine(Palette.BLUE, p_co_v2, p_v2, false); + drawLine(Palette.BLUE, p_box2, p_v3, false); drawBubble("Version 0", null, p_v0); drawBubble("Version 1", null, p_v1); @@ -98,9 +99,9 @@ public class RepositoryCustomScreenShots extends GhidraScreenShotGenerator { drawText(p_leg1_text, -1, " Check Out"); drawText(p_leg2_text, -1, " Make changes and merge"); drawText(p_leg3_text, -1, " Create new version"); - drawLine(Color.BLACK, p_leg1, p_leg1_text, true); + drawLine(Palette.BLACK, p_leg1, p_leg1_text, true); drawLine(green, p_leg2, p_leg2_text, false); - drawLine(Color.BLUE, p_leg3, p_leg3_text, false); + drawLine(Palette.BLUE, p_leg3, p_leg3_text, false); } private void drawLine(Color color, Point p1, Point p2, boolean dashed) { @@ -130,7 +131,7 @@ public class RepositoryCustomScreenShots extends GhidraScreenShotGenerator { g.setFont(f); FontMetrics metrics = g.getFontMetrics(); int height = metrics.getHeight(); - g.setColor(Color.BLACK); + g.setColor(Palette.BLACK); g.drawOval(x, y, radius * 2, radius * 2); if (text2 == null) { @@ -168,7 +169,7 @@ public class RepositoryCustomScreenShots extends GhidraScreenShotGenerator { int y = p.y - height / 2; g.fillRect(x, y, width, height); - g.setColor(Color.BLACK); + g.setColor(Palette.BLACK); g.drawRect(x, y, width, height); y += margin; @@ -203,7 +204,7 @@ public class RepositoryCustomScreenShots extends GhidraScreenShotGenerator { // int y = p.y - height / 2; // g.fillRect(x, y, width, height); - g.setColor(Color.BLACK); + g.setColor(Palette.BLACK); int y = p.y - height / 2; int x = p.x; @@ -221,7 +222,7 @@ public class RepositoryCustomScreenShots extends GhidraScreenShotGenerator { @Test public void testAutoMergeCodeUnits() { - closeAllWindowsAndFrames(); + closeAllWindows(); final MergeProgressPanel panel = new MergeProgressPanel(); final String[] MEMORY = new String[] { "Memory" }; @@ -249,18 +250,14 @@ public class RepositoryCustomScreenShots extends GhidraScreenShotGenerator { panel.addInfo(EXTERNAL_PROGRAM); panel.addInfo(PROPERTY_LIST); - runSwing(new Runnable() { - - @Override - public void run() { - panel.setCompleted(MEMORY); - panel.setCompleted(PROGRAM_TREE); - panel.setCompleted(DATA_TYPES); - panel.setCompleted(PROGRAM_CONTEXT); - panel.setCompleted(LISTING); - panel.setCompleted(BYTES); - panel.setInProgress(FUNCTIONS); - } + runSwing(() -> { + panel.setCompleted(MEMORY); + panel.setCompleted(PROGRAM_TREE); + panel.setCompleted(DATA_TYPES); + panel.setCompleted(PROGRAM_CONTEXT); + panel.setCompleted(LISTING); + panel.setCompleted(BYTES); + panel.setInProgress(FUNCTIONS); }); JPanel mainPanel = new JPanel(new VerticalLayout(20)); diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/RepositoryScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/RepositoryScreenShots.java index b818842fc7..e0ae764585 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/RepositoryScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/RepositoryScreenShots.java @@ -28,6 +28,7 @@ import org.junit.*; import docking.widgets.indexedscrollpane.IndexedScrollPane; import generic.test.TestUtils; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.cmd.function.AddRegisterParameterCommand; import ghidra.app.merge.*; import ghidra.app.merge.listing.*; @@ -71,7 +72,8 @@ public class RepositoryScreenShots extends AbstractListingMergeManagerTest { public void setUp() throws Exception { super.setUp(); String testFilename = getClass().getSimpleName().replace(".class", ""); - mtfGenerator = new MergeScreenShotGenerator(testFilename, testName.getMethodName(), mtf, testName); + mtfGenerator = + new MergeScreenShotGenerator(testFilename, testName.getMethodName(), mtf, testName); env = mtf.getTestEnvironment(); } @@ -150,7 +152,7 @@ public class RepositoryScreenShots extends AbstractListingMergeManagerTest { Container namePanel = (Container) TestUtils.getInstanceField("namePanel", memoryMergePanel); setToolSize(600, 450); Window window = mergeTool.getActiveWindow(); - + mtfGenerator.captureComponent(window); // chooseRadioButton(MergeConstants.MY_TITLE, namePanel.getClass(), false); @@ -642,13 +644,13 @@ public class RepositoryScreenShots extends AbstractListingMergeManagerTest { int arrowHead2Y = lock3Y; int description1Y = arrowTailY - 10; int description2Y = arrowTailY + 10; - mtfGenerator.drawArrow(Color.RED, 2, new Point(arrowTailX, arrowTailY), + mtfGenerator.drawArrow(Palette.RED, 2, new Point(arrowTailX, arrowTailY), new Point(arrowHeadX, arrowHead1Y), 8); - mtfGenerator.drawArrow(Color.RED, 2, new Point(arrowTailX, arrowTailY), + mtfGenerator.drawArrow(Palette.RED, 2, new Point(arrowTailX, arrowTailY), new Point(arrowHeadX, arrowHead2Y), 8); - mtfGenerator.drawText(description1, Color.RED, new Point(descriptionX, description1Y), + mtfGenerator.drawText(description1, Palette.RED, new Point(descriptionX, description1Y), DESCRIPTION_FONT_SIZE); - mtfGenerator.drawText(description2, Color.RED, new Point(descriptionX, description2Y), + mtfGenerator.drawText(description2, Palette.RED, new Point(descriptionX, description2Y), DESCRIPTION_FONT_SIZE); } @@ -661,7 +663,7 @@ public class RepositoryScreenShots extends AbstractListingMergeManagerTest { Dimension size = listingPanels[0].getSize(); int descriptionX = listingX + (size.width / 3); int descriptionY = listingY + size.height - 20; - mtfGenerator.drawText(greyListingDescription, Color.RED, + mtfGenerator.drawText(greyListingDescription, Palette.RED, new Point(descriptionX, descriptionY), DESCRIPTION_FONT_SIZE); } @@ -690,9 +692,9 @@ public class RepositoryScreenShots extends AbstractListingMergeManagerTest { int arrowHeadY = buttonY; int arrowTailY = buttonY; int descriptionY = buttonY + 5; - mtfGenerator.drawArrow(Color.RED, 2, new Point(arrowTailX, arrowTailY), + mtfGenerator.drawArrow(Palette.RED, 2, new Point(arrowTailX, arrowTailY), new Point(arrowHeadX, arrowHeadY), 8); - mtfGenerator.drawText(adjustFieldsDescription, Color.RED, + mtfGenerator.drawText(adjustFieldsDescription, Palette.RED, new Point(descriptionX, descriptionY), DESCRIPTION_FONT_SIZE); } @@ -711,11 +713,11 @@ public class RepositoryScreenShots extends AbstractListingMergeManagerTest { int arrowHeadY = westLabelBottomY; int arrowTailY = westLabelBottomY + 15; int descriptionY = westLabelBottomY + 20; - mtfGenerator.drawArrow(Color.RED, 2, new Point(arrowTailX, arrowTailY), + mtfGenerator.drawArrow(Palette.RED, 2, new Point(arrowTailX, arrowTailY), new Point(arrowHeadX, arrowTailY), 0); - mtfGenerator.drawArrow(Color.RED, 2, new Point(arrowHeadX, arrowTailY), + mtfGenerator.drawArrow(Palette.RED, 2, new Point(arrowHeadX, arrowTailY), new Point(arrowHeadX, arrowHeadY), 8); - mtfGenerator.drawText("Indicates which conflict you are resolving.", Color.RED, + mtfGenerator.drawText("Indicates which conflict you are resolving.", Palette.RED, new Point(descriptionX, descriptionY), DESCRIPTION_FONT_SIZE); } @@ -734,9 +736,9 @@ public class RepositoryScreenShots extends AbstractListingMergeManagerTest { int arrowHeadY = eastLabelY - 10; int arrowTailY = arrowHeadY - 30; int descriptionY = arrowTailY - 5; - mtfGenerator.drawArrow(Color.RED, 2, new Point(arrowHeadX, arrowTailY), + mtfGenerator.drawArrow(Palette.RED, 2, new Point(arrowHeadX, arrowTailY), new Point(arrowHeadX, arrowHeadY), 8); - mtfGenerator.drawText(addressRangeDescription, Color.RED, + mtfGenerator.drawText(addressRangeDescription, Palette.RED, new Point(descriptionX, descriptionY), DESCRIPTION_FONT_SIZE); } @@ -744,7 +746,7 @@ public class RepositoryScreenShots extends AbstractListingMergeManagerTest { Graphics g = image.getGraphics(); Font font = g.getFont(); g.setFont(font.deriveFont(DESCRIPTION_FONT_SIZE)); - g.setColor(Color.RED); + g.setColor(Palette.RED); FontMetrics fontMetrics = g.getFontMetrics(font.deriveFont(DESCRIPTION_FONT_SIZE)); int descriptionWidth = fontMetrics.stringWidth(description); return descriptionWidth; @@ -763,9 +765,9 @@ public class RepositoryScreenShots extends AbstractListingMergeManagerTest { int westLabelY = westLabelLocation.y - windowLocationOnScreen.y; int arrowY = westLabelY + 5; int descriptionY = arrowY; - mtfGenerator.drawArrow(Color.RED, 2, new Point(arrowTailX, arrowY), + mtfGenerator.drawArrow(Palette.RED, 2, new Point(arrowTailX, arrowY), new Point(arrowHeadX, arrowY), 8); - mtfGenerator.drawText("Indicates the address(es) in conflict.", Color.RED, + mtfGenerator.drawText("Indicates the address(es) in conflict.", Palette.RED, new Point(descriptionX, descriptionY), DESCRIPTION_FONT_SIZE); } @@ -783,9 +785,9 @@ public class RepositoryScreenShots extends AbstractListingMergeManagerTest { int arrowTailY = endTitleTextY - 5; int arrowHeadY = endTitleTextY + 5; int descriptionY = endTitleTextY; - mtfGenerator.drawArrow(Color.RED, 2, new Point(arrowTailX, arrowTailY), + mtfGenerator.drawArrow(Palette.RED, 2, new Point(arrowTailX, arrowTailY), new Point(arrowHeadX, arrowHeadY), 8); - mtfGenerator.drawText("Type of conflict to resolve.", Color.RED, + mtfGenerator.drawText("Type of conflict to resolve.", Palette.RED, new Point(descriptionX, descriptionY), DESCRIPTION_FONT_SIZE); } @@ -794,9 +796,9 @@ public class RepositoryScreenShots extends AbstractListingMergeManagerTest { Point variousChoicesLocation = variousChoicesPanel.getLocationOnScreen(); int conflictAreaX = variousChoicesLocation.x - windowLocationOnScreen.x; int conflictAreaY = variousChoicesLocation.y - windowLocationOnScreen.y; - mtfGenerator.drawText("Area indicating the specific information", Color.RED, + mtfGenerator.drawText("Area indicating the specific information", Palette.RED, new Point(conflictAreaX + 20, conflictAreaY + 40), DESCRIPTION_FONT_SIZE); - mtfGenerator.drawText("for the current conflict(s) being resolved.", Color.RED, + mtfGenerator.drawText("for the current conflict(s) being resolved.", Palette.RED, new Point(conflictAreaX + 20, conflictAreaY + 60), DESCRIPTION_FONT_SIZE); } @@ -816,11 +818,11 @@ public class RepositoryScreenShots extends AbstractListingMergeManagerTest { int arrowTailY = radioButtonY - 10; int description1Y = radioButtonY - 20; int description2Y = radioButtonY; - mtfGenerator.drawArrow(Color.RED, 2, new Point(arrowTailX, arrowTailY), + mtfGenerator.drawArrow(Palette.RED, 2, new Point(arrowTailX, arrowTailY), new Point(arrowHeadX, arrowHeadY), 8); - mtfGenerator.drawText("Radio buttons or check boxes to", Color.RED, + mtfGenerator.drawText("Radio buttons or check boxes to", Palette.RED, new Point(descriptionX, description1Y), DESCRIPTION_FONT_SIZE); - mtfGenerator.drawText("select for resolving the conflict(s).", Color.RED, + mtfGenerator.drawText("select for resolving the conflict(s).", Palette.RED, new Point(descriptionX, description2Y), DESCRIPTION_FONT_SIZE); } @@ -838,11 +840,11 @@ public class RepositoryScreenShots extends AbstractListingMergeManagerTest { int checkBoxHeight = useForAllCB.getSize().height; int arrowY = useForAllY + (checkBoxHeight / 2); int descriptionY = useForAllY + 15; - mtfGenerator.drawArrow(Color.RED, 2, new Point(arrowTailX, arrowY), + mtfGenerator.drawArrow(Palette.RED, 2, new Point(arrowTailX, arrowY), new Point(arrowHeadX, arrowY), 8); mtfGenerator.drawText( "Check this box to automatically make the same choice for all remaining conflicts like this one.", - Color.RED, new Point(descriptionX, descriptionY), DESCRIPTION_FONT_SIZE); + Palette.RED, new Point(descriptionX, descriptionY), DESCRIPTION_FONT_SIZE); } private void addApplyDescription(Image image, Point windowLocationOnScreen, @@ -863,11 +865,11 @@ public class RepositoryScreenShots extends AbstractListingMergeManagerTest { int arrowHeadY = applyButtonY + 10; int description1Y = applyButtonY + 5; int description2Y = description1Y + 20; - mtfGenerator.drawArrow(Color.RED, 2, new Point(arrowTailX, arrowTailY), + mtfGenerator.drawArrow(Palette.RED, 2, new Point(arrowTailX, arrowTailY), new Point(arrowHeadX, arrowHeadY), 8); - mtfGenerator.drawText(description1, Color.RED, new Point(descriptionX, description1Y), + mtfGenerator.drawText(description1, Palette.RED, new Point(descriptionX, description1Y), DESCRIPTION_FONT_SIZE); - mtfGenerator.drawText(description2, Color.RED, new Point(descriptionX, description2Y), + mtfGenerator.drawText(description2, Palette.RED, new Point(descriptionX, description2Y), DESCRIPTION_FONT_SIZE); } @@ -2409,8 +2411,9 @@ public class RepositoryScreenShots extends AbstractListingMergeManagerTest { int txId = program.startTransaction("Modify Original Program"); boolean commit = false; try { - program.getExternalManager().setExternalPath("ADVAPI32.DLL", "//advapi32.dll", - true); + program.getExternalManager() + .setExternalPath("ADVAPI32.DLL", "//advapi32.dll", + true); commit = true; } finally { @@ -2465,8 +2468,9 @@ public class RepositoryScreenShots extends AbstractListingMergeManagerTest { int txId = program.startTransaction("Modify Original Program"); boolean commit = false; try { - program.getExternalManager().setExternalPath("ADVAPI32.DLL", "//advapi32.dll", - true); + program.getExternalManager() + .setExternalPath("ADVAPI32.DLL", "//advapi32.dll", + true); commit = true; } finally { diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ShowInstructionInfoPluginScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ShowInstructionInfoPluginScreenShots.java index e6a485404f..ed26a0326e 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ShowInstructionInfoPluginScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ShowInstructionInfoPluginScreenShots.java @@ -27,6 +27,7 @@ import docking.*; import docking.widgets.fieldpanel.FieldPanel; import docking.widgets.fieldpanel.Layout; import docking.widgets.fieldpanel.field.Field; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin; import ghidra.app.plugin.core.codebrowser.CodeViewerProvider; import ghidra.app.plugin.core.datamgr.DataTypesProvider; @@ -93,11 +94,11 @@ public class ShowInstructionInfoPluginScreenShots extends GhidraScreenShotGenera Rectangle shapeBounds = new Rectangle(location, labelSize); int thickness = 5; - drawRectangle(Color.RED, shapeBounds, thickness); + drawRectangle(Palette.RED, shapeBounds, thickness); Point start = getEndOfRow(cb, listingPanel, window); Point end = new Point(location.x, location.y); - drawLine(Color.RED, thickness, start, end); + drawLine(Palette.RED, thickness, start, end); cropListingWithStatusArea(); diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/TextFormatter.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/TextFormatter.java index 2faf062de3..8a74630ae3 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/TextFormatter.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/TextFormatter.java @@ -20,6 +20,9 @@ import java.awt.image.BufferedImage; import java.util.regex.Matcher; import java.util.regex.Pattern; +import generic.theme.GThemeDefaults.Colors; +import generic.theme.GThemeDefaults.Colors.Palette; + /** * Each line is sized based on the font height and line padding on the top and bottom of the line. * The y coordinate tracks the top of the line, so a lines baseline (position to draw the text) @@ -37,7 +40,7 @@ public class TextFormatter { private int y; private int leftMargin; private int baselineOffset; - private TextFormatterContext defaultContext = new TextFormatterContext(Color.BLACK); + private TextFormatterContext defaultContext = new TextFormatterContext(Colors.FOREGROUND); private int width; @@ -65,9 +68,9 @@ public class TextFormatter { int height = lineCount * (lineHeight) + topMargin * 2; image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); Graphics2D g = image.createGraphics(); - g.setColor(Color.WHITE); + g.setColor(Colors.BACKGROUND); g.fillRect(0, 0, width, height); - g.setColor(Color.black); + g.setColor(Palette.BLACK); g.drawRect(0, 0, width - 1, height - 1); g.dispose(); } diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ThemingScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ThemingScreenShots.java new file mode 100644 index 0000000000..8900ad526e --- /dev/null +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ThemingScreenShots.java @@ -0,0 +1,68 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package help.screenshot; + +import java.awt.Font; + +import org.junit.Test; + +import docking.theme.gui.*; +import generic.theme.*; +import generic.theme.GThemeDefaults.Colors.Palette; +import resources.ResourceManager; + +public class ThemingScreenShots extends GhidraScreenShotGenerator { + + public ThemingScreenShots() { + super(); + } + + @Test + public void testThemeDialog() { + showDialogWithoutBlocking(tool, new ThemeDialog()); + captureDialog(1000, 500); + } + + @Test + public void testColorEditor() { + ColorValueEditor editor = new ColorValueEditor(e -> { + /**/}); + ColorValue value = new ColorValue("color.bg.test", Palette.BLUE); + Gui.setColor(value); + editor.editValue(value); + captureDialog(); + } + + @Test + public void testFontEditor() { + FontValueEditor editor = new FontValueEditor(e -> { + /**/}); + FontValue value = new FontValue("font.xyz", new Font("Monospaced", Font.BOLD, 14)); + Gui.setFont(value); + editor.editValue(value); + captureDialog(); + } + + @Test + public void testIconEditor() { + IconValueEditor editor = new IconValueEditor(e -> { + /**/}); + IconValue value = new IconValue("icon.bomb", ResourceManager.getDefaultIcon()); + Gui.setIcon(value); + editor.editValue(value); + captureDialog(); + } +} diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ToolScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ToolScreenShots.java index 5d7ae7c6d0..7f82a95cb2 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ToolScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/ToolScreenShots.java @@ -36,6 +36,9 @@ import docking.tool.ToolConstants; import docking.widgets.OptionDialog; import docking.widgets.table.GTable; import generic.jar.ResourceFile; +import generic.theme.GThemeDefaults.Colors; +import generic.theme.GThemeDefaults.Colors.Java; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.framework.Application; import ghidra.framework.LoggingInitialization; import ghidra.framework.cmd.BackgroundCommand; @@ -135,11 +138,12 @@ public class ToolScreenShots extends GhidraScreenShotGenerator { tool.executeBackgroundCommand(new DummyBackgroundCommand(), program); Border inner = BorderFactory.createRaisedBevelBorder(); - Border outer = BorderFactory.createLineBorder(Color.BLACK); + Border outer = BorderFactory.createLineBorder(Java.BORDER); statusBar.setBorder(BorderFactory.createCompoundBorder(outer, inner)); captureComponent(statusBar); program.endTransaction(id, false); - padImage(Color.WHITE, topBottomMargin, leftRightMargin, leftRightMargin, topBottomMargin); + padImage(Colors.FOREGROUND, topBottomMargin, leftRightMargin, leftRightMargin, + topBottomMargin); JComponent statusLabel = (JComponent) getInstanceField("statusLabel", statusBar); Font font = new Font("Ariel", Font.PLAIN, 12); @@ -184,8 +188,9 @@ public class ToolScreenShots extends GhidraScreenShotGenerator { int arrowX = bounds.x + bounds.width / 2 + leftMargin; int arrowStartY = textY - metrics.getHeight() - 5; int arrowEndY = height - topMargin; - drawText(label, Color.BLACK, new Point(textX, textY), font); - drawArrow(Color.BLACK, 1, new Point(arrowX, arrowStartY), new Point(arrowX, arrowEndY), 9); + drawText(label, Colors.FOREGROUND, new Point(textX, textY), font); + drawArrow(Palette.BLACK, 1, new Point(arrowX, arrowStartY), new Point(arrowX, arrowEndY), + 9); } private void labelTop(String label, Rectangle bounds, Font font, FontMetrics metrics, @@ -195,8 +200,9 @@ public class ToolScreenShots extends GhidraScreenShotGenerator { int arrowX = bounds.x + bounds.width / 2 + leftMargin; int arrowStartY = textY + 5; int arrowEndY = topMargin; - drawText(label, Color.BLACK, new Point(textX, textY), font); - drawArrow(Color.BLACK, 1, new Point(arrowX, arrowStartY), new Point(arrowX, arrowEndY), 9); + drawText(label, Colors.FOREGROUND, new Point(textX, textY), font); + drawArrow(Palette.BLACK, 1, new Point(arrowX, arrowStartY), new Point(arrowX, arrowEndY), + 9); } private int getTextStart(Rectangle bounds, FontMetrics metrics, String string) { @@ -261,7 +267,7 @@ public class ToolScreenShots extends GhidraScreenShotGenerator { captureDialog(); JButton button = findButtonByText(window, "Restore Defaults"); - drawRectangleWithDropShadowAround(button, Color.GREEN, 2); + drawRectangleWithDropShadowAround(button, Palette.GREEN, 2); crop(new Rectangle(0, 200, 700, 150)); } diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/TreesScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/TreesScreenShots.java index fa7898a400..951b02b580 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/TreesScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/TreesScreenShots.java @@ -15,7 +15,8 @@ */ package help.screenshot; -import java.awt.*; +import java.awt.Component; +import java.awt.Rectangle; import java.util.Arrays; import javax.swing.*; @@ -38,6 +39,7 @@ import docking.widgets.table.constrainteditor.ColumnConstraintEditor; import docking.widgets.table.constrainteditor.IntegerConstraintEditor; import docking.widgets.table.threaded.ThreadedTableModel; import docking.widgets.tree.*; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.plugin.core.datamgr.DataTypesProvider; import ghidra.app.plugin.core.datamgr.tree.DataTypeArchiveGTree; import ghidra.app.plugin.core.functionwindow.FunctionWindowProvider; @@ -182,7 +184,7 @@ public class TreesScreenShots extends GhidraScreenShotGenerator { int x = rectangle.x + rectangle.width - (width - padding) - iconPadding; int y = rectangle.y - padding; Rectangle shapeBounds = new Rectangle(x, y, width, height); - drawOval(Color.GREEN.darker(), shapeBounds, thickness); + drawOval(Palette.GREEN, shapeBounds, thickness); } diff --git a/gradle/helpProject.gradle b/gradle/helpProject.gradle index 7f1794b400..a75989f6d7 100644 --- a/gradle/helpProject.gradle +++ b/gradle/helpProject.gradle @@ -132,6 +132,8 @@ task buildHelp(type: JavaExec, dependsOn: indexHelp) { group rootProject.GHIDRA_GROUP description " Builds the help for this module. [gradle/helpProject.gradle]\n" + outputs.upToDateWhen {false} + File helpRootDir = file('src/main/help/help') File outputDir = file('build/help/main/help')