diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/pcode/DebuggerPcodeStepperProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/pcode/DebuggerPcodeStepperProvider.java index fe854d8336..3dde790938 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/pcode/DebuggerPcodeStepperProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/pcode/DebuggerPcodeStepperProvider.java @@ -26,7 +26,8 @@ import java.util.function.Function; import java.util.stream.Collectors; import javax.swing.*; -import javax.swing.table.*; +import javax.swing.table.TableColumn; +import javax.swing.table.TableColumnModel; import db.Transaction; import docking.action.DockingAction; @@ -265,8 +266,8 @@ public class DebuggerPcodeStepperProvider extends ComponentProviderAdapter { } @Override - protected void configureFont(JTable table, TableModel model, int column) { - setFont(fixedWidthFont); + protected Font getDefaultFont() { + return fixedWidthFont; } @Override diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/CustomToStringCellRenderer.java b/Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/CustomToStringCellRenderer.java index 3a45e45eb6..70e513621a 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/CustomToStringCellRenderer.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/CustomToStringCellRenderer.java @@ -25,7 +25,6 @@ import java.util.function.BiFunction; import javax.swing.*; import javax.swing.plaf.basic.BasicHTML; -import javax.swing.table.TableModel; import javax.swing.text.View; import ghidra.docking.settings.Settings; @@ -92,11 +91,7 @@ public class CustomToStringCellRenderer extends AbstractGColumnRenderer { } @Override - protected void configureFont(JTable table, TableModel model, int column) { - setFont(getCustomFont()); - } - - protected Font getCustomFont() { + protected Font getDefaultFont() { switch (customFont) { default: case DEFAULT: diff --git a/Ghidra/Extensions/MachineLearning/src/main/java/ghidra/machinelearning/functionfinding/SimilarStartsTableModel.java b/Ghidra/Extensions/MachineLearning/src/main/java/ghidra/machinelearning/functionfinding/SimilarStartsTableModel.java index 1469b10716..12b6f21219 100644 --- a/Ghidra/Extensions/MachineLearning/src/main/java/ghidra/machinelearning/functionfinding/SimilarStartsTableModel.java +++ b/Ghidra/Extensions/MachineLearning/src/main/java/ghidra/machinelearning/functionfinding/SimilarStartsTableModel.java @@ -15,11 +15,9 @@ */ package ghidra.machinelearning.functionfinding; +import java.awt.Font; import java.util.List; -import javax.swing.JTable; -import javax.swing.table.TableModel; - import docking.widgets.table.AbstractDynamicTableColumn; import docking.widgets.table.TableColumnDescriptor; import ghidra.docking.settings.Settings; @@ -48,7 +46,7 @@ public class SimilarStartsTableModel extends AddressBasedTableModel getColumnRenderer() { final GColumnRenderer monospacedRenderer = new AbstractGColumnRenderer<>() { + @Override - protected void configureFont(JTable table, TableModel model, int column) { - setFont(getFixedWidthFont()); + protected Font getDefaultFont() { + return fixedWidthFont; } @Override diff --git a/Ghidra/Extensions/sample/src/main/java/ghidra/examples/HelloWorldComponentProvider.java b/Ghidra/Extensions/sample/src/main/java/ghidra/examples/HelloWorldComponentProvider.java index 3235a57ca9..30a32ab8b6 100644 --- a/Ghidra/Extensions/sample/src/main/java/ghidra/examples/HelloWorldComponentProvider.java +++ b/Ghidra/Extensions/sample/src/main/java/ghidra/examples/HelloWorldComponentProvider.java @@ -15,7 +15,8 @@ */ package ghidra.examples; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.FlowLayout; import java.awt.event.*; import javax.swing.*; @@ -30,8 +31,8 @@ import ghidra.util.HelpLocation; import ghidra.util.Msg; public class HelloWorldComponentProvider extends ComponentProviderAdapter { - private final static HelpLocation HELP = new HelpLocation("SampleHelpTopic", - "SampleHelpTopic_Anchor_Name"); + private final static HelpLocation HELP = + new HelpLocation("SampleHelpTopic", "SampleHelpTopic_Anchor_Name"); private MyButton activeButtonObj; private JPanel mainPanel; private DockingAction action; @@ -64,8 +65,8 @@ public class HelloWorldComponentProvider extends ComponentProviderAdapter { // the menu item will appear on the local toolbar drop down. Icon icon = new GIcon("icon.sample.action.hello.world"); action.setMenuBarData(new MenuData(new String[] { "Misc", "Hello World" }, icon)); - action.setKeyBindingData(new KeyBindingData(KeyStroke.getKeyStroke(KeyEvent.VK_W, - InputEvent.CTRL_MASK))); + action.setKeyBindingData( + new KeyBindingData(KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.CTRL_MASK))); // puts the action on the local toolbar. action.setToolBarData(new ToolBarData(icon)); @@ -81,11 +82,11 @@ public class HelloWorldComponentProvider extends ComponentProviderAdapter { public void actionPerformed(ActionContext context) { announce("Hello World"); - // To get the context object, + // To get the context object, Object contextObject = context.getContextObject(); // ...now we can cast activeObj to be a object of MyButton - // if that is necessary, as the overridden isAddToPopup() method below + // if that is necessary, as the overridden isAddToPopup() method below // will not add the popup action if the context object is not our button @SuppressWarnings("unused") @@ -120,8 +121,6 @@ public class HelloWorldComponentProvider extends ComponentProviderAdapter { JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER)); panel.setBorder(BorderFactory.createTitledBorder("Example of a Component")); activeButtonObj = new MyButton("Hello World"); - Font f = activeButtonObj.getFont(); - activeButtonObj.setFont(f.deriveFont(Font.BOLD, 14)); panel.add(activeButtonObj); mainPanel.add(panel, BorderLayout.CENTER); } diff --git a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/overview/BSimOverviewModel.java b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/overview/BSimOverviewModel.java index d7d4bcd9a3..e3540f3346 100755 --- a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/overview/BSimOverviewModel.java +++ b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/overview/BSimOverviewModel.java @@ -16,12 +16,11 @@ package ghidra.features.bsim.gui.overview; import java.awt.Component; +import java.awt.Font; import java.util.ArrayList; import java.util.List; import javax.swing.JLabel; -import javax.swing.JTable; -import javax.swing.table.TableModel; import docking.widgets.table.*; import generic.lsh.vector.LSHVectorFactory; @@ -233,8 +232,8 @@ public class BSimOverviewModel extends AddressBasedTableModel results = new ArrayList(); // Maps functions (represented by addresses) to the number of matches in the query. - // This is here to provide quick access for the MatchCountTableColumn. + // This is here to provide quick access for the MatchCountTableColumn. private Map functionMatchMap = new HashMap<>(); public BSimMatchResultsModel(PluginTool tool, DatabaseInformation info, @@ -70,15 +69,15 @@ public class BSimMatchResultsModel extends AddressBasedTableModel queryResults) { @@ -192,7 +191,7 @@ public class BSimMatchResultsModel extends AddressBasedTableModel { @@ -404,7 +403,7 @@ public class BSimMatchResultsModel extends AddressBasedTableModel 0) { userName = "\n" + userName; } - doc.insertString(offset, userName, userAttrSet); + doc.insertString(offset, userName, userAttrs); offset = doc.getLength(); doc.insertString(offset, - "\t" + DateUtils.formatDateTimestamp(history.getModificationDate()), dateAttrSet); + "\t" + DateUtils.formatDateTimestamp(history.getModificationDate()), dateAttrs); doc.setParagraphAttributes(offset, 1, tabAttrSet, false); offset = doc.getLength(); @@ -112,25 +113,13 @@ class CommentHistoryPanel extends JPanel { } private void setUpAttributes() { - textAttrSet = new SimpleAttributeSet(); - textAttrSet.addAttribute(StyleConstants.FontFamily, "Monospaced"); - textAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12)); - textAttrSet.addAttribute(StyleConstants.Foreground, - new GColor("color.fg.plugin.comments.history.text")); - userAttrSet = new SimpleAttributeSet(); - userAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); - userAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12)); - userAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE); - userAttrSet.addAttribute(StyleConstants.Foreground, - new GColor("color.fg.plugin.comments.history.user")); - - dateAttrSet = new SimpleAttributeSet(); - dateAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); - dateAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11)); - dateAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE); - dateAttrSet.addAttribute(StyleConstants.Foreground, - new GColor("color.fg.plugin.comments.history.date")); + Font bold = Gui.getFont("font.standard.bold"); + Font monospaced = Gui.getFont("font.monospaced"); + textAttrSet = + new GAttributes(monospaced, new GColor("color.fg.plugin.comments.history.text")); + userAttrs = new GAttributes(bold, new GColor("color.fg.plugin.comments.history.user")); + dateAttrs = new GAttributes(bold, new GColor("color.fg.plugin.comments.history.date")); tabAttrSet = new SimpleAttributeSet(); TabStop tabs = new TabStop(100, StyleConstants.ALIGN_LEFT, TabStop.LEAD_NONE); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/cparser/ParseDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/cparser/ParseDialog.java index 6a42cff0b5..c07818f942 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/cparser/ParseDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/cparser/ParseDialog.java @@ -39,6 +39,7 @@ import docking.widgets.pathmanager.PathnameTablePanel; import docking.widgets.table.GTableCellRenderer; import docking.widgets.table.GTableCellRenderingData; import generic.jar.ResourceFile; +import generic.theme.Gui; import ghidra.app.plugin.core.processors.SetLanguageDialog; import ghidra.app.util.cparser.C.CParserUtils; import ghidra.framework.Application; @@ -371,8 +372,7 @@ class ParseDialog extends ReusableDialogComponentProvider { updateArchitectureDescription(); languageButton.setName("Set Processor Architecture"); - Font font = languageButton.getFont(); - languageButton.setFont(font.deriveFont(Font.BOLD)); + Gui.registerFont(languageButton, Font.BOLD); JPanel panel = new JPanel(new BorderLayout()); panel.add(languageTextField, BorderLayout.CENTER); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/FunctionEditorDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/FunctionEditorDialog.java index cc5f5973ec..027e131190 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/FunctionEditorDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/FunctionEditorDialog.java @@ -246,8 +246,6 @@ public class FunctionEditorDialog extends DialogComponentProvider implements Mod signatureFieldUndoRedoKeeper = DockingUtils.installUndoRedo(signatureTextField); - Font font = signatureTextField.getFont(); - signatureTextField.setFont(font.deriveFont(18.0f)); panel.add(signatureTextField); signatureTextField.setEscapeListener(e -> { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/FunctionSignatureTextField.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/FunctionSignatureTextField.java index 2d256a9eda..f1174ede46 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/FunctionSignatureTextField.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/FunctionSignatureTextField.java @@ -15,7 +15,8 @@ */ package ghidra.app.plugin.core.function.editor; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Color; import java.awt.event.*; import java.util.ArrayList; import java.util.List; @@ -26,12 +27,16 @@ import javax.swing.text.*; import docking.actions.KeyBindingUtils; import generic.theme.GColor; +import generic.theme.Gui; import ghidra.util.Swing; class FunctionSignatureTextField extends JTextPane { private static final String ENTER_ACTION_NAME = "ENTER"; private static final String ESCAPE_ACTION_NAME = "ESCAPE"; private static final String TAB_ACTION_NAME = "TAB"; + + private static final String FONT_ID = "font.plugin.function.text.editor"; + public static Color DEFAULT_COLOR = new GColor("color.fg.plugin.function.editor.dialog.textfield.default"); public static Color PARAMETER_NAME_COLOR = @@ -52,8 +57,7 @@ class FunctionSignatureTextField extends JTextPane { private SimpleAttributeSet errorAttributes; FunctionSignatureTextField() { - Font myFont = getFont(); - setFont(myFont.deriveFont(24.0f)); + Gui.registerFont(this, FONT_ID); doc = getStyledDocument(); AttributeSet inputAttributes = getInputAttributes(); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/textarea/HintTextArea.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/HintTextArea.java similarity index 76% rename from Ghidra/Framework/Docking/src/main/java/docking/widgets/textarea/HintTextArea.java rename to Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/HintTextArea.java index e2cfd3d636..140ae75bc5 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/textarea/HintTextArea.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/HintTextArea.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package docking.widgets.textarea; +package ghidra.app.plugin.core.instructionsearch.ui; import java.awt.*; @@ -23,8 +23,8 @@ import generic.theme.GThemeDefaults.Colors; import generic.theme.GThemeDefaults.Colors.Messages; /** - * Simple text area that shows a text hint when the field is empty. - * + * Simple text area that shows a text hint when the field is empty. + * * Hint text will be shown in light grey, italicized, and in angle brackets. Normal text will * be plain black. */ @@ -34,7 +34,7 @@ public class HintTextArea extends JTextArea { /** * Constructs the class with the hint text to be shown. - * + * * @param hint the hint */ public HintTextArea(String hint) { @@ -42,8 +42,8 @@ public class HintTextArea extends JTextArea { } /** - * Need to override the setText method so we can set font attributes. - * + * Need to override the setText method so we can set formatting attributes. + * * @param text the text */ @Override @@ -74,7 +74,27 @@ public class HintTextArea extends JTextArea { * Sets the text attributes to be used when NOT viewing the hint. */ protected void setAttributes() { - this.setFont(getFont().deriveFont(Font.PLAIN)); setForeground(Colors.FOREGROUND); } + + /** + * Sets the text attributes to be used when there is an error in the input. + */ + private void setErrorAttributes() { + setForeground(Colors.ERROR); + } + + /** + * Invoked. when the text in the box does not pass validation. + */ + public void setError() { + setErrorAttributes(); + } + + /** + * Invoked when the text in the box passes validation. + */ + public void setValid() { + setAttributes(); + } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/HintTextAreaIS.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/HintTextAreaIS.java deleted file mode 100644 index ba0e87cf72..0000000000 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/HintTextAreaIS.java +++ /dev/null @@ -1,62 +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 ghidra.app.plugin.core.instructionsearch.ui; - -import java.awt.Font; - -import docking.widgets.textarea.HintTextArea; -import generic.theme.GThemeDefaults.Colors; - -/** - * Allows users to provide a text hint in a text field, shown only when the text is empty. - *

- * Hint text will be shown in light grey, italicized, and in angle brackets. Normal text will - * be plain black. - */ -public class HintTextAreaIS extends HintTextArea { - - /** - * Constructs the class with the hint text to be shown. - * - * @param hint the hint - */ - public HintTextAreaIS(final String hint) { - super(hint); - } - - /** - * Invoked. when the text in the box does not pass validation. - */ - public void setError() { - setErrorAttributes(); - } - - /** - * Invoked when the text in the box passes validation. - */ - public void setValid() { - setAttributes(); - } - - /** - * Sets the text attributes to be used when there is an error in the input. - */ - private void setErrorAttributes() { - this.setFont(getFont().deriveFont(Font.PLAIN)); - setForeground(Colors.ERROR); - } - -} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InsertBytesWidget.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InsertBytesWidget.java index 84d922f04b..f5a11e3d98 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InsertBytesWidget.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InsertBytesWidget.java @@ -47,7 +47,7 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement // The input text area. This is a generic JTextArea but displays a textual 'hint' to inform // the user of what type of input is required. - private HintTextAreaIS inputBytesTA; + private HintTextArea inputBytesTA; private SelectionModeWidget selectionModeWidget; private EndianFlipWidget endianFlipWidget; @@ -79,7 +79,7 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement /** * Constructor. - * + * * @param program the current program * @param dialog the parent search dialog */ @@ -108,7 +108,7 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement * Load a set of bytes (in string form; hex or binary) into the search * dialog. The bytes are disassembled and displayed in the * {@link InstructionTable}. - * + * * @param bytes the bytes to load */ public void loadBytes(String bytes) { @@ -139,7 +139,7 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement /** * Creates the visual components for this dialog. - * + * * @return the new panel */ protected JPanel createWorkPanel() { @@ -148,7 +148,7 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement contentPanel.setMinimumSize(new Dimension(500, 300)); // Create the input text widget and give it a scrollbar. - inputBytesTA = new HintTextAreaIS(HINT_TEXT); + inputBytesTA = new HintTextArea(HINT_TEXT); JScrollPane scrollPane = new JScrollPane(inputBytesTA); inputBytesTA.addKeyListener(this); @@ -188,7 +188,7 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement msgPanel.clear(); // When bringing up the dialog, always populate it with whatever is in the main dialog so - // the user can edit those instructions if desired. And make sure to set the entire + // the user can edit those instructions if desired. And make sure to set the entire // string to be selected so they can quickly delete them with a single keystroke. // // Note: To get the correct string for the instruction, we go to the search data @@ -251,20 +251,20 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement List allBytes = InstructionSearchUtils.toByteArray(input); // Now we have a valid byte string so we can start disassembling. To do this, we pass - // the entire string to the pseudo-disassembler and it will return the first + // the entire string to the pseudo-disassembler and it will return the first // instruction. We save that one off, then remove those bytes from the main string and - // pass the now-shorter string to the disassembler, where it will return the next + // pass the now-shorter string to the disassembler, where it will return the next // instruction, and so on, and so on... // - // TODO: Possibly modify the PseudoDisassembler to disassemble the entire thing at + // TODO: Possibly modify the PseudoDisassembler to disassemble the entire thing at // once, not just one instruction at a time. // // NOTE: Some instructions have operands that cannot be accurately calculated - // without having a specific instruction instance (ie: an operand that is an + // without having a specific instruction instance (ie: an operand that is an // offset from the instruction address). This is obviously problematic because we - // aren't dealing with 'real' instructions that map to an address in a program; - // we're just loading bytes and trying to figure out what instructions they - // might represent. In these cases we just use the minimum address of the loaded + // aren't dealing with 'real' instructions that map to an address in a program; + // we're just loading bytes and trying to figure out what instructions they + // might represent. In these cases we just use the minimum address of the loaded // program as the base address. List instructions = new ArrayList<>(); @@ -272,7 +272,7 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement while (allBytes.size() > 0) { try { - // First call the disassembler to get the first instruction. + // First call the disassembler to get the first instruction. Byte[] bytearray = new Byte[allBytes.size()]; bytearray = allBytes.toArray(bytearray); @@ -318,10 +318,10 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement /** * Creates {@link OperandMetadata} objects for each operand in the * instruction provided. - * + * * @param instruction the instruction to parse * @return list of operand metadata - * @throws MemoryAccessException + * @throws MemoryAccessException if there is an exception getting instruction bytes */ private List createOperandMetadata(PseudoInstruction instruction) throws MemoryAccessException { @@ -334,7 +334,7 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement operandMD.setOpType(instruction.getOperandType(i)); operandMD.setTextRep(instruction.getDefaultOperandRepresentation(i)); - // The mask container is a bit tricky. The mask string we can get directly from the + // The mask container is a bit tricky. The mask string we can get directly from the // prototype object in the pseudo instruction. For the value string we have to do // a bit of calculating: we know the entire instruction byte string and we know // this operand mask, so AND them together and we get the operand bytes. @@ -353,15 +353,15 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement /** * Creates a {@link InstructionMetadata} object for the instruction * provided. - * + * * @param instruction the instruction to parse * @return the instruction metadata - * @throws MemoryAccessException + * @throws MemoryAccessException if there is an exception getting instruction bytes */ private InstructionMetadata createInstructionMetadata(PseudoInstruction instruction) throws MemoryAccessException { - // The mask array we can get directly from the prototype. For the value array we + // The mask array we can get directly from the prototype. For the value array we // have to figure out which bits pertain to operands and just zero them out, so we're // just left with the instruction (mnemonic) bits. InstructionPrototype prototype = instruction.getPrototype(); @@ -387,7 +387,7 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement *

  • value = 01101100 10001110
  • *
  • --------------------------
  • *
  • ret = 01101000 10000000
  • - * + * * @param mask the mnemonic mask * @param value the full instruction value string * @return the cleared byte array @@ -400,7 +400,7 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement * Verifies that the input entered by the user is valid. Meaning: *
  • The string represents a hex or binary number.
  • *
  • The string contains only full bytes.
  • - * + * * @return true if input is valid */ public boolean validateInput() { @@ -409,7 +409,7 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement /** * Verifies that the given string is valid binary or hex input. - * + * * @param input the string to validate * @return true if valid */ @@ -480,7 +480,7 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement /** * Flags the given string as invalid input - * + * */ public void setInputInvalid() { inputBytesTA.setError(); @@ -505,12 +505,12 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement /** * Need to capture keystrokes so we can validate input on the fly. Every * time a character is typed we check the entire input for correctness. - * + * * Note that this MUST be done in the release handler; in the type or press * handler the input widget has not officially been updated with the new * character. - * - * @param e + * + * @param e the event */ @Override public void keyReleased(KeyEvent e) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InstructionTableCellRenderer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InstructionTableCellRenderer.java index d6833c37a8..6c745e4e05 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InstructionTableCellRenderer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InstructionTableCellRenderer.java @@ -17,8 +17,8 @@ package ghidra.app.plugin.core.instructionsearch.ui; import java.awt.*; -import javax.swing.*; -import javax.swing.table.TableModel; +import javax.swing.JLabel; +import javax.swing.SwingConstants; import docking.widgets.table.GTableCellRenderingData; import generic.theme.Gui; @@ -45,20 +45,12 @@ public class InstructionTableCellRenderer extends GhidraTableCellRenderer { public Component getTableCellRendererComponent(GTableCellRenderingData data) { Object value = data.getValue(); - JTable table = data.getTable(); - int column = data.getColumnViewIndex(); - boolean isSelected = data.isSelected(); boolean hasFocus = data.hasFocus(); - - // Do a null check on the input here to protect ourselves. This value can be null - // in certain cases (eg: change resolution on the screen [ctrl-+ on mac], then move the - // instruction window to a different monitor, then click on a cell). if (value == null) { return this; } - // Get the data object backing the cell. InstructionTableDataObject dataObject = (InstructionTableDataObject) value; String strData = dataObject.getData(); @@ -66,7 +58,7 @@ public class InstructionTableCellRenderer extends GhidraTableCellRenderer { JLabel theRenderer = (JLabel) super.getTableCellRendererComponent(renderData); - setTextAttributes(table, value, column); + setTextAttributes(); setBackgroundAttributes(isSelected, hasFocus, dataObject); setBorderAttributes(dataObject, theRenderer); setForegroundAttributes(dataObject, theRenderer); @@ -80,8 +72,6 @@ public class InstructionTableCellRenderer extends GhidraTableCellRenderer { private void setForegroundAttributes(InstructionTableDataObject dataObject, JLabel theRenderer) { - // Change the foreground to use a font of our choosing. The main reason is that we - // want to use a monospaced font for binary rendering. theRenderer.setForeground(dataObject.getForegroundColor()); Font newFont = theRenderer.getFont().deriveFont(dataObject.getFontStyle()); theRenderer.setFont(newFont); @@ -89,8 +79,6 @@ public class InstructionTableCellRenderer extends GhidraTableCellRenderer { private void setBackgroundAttributes(boolean isSelected, boolean hasFocus, InstructionTableDataObject dataObject) { - // Set the background color based on what the cell says. If it's selected, make it a - // bit darker. Color backgroundColor = dataObject.getBackgroundColor(); if (backgroundColor != null) { if (isSelected || hasFocus) { @@ -102,10 +90,9 @@ public class InstructionTableCellRenderer extends GhidraTableCellRenderer { } } - private void setTextAttributes(JTable table, Object value, int col) { + private void setTextAttributes() { setHorizontalAlignment(SwingConstants.LEFT); - TableModel model = table.getModel(); - configureFont(table, model, col); + setFont(getDefaultFont()); setOpaque(true); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/CodeCompletionWindow.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/CodeCompletionWindow.java index cadedb4ce8..a8402e26eb 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/CodeCompletionWindow.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/CodeCompletionWindow.java @@ -26,6 +26,7 @@ import javax.swing.event.ListDataListener; import docking.widgets.list.GListCellRenderer; import generic.theme.GThemeDefaults.Colors.Tooltips; +import generic.theme.Gui; import generic.util.WindowUtilities; import ghidra.app.plugin.core.console.CodeCompletion; @@ -34,23 +35,25 @@ import ghidra.app.plugin.core.console.CodeCompletion; */ public class CodeCompletionWindow extends JDialog { + private static final String FONT_ID = "font.plugin.terminal.completion.list"; + protected final InterpreterPanel console; protected final JTextPane outputTextField; /* List of CodeCompletions. * If the substitution value is null, then that attribute will not be * selectable for substitution. */ - protected List completion_list; + protected List completionData; /* current list of completions */ - protected JList jlist; + protected JList jlist; public CodeCompletionWindow(Window parent, InterpreterPanel cp, JTextPane textField) { super(parent); this.console = cp; outputTextField = textField; - jlist = new JList(); - completion_list = null; + jlist = new JList<>(); + completionData = null; setUndecorated(true); /* don't steal focus from text input! */ @@ -58,14 +61,14 @@ public class CodeCompletionWindow extends JDialog { jlist.setBackground(Tooltips.BACKGROUND); jlist.setCellRenderer(new CodeCompletionListCellRenderer()); - /* add the ability to double-click a code completion */ + + // add the ability to double-click a code completion MouseListener mouseListener = new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { - /* when the user clicks the popup window, make sure - * that the outputTextField gets the focus (so that the escape - * key and other hotkeys to manage the popup work correctly - */ + // when the user clicks the popup window, make sure that the outputTextField gets + // the focus (so that the escape key and other hotkeys to manage the popup work + // correctly outputTextField.requestFocusInWindow(); /* double-click inserts a completion */ if (e.getClickCount() == 2) { @@ -74,9 +77,9 @@ public class CodeCompletionWindow extends JDialog { } }; jlist.addMouseListener(mouseListener); - /* actually put the components together */ + getContentPane().add(new JScrollPane(jlist)); - updateCompletionList(completion_list); + updateCompletionList(completionData); jlist.addKeyListener(new KeyAdapter() { @Override @@ -121,7 +124,7 @@ public class CodeCompletionWindow extends JDialog { * @param list List of code completions */ public void updateCompletionList(List list) { - completion_list = list; + completionData = list; jlist.setModel(new CodeCompletionListModel(list)); jlist.setSelectionModel(new CodeCompletionListSelectionModel(list)); jlist.clearSelection(); @@ -247,7 +250,7 @@ public class CodeCompletionWindow extends JDialog { */ @Override public void setFont(Font font) { - jlist.setFont(font); + Gui.registerFont(jlist, FONT_ID); } /** @@ -256,7 +259,7 @@ public class CodeCompletionWindow extends JDialog { */ public void selectPrevious() { for (int i = jlist.getSelectedIndex() - 1; i >= 0; i--) { - CodeCompletion completion = completion_list.get(i); + CodeCompletion completion = completionData.get(i); if (CodeCompletion.isValid(completion)) { jlist.setSelectedIndex(i); jlist.ensureIndexIsVisible(i); @@ -271,11 +274,11 @@ public class CodeCompletionWindow extends JDialog { */ public void selectNext() { - if (null == completion_list) { + if (null == completionData) { return; } - for (int i = jlist.getSelectedIndex() + 1; i < completion_list.size(); i++) { - CodeCompletion completion = completion_list.get(i); + for (int i = jlist.getSelectedIndex() + 1; i < completionData.size(); i++) { + CodeCompletion completion = completionData.get(i); if (CodeCompletion.isValid(completion)) { jlist.setSelectedIndex(i); jlist.ensureIndexIsVisible(i); @@ -296,18 +299,18 @@ public class CodeCompletionWindow extends JDialog { if (-1 == i) { return null; } - return completion_list.get(i); + return completionData.get(i); } } /** * Code completion ListModel. */ -class CodeCompletionListModel implements ListModel { - List completion_list; +class CodeCompletionListModel implements ListModel { + List completionData; public CodeCompletionListModel(List completion_list) { - this.completion_list = completion_list; + this.completionData = completion_list; } @Override @@ -321,22 +324,22 @@ class CodeCompletionListModel implements ListModel { } @Override - public Object getElementAt(int index) { - if ((null == completion_list) || completion_list.isEmpty()) { + public CodeCompletion getElementAt(int index) { + if ((null == completionData) || completionData.isEmpty()) { if (0 == index) { return new CodeCompletion("(no completions available)", null, null); } return null; } - return completion_list.get(index); + return completionData.get(index); } @Override public int getSize() { - if ((null == completion_list) || completion_list.isEmpty()) { + if ((null == completionData) || completionData.isEmpty()) { return 1; } - return completion_list.size(); + return completionData.size(); } } @@ -405,12 +408,8 @@ class CodeCompletionListCellRenderer extends GListCellRenderer { @Override public Component getListCellRendererComponent(JList list, CodeCompletion codeCompletion, int index, boolean isSelected, boolean cellHasFocus) { - if (codeCompletion.getComponent() == null) { - return super.getListCellRendererComponent(list, codeCompletion, index, isSelected, - cellHasFocus); - } - - JComponent component = codeCompletion.getComponent(); + JLabel component = (JLabel) super.getListCellRendererComponent(list, codeCompletion, index, + isSelected, cellHasFocus); // if it's selected, make sure it shows up that way component.setOpaque(true); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterPanel.java index 648f6345fc..7825d4483f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterPanel.java @@ -28,8 +28,7 @@ import javax.swing.text.*; import docking.DockingUtils; import docking.actions.KeyBindingUtils; -import generic.theme.GColor; -import generic.theme.Gui; +import generic.theme.*; import generic.util.WindowUtilities; import ghidra.app.plugin.core.console.CodeCompletion; import ghidra.framework.options.OptionsChangeListener; @@ -50,9 +49,9 @@ public class InterpreterPanel extends JPanel implements OptionsChangeListener { "This is the font that will be used in the Console. " + "Double-click the font example to change it."; - private static final Color NORMAL_COLOR = new GColor("color.fg.interpreterconsole"); - private static final Color ERROR_COLOR = new GColor("color.fg.interpreterconsole.error"); - private static final Color BG_COLOR = new GColor("color.bg.interpreterconsole"); + private static final GColor NORMAL_COLOR = new GColor("color.fg.interpreterconsole"); + private static final GColor ERROR_COLOR = new GColor("color.fg.interpreterconsole.error"); + private static final GColor BG_COLOR = new GColor("color.bg.interpreterconsole"); public enum TextType { STDOUT, STDERR, STDIN; @@ -84,16 +83,6 @@ public class InterpreterPanel extends JPanel implements OptionsChangeListener { private boolean caretGuard = true; private PluginTool tool; - private static SimpleAttributeSet createAttributes(Font font, Color color) { - SimpleAttributeSet attributeSet = new SimpleAttributeSet(); - attributeSet.addAttribute(StyleConstants.FontFamily, font.getFamily()); - attributeSet.addAttribute(StyleConstants.FontSize, font.getSize()); - attributeSet.addAttribute(StyleConstants.Italic, font.isItalic()); - attributeSet.addAttribute(StyleConstants.Bold, font.isBold()); - attributeSet.addAttribute(StyleConstants.Foreground, color); - return attributeSet; - } - public InterpreterPanel(PluginTool tool, InterpreterConnection interpreter) { this.tool = tool; this.interpreter = interpreter; @@ -373,9 +362,11 @@ public class InterpreterPanel extends JPanel implements OptionsChangeListener { private void updateFontAttributes(Font font) { Font boldFont = font.deriveFont(Font.BOLD); - STDOUT_SET = createAttributes(font, NORMAL_COLOR); - STDERR_SET = createAttributes(font, ERROR_COLOR); - STDIN_SET = createAttributes(boldFont, NORMAL_COLOR); + + STDOUT_SET = new GAttributes(font, NORMAL_COLOR); + STDOUT_SET = new GAttributes(font, NORMAL_COLOR); + STDERR_SET = new GAttributes(font, ERROR_COLOR); + STDIN_SET = new GAttributes(boldFont, NORMAL_COLOR); setTextPaneFont(inputTextPane, boldFont); setTextPaneFont(promptTextPane, font); @@ -389,8 +380,7 @@ public class InterpreterPanel extends JPanel implements OptionsChangeListener { HelpLocation help = new HelpLocation(getName(), "ConsolePlugin"); options.setOptionsHelpLocation(help); - options.registerThemeFontBinding(FONT_OPTION_LABEL, FONT_ID, help, - FONT_DESCRIPTION); + options.registerThemeFontBinding(FONT_OPTION_LABEL, FONT_ID, help, FONT_DESCRIPTION); options.registerOption(COMPLETION_WINDOW_TRIGGER_LABEL, CompletionWindowTrigger.TAB, help, COMPLETION_WINDOW_TRIGGER_DESCRIPTION); @@ -490,8 +480,8 @@ public class InterpreterPanel extends JPanel implements OptionsChangeListener { completionInsertionPosition = inputTextPane.getCaretPosition(); String text = getInputTextPaneText(); - List completions = InterpreterPanel.this.interpreter.getCompletions( - text, completionInsertionPosition); + List completions = + InterpreterPanel.this.interpreter.getCompletions(text, completionInsertionPosition); completionWindow.updateCompletionList(completions); }); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapProvider.java index d10b3c4dfd..1326421311 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapProvider.java @@ -67,7 +67,7 @@ class MemoryMapProvider extends ComponentProviderAdapter { private DockingAction deleteAction; private DockingAction setBaseAction; - private MemoryMapPlugin plugin = null; + private MemoryMapPlugin plugin; private Program program; private MemoryMapManager memManager; @@ -135,8 +135,12 @@ class MemoryMapProvider extends ComponentProviderAdapter { table.installNavigation(tool); table.setAutoCreateColumnsFromModel(false); - GTableCellRenderer monoRenderer = new GTableCellRenderer(); - monoRenderer.setFont(monoRenderer.getFixedWidthFont()); + GTableCellRenderer monoRenderer = new GTableCellRenderer() { + @Override + protected Font getDefaultFont() { + return fixedWidthFont; + } + }; TableColumn column = table.getColumn(MemoryMapModel.START_COL); column.setCellRenderer(monoRenderer); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/EditReferencesProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/EditReferencesProvider.java index 600a8cc99e..1ec62a6d0e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/EditReferencesProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/references/EditReferencesProvider.java @@ -1019,8 +1019,6 @@ public class EditReferencesProvider extends ComponentProviderAdapter private class RefCellTextRenderer extends GTableCellRenderer { RefCellTextRenderer() { - defaultFont = getFont(); - boldFont = defaultFont.deriveFont(defaultFont.getStyle() | Font.BOLD); setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 0)); } 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 75c4f2bf81..2a998d17b1 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 @@ -28,7 +28,6 @@ import docking.widgets.OptionDialog; import docking.widgets.table.*; import generic.theme.GColor; import generic.theme.GThemeDefaults.Colors.Palette; -import generic.theme.Gui; import ghidra.app.cmd.register.SetRegisterCmd; import ghidra.app.events.ProgramSelectionPluginEvent; import ghidra.app.services.MarkerService; @@ -498,7 +497,11 @@ class RegisterValueRenderer extends GTableCellRenderer { RegisterValueRenderer(JTable table) { setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); - Gui.registerFont(this, "font.monospaced"); + } + + @Override + protected Font getDefaultFont() { + return fixedWidthFont; } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/SetRegisterValueDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/SetRegisterValueDialog.java index a077bf5ceb..8eb33f004a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/SetRegisterValueDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/SetRegisterValueDialog.java @@ -28,6 +28,7 @@ import javax.swing.event.ChangeListener; import docking.DialogComponentProvider; import docking.widgets.combobox.GComboBox; import docking.widgets.label.GLabel; +import generic.theme.GThemeDefaults.Ids.Fonts; import generic.theme.Gui; import ghidra.app.util.bean.FixedBitSizeValueField; import ghidra.program.model.address.*; @@ -77,8 +78,6 @@ public class SetRegisterValueDialog extends DialogComponentProvider { private JComponent buildWorkPanel(Register[] registers) { registerComboBox = new GComboBox<>(wrapRegisters(registers)); - Font f = registerComboBox.getFont().deriveFont(13f); - registerComboBox.setFont(f); registerValueField = new FixedBitSizeValueField(32, true, false); registerValueField.addChangeListener(new ChangeListener() { @Override @@ -93,11 +92,11 @@ public class SetRegisterValueDialog extends DialogComponentProvider { registerChanged(); } }); - f = Gui.getFont("font.monospaced"); addressRangeList = new JList(); addressRangeList.setEnabled(false); - addressRangeList.setFont(f); + Gui.registerFont(addressRangeList, Fonts.MONOSPACED); + JScrollPane scrollPane = new JScrollPane(addressRangeList); scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); Dimension d = scrollPane.getPreferredSize(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/scalartable/ScalarSearchModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/scalartable/ScalarSearchModel.java index d769c11d20..61abea9a46 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/scalartable/ScalarSearchModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/scalartable/ScalarSearchModel.java @@ -16,11 +16,12 @@ package ghidra.app.plugin.core.scalartable; import java.awt.Component; +import java.awt.Font; import java.math.BigInteger; import java.util.Comparator; -import javax.swing.*; -import javax.swing.table.TableModel; +import javax.swing.JLabel; +import javax.swing.SwingConstants; import docking.widgets.table.*; import ghidra.docking.settings.Settings; @@ -321,7 +322,7 @@ public class ScalarSearchModel extends AddressBasedTableModel { //================================================================================================== // Columns & Column helpers -//================================================================================================== +//================================================================================================== private class ScalarComparator implements Comparator { @@ -339,8 +340,7 @@ public class ScalarSearchModel extends AddressBasedTableModel { return (o1.isSigned() ? 1 : -1); } - return o1.isSigned() - ? Long.compare(o1.getSignedValue(), o2.getSignedValue()) + return o1.isSigned() ? Long.compare(o1.getSignedValue(), o2.getSignedValue()) : Long.compareUnsigned(o1.getUnsignedValue(), o2.getUnsignedValue()); } } @@ -410,15 +410,14 @@ public class ScalarSearchModel extends AddressBasedTableModel { } @Override - protected void configureFont(JTable table, TableModel model, int column) { - setFont(fixedWidthFont); + protected Font getDefaultFont() { + return fixedWidthFont; } @Override public ColumnConstraintFilterMode getColumnConstraintFilterMode() { return ColumnConstraintFilterMode.ALLOW_ALL_FILTERS; } - }; @Override @@ -440,10 +439,7 @@ public class ScalarSearchModel extends AddressBasedTableModel { public Scalar getValue(ScalarRowObject rowObject, Settings settings, Program p, ServiceProvider provider) throws IllegalArgumentException { Scalar scalar = rowObject.getScalar(); - - Scalar unsigned = new Scalar(scalar.bitLength(), scalar.getUnsignedValue(), false); - return unsigned; - + return new Scalar(scalar.bitLength(), scalar.getUnsignedValue(), false); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/strings/EncodedStringsDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/strings/EncodedStringsDialog.java index 0c47de5707..31dd8fee4e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/strings/EncodedStringsDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/strings/EncodedStringsDialog.java @@ -38,7 +38,7 @@ import docking.widgets.spinner.IntegerSpinner; import docking.widgets.table.threaded.ThreadedTableModelListener; import generic.jar.ResourceFile; import generic.theme.GThemeDefaults; -import ghidra.app.services.GoToService; +import generic.theme.Gui; import ghidra.app.services.StringTranslationService; import ghidra.app.services.StringTranslationService.TranslateOptions; import ghidra.docking.settings.Settings; @@ -72,6 +72,8 @@ public class EncodedStringsDialog extends DialogComponentProvider { Map.entry(CharsetInfo.UTF16, UnicodeDataType.dataType), Map.entry(CharsetInfo.UTF32, Unicode32DataType.dataType)); + private static final String BUTTON_FONT_ID = "font.plugin.strings.buttons"; + private final PluginTool tool; private final EncodedStringsPlugin plugin; private final Program program; @@ -148,7 +150,7 @@ public class EncodedStringsDialog extends DialogComponentProvider { /** * For test/screen shot use - * + * * @param charsetName set the charset */ public void setSelectedCharset(String charsetName) { @@ -157,7 +159,7 @@ public class EncodedStringsDialog extends DialogComponentProvider { /** * For test/screen shot use - * + * * @param b boolean */ public void setRequireValidStringOption(boolean b) { @@ -167,7 +169,7 @@ public class EncodedStringsDialog extends DialogComponentProvider { /** * For test/screen shot use - * + * * @param b boolean */ public void setAllowLatinScriptOption(boolean b) { @@ -178,7 +180,7 @@ public class EncodedStringsDialog extends DialogComponentProvider { /** * For test/screen shot use - * + * * @param b boolean */ public void setAllowCommonScriptOption(boolean b) { @@ -189,7 +191,7 @@ public class EncodedStringsDialog extends DialogComponentProvider { /** * For test/screen shot use - * + * * @param b boolean */ public void setAllowAnyScriptOption(boolean b) { @@ -200,7 +202,7 @@ public class EncodedStringsDialog extends DialogComponentProvider { /** * For test/screen shot use - * + * * @param requiredScript unicode script */ public void setRequiredScript(UnicodeScript requiredScript) { @@ -210,7 +212,7 @@ public class EncodedStringsDialog extends DialogComponentProvider { /** * For test/screen shot use - * + * * @param b boolean */ public void setShowAdvancedOptions(boolean b) { @@ -221,7 +223,7 @@ public class EncodedStringsDialog extends DialogComponentProvider { /** * For test/screen shot use - * + * * @param b boolean */ public void setShowScriptOptions(boolean b) { @@ -232,7 +234,7 @@ public class EncodedStringsDialog extends DialogComponentProvider { /** * For test/screen shot use - * + * * @param b boolean */ public void setExcludeCodecErrors(boolean b) { @@ -243,7 +245,7 @@ public class EncodedStringsDialog extends DialogComponentProvider { /** * For test/screen shot use - * + * * @param b boolean */ public void setExcludeNonStdCtrlChars(boolean b) { @@ -254,7 +256,7 @@ public class EncodedStringsDialog extends DialogComponentProvider { /** * For test/screen shot use - * + * * @return table model */ public EncodedStringsTableModel getStringModel() { @@ -263,7 +265,7 @@ public class EncodedStringsDialog extends DialogComponentProvider { /** * For test/screen shot use - * + * * @return button */ public JButton getCreateButton() { @@ -423,8 +425,7 @@ public class EncodedStringsDialog extends DialogComponentProvider { table.setPreferredScrollableViewportSize(new Dimension(350, 150)); table.getSelectionModel().addListSelectionListener(e -> selectedRowChange()); - GoToService goToService = tool.getService(GoToService.class); - table.installNavigation(goToService, goToService.getDefaultNavigatable()); + table.installNavigation(tool); filterPanel = new GhidraTableFilterPanel<>(table, tableModel); } @@ -454,7 +455,7 @@ public class EncodedStringsDialog extends DialogComponentProvider { public void keyPressed(KeyEvent e) { // Note: we override the [ENTER] key handling to allow the user to invoke the // dialog and just hit enter to create the string without having to do any - // clicking (otherwise the charset combobox consumes the keystroke) + // clicking (otherwise the charset combobox consumes the keystroke) if (e.getKeyChar() == '\n') { e.consume(); if (charsetComboBox.isPopupVisible()) { @@ -604,10 +605,10 @@ public class EncodedStringsDialog extends DialogComponentProvider { scriptFailedCountLabel .setToolTipText("Number of strings excluded due to failing script requirements."); - Font font = new JPanel().getFont().deriveFont(10.0f); allowLatinScriptButton = new JToggleButton("A-Z"); allowLatinScriptButton.setName("ALLOW_LATIN_SCRIPT"); - allowLatinScriptButton.setFont(font); + Gui.registerFont(allowLatinScriptButton, BUTTON_FONT_ID); + allowLatinScriptButton.setToolTipText( "Allow Latin characters (e.g. A-Z, etc) to also be present in the string."); allowLatinScriptButton.setSelected(true); @@ -620,7 +621,7 @@ public class EncodedStringsDialog extends DialogComponentProvider { allowCommonScriptButton = new JToggleButton("0-9,!?"); allowCommonScriptButton.setName("ALLOW_COMMON_SCRIPT"); - allowCommonScriptButton.setFont(font); + Gui.registerFont(allowCommonScriptButton, BUTTON_FONT_ID); allowCommonScriptButton.setToolTipText( "Allow common characters (e.g. 0-9, space, punctuation, etc) to also be present in the string."); allowCommonScriptButton.setSelected(true); @@ -633,7 +634,7 @@ public class EncodedStringsDialog extends DialogComponentProvider { allowAnyScriptButton = new JToggleButton("Any"); allowAnyScriptButton.setName("ALLOW_ANY_SCRIPT"); - allowAnyScriptButton.setFont(font); + Gui.registerFont(allowAnyScriptButton, BUTTON_FONT_ID); allowAnyScriptButton.setToolTipText( "Allow all other character scripts to also be present in the string."); allowAnyScriptButton.setSelected(true); @@ -747,13 +748,12 @@ public class EncodedStringsDialog extends DialogComponentProvider { executeMonitoredRunnable("Creating Strings", true, true, 100, this::createStringsAndClose); } - private void setActionItemEnablement(boolean b) { - createButton.setEnabled(b); - cancelButton.setEnabled(b); + private void setActionItemEnablement(boolean enabled) { + createButton.setEnabled(enabled); + cancelButton.setEnabled(enabled); table.removeNavigation(); - if (b) { - GoToService goToService = tool.getService(GoToService.class); - table.installNavigation(goToService, goToService.getDefaultNavigatable()); + if (enabled) { + table.installNavigation(tool); } } @@ -834,11 +834,10 @@ public class EncodedStringsDialog extends DialogComponentProvider { createButton.setEnabled(false); return; } - String createMessage = isSingleStringMode() - ? "Create" - : "Create %s".formatted(rowCount == selectedRowCount || selectedRowCount == 0 - ? "All" - : "Selected (%d)".formatted(selectedRowCount)); + String createMessage = isSingleStringMode() ? "Create" + : "Create %s" + .formatted(rowCount == selectedRowCount || selectedRowCount == 0 ? "All" + : "Selected (%d)".formatted(selectedRowCount)); createButton.setEnabled(true); createButton.setText(createMessage); @@ -954,8 +953,7 @@ public class EncodedStringsDialog extends DialogComponentProvider { return null; } File f = new File(filename); - ResourceFile rf = f.isAbsolute() && f.isFile() - ? new ResourceFile(f) + ResourceFile rf = f.isAbsolute() && f.isFile() ? new ResourceFile(f) : Application.findDataFileInAnyModule(filename); if (rf == null) { Msg.error(this, "Unable to find string model file: %s".formatted(filename)); @@ -1012,8 +1010,7 @@ public class EncodedStringsDialog extends DialogComponentProvider { private StringTranslationService getSelectedStringTranslationService(boolean ifEnabled) { boolean enabled = showTranslateOptionsButton.isSelected(); - return ifEnabled && !enabled - ? null + return ifEnabled && !enabled ? null : (StringTranslationService) translateComboBox.getSelectedItem(); } @@ -1081,7 +1078,7 @@ public class EncodedStringsDialog extends DialogComponentProvider { * Execute a non-modal task that has progress and can be cancelled. *

    * See {@link #executeProgressTask(Task, int)}. - * + * * @param taskTitle String title of task * @param canCancel boolean flag, if true task can be canceled by the user * @param hasProgress boolean flag, if true the task has a progress meter diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/debug/DomainEventComponentProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/debug/DomainEventComponentProvider.java index e51804fe0b..3b09e14664 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/debug/DomainEventComponentProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/debug/DomainEventComponentProvider.java @@ -15,7 +15,6 @@ */ package ghidra.app.plugin.debug; -import java.awt.Font; import java.util.ArrayList; import java.util.List; @@ -59,22 +58,11 @@ public class DomainEventComponentProvider extends ComponentProviderAdapter { return scrollPane; } - /** - * @see docking.ComponentProvider#componentHidden() - */ @Override public void componentHidden() { clear(); } - public Font getFont() { - return textArea.getFont(); - } - - public void setFont(Font font) { - textArea.setFont(font); - } - private void createAction() { clearAction = new DockingAction("Clear Display", getName()) { @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/debug/DomainEventDisplayPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/debug/DomainEventDisplayPlugin.java index 59c1b534e8..b4c434f273 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/debug/DomainEventDisplayPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/debug/DomainEventDisplayPlugin.java @@ -15,7 +15,6 @@ */ package ghidra.app.plugin.debug; -import java.awt.Font; import java.util.Date; import ghidra.app.DeveloperPluginPackage; @@ -47,28 +46,18 @@ public class DomainEventDisplayPlugin extends Plugin implements DomainObjectList private Program currentProgram; private DomainEventComponentProvider provider; - private String padString; - /** - * Constructor - */ public DomainEventDisplayPlugin(PluginTool tool) { super(tool); - String dateStr = new Date() + ": "; - padString = dateStr.replaceAll(".", " "); - provider = new DomainEventComponentProvider(tool, getName()); - // Note: this plugin in the 'Developer' category and as such does not need help + // Note: this plugin in the 'Developer' category and as such does not need help HelpService helpService = Help.getHelpService(); helpService.excludeFromHelp(provider); } - /** - * Put event processing code here. - */ @Override public void processEvent(PluginEvent event) { if (event instanceof ProgramActivatedPluginEvent) { @@ -83,10 +72,6 @@ public class DomainEventDisplayPlugin extends Plugin implements DomainObjectList } } - /** - * Tells a plugin that it is no longer needed. The plugin should remove - * itself from anything that it is registered to and release any resources. - */ @Override public void dispose() { if (currentProgram != null) { @@ -94,9 +79,6 @@ public class DomainEventDisplayPlugin extends Plugin implements DomainObjectList } } - /** - * This is the callback method for DomainObjectChangedEvents. - */ @Override public void domainObjectChanged(DomainObjectChangedEvent ev) { if (tool != null && provider.isVisible()) { @@ -104,24 +86,6 @@ public class DomainEventDisplayPlugin extends Plugin implements DomainObjectList } } - /** - * Get the font for the text area; font property will show up on the - * plugin property sheet. - */ - public Font getFont() { - return provider.getFont(); - } - - /** - * Set the font for the text area; font property will show up on the - * plugin property sheet. - - */ - public void setFont(Font font) { - provider.setFont(font); - tool.setConfigChanged(true); - } - /** * Display the change event. */ diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/gui/WindowLocationPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/gui/WindowLocationPlugin.java index e3e7ef3eab..01271f7d45 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/gui/WindowLocationPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/gui/WindowLocationPlugin.java @@ -27,6 +27,7 @@ import javax.swing.*; import docking.ComponentProvider; import docking.Tool; import generic.theme.GColor; +import generic.theme.Gui; import generic.util.WindowUtilities; import generic.util.image.ImageUtils; import ghidra.app.DeveloperPluginPackage; @@ -110,6 +111,8 @@ public class WindowLocationPlugin extends Plugin { private class WindowLocationPanel extends JPanel { + private static final String FONT_ID = "font.plugin.window.location"; + private MouseListener mousy = new MouseListener(); WindowLocationPanel() { @@ -188,9 +191,8 @@ public class WindowLocationPlugin extends Plugin { } private void paintWindows(Graphics2D g2d, AffineTransform xform) { - Font f = g2d.getFont(); - Font biggerFont = f.deriveFont(40f); - g2d.setFont(biggerFont); + Font f = Gui.getFont(FONT_ID); + g2d.setFont(f); g2d.setColor(FG_COLOR_WINDOW_TEXT); Window[] windows = Window.getWindows(); @@ -423,10 +425,7 @@ public class WindowLocationPlugin extends Plugin { @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((window == null) ? 0 : window.hashCode()); - return result; + return Objects.hash(window); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AbstractVariableFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AbstractVariableFieldFactory.java index 761ffc325f..5a34b674e0 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AbstractVariableFieldFactory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AbstractVariableFieldFactory.java @@ -65,10 +65,12 @@ public abstract class AbstractVariableFieldFactory extends FieldFactory { * @param fieldOptions the Options for field specific properties. */ protected AbstractVariableFieldFactory(String name, FieldFormatModel model, - ListingHighlightProvider highlightProvider, Options displayOptions, Options fieldOptions) { + ListingHighlightProvider highlightProvider, Options displayOptions, + Options fieldOptions) { super(name, model, highlightProvider, displayOptions, fieldOptions); } + @Override protected void initDisplayOptions(Options displayOptions) { // display options for local variables handled by FieldFactory base class @@ -110,8 +112,7 @@ public abstract class AbstractVariableFieldFactory extends FieldFactory { super.displayOptionsChanged(options, optionName, oldValue, newValue); } - @SuppressWarnings("deprecation") - // we know + @SuppressWarnings("deprecation") // ignore getFontMetrics() deprecation warning private void setMetrics(Font newFont, ParameterFieldOptions paramFieldOptions) { paramFieldOptions.defaultMetrics = Toolkit.getDefaultToolkit().getFontMetrics(newFont); for (int i = 0; i < paramFieldOptions.fontMetrics.length; i++) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/FieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/FieldFactory.java index ddc49fcf29..7289431f25 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/FieldFactory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/FieldFactory.java @@ -29,7 +29,6 @@ import ghidra.framework.options.ToolOptions; import ghidra.program.model.listing.Data; import ghidra.program.util.ProgramLocation; import ghidra.util.HelpLocation; -import ghidra.util.SystemUtilities; import ghidra.util.classfinder.ExtensionPoint; /** @@ -66,8 +65,8 @@ public abstract class FieldFactory implements ExtensionPoint { * @param fieldOptions the Options for field specific properties. */ protected FieldFactory(String name, FieldFormatModel model, - ListingHighlightProvider highlightProvider, - Options displayOptions, Options fieldOptions) { + ListingHighlightProvider highlightProvider, Options displayOptions, + Options fieldOptions) { this.name = name; this.model = model; this.hlProvider = highlightProvider; @@ -135,7 +134,7 @@ public abstract class FieldFactory implements ExtensionPoint { public void displayOptionsChanged(Options options, String optionName, Object oldValue, Object newValue) { if (optionName.equals(FONT_OPTION_NAME)) { - baseFont = SystemUtilities.adjustForFontSizeOverride((Font) newValue); + baseFont = (Font) newValue; setMetrics(baseFont); } else if (optionName.equals(styleOptionName)) { @@ -225,7 +224,7 @@ public abstract class FieldFactory implements ExtensionPoint { /** * Returns true if this given field represents the given location * @param listingField the field - * @param location the location + * @param location the location * @return true if this given field represents the given location */ public boolean supportsLocation(ListingField listingField, ProgramLocation location) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/options/OptionsGui.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/options/OptionsGui.java index c2eb8ecb68..8a4ec893c7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/options/OptionsGui.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/options/OptionsGui.java @@ -40,7 +40,6 @@ import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.GhidraOptions; import ghidra.app.util.viewer.field.ListingColors; import ghidra.app.util.viewer.field.ListingColors.*; -import ghidra.util.SystemUtilities; /** * Class for displaying and manipulating field colors and fonts. @@ -133,13 +132,13 @@ public class OptionsGui extends JPanel { /** * Constructor - * + * * @param font the base font for the fields. * @param listener the listener to be notified when options change. */ public OptionsGui(Font font, PropertyChangeListener listener) { propertyChangeListener = listener; - setBaseFont(SystemUtilities.adjustForFontSizeOverride(font)); + setBaseFont(font); genLayouts(); buildPanel(); fieldPanel.setBackgroundColor(BACKGROUND.getColor()); @@ -217,7 +216,7 @@ public class OptionsGui extends JPanel { /** * callback for when the selected display field changes. - * + * * @param index the index in the JList of the selected field. */ private void setSelectedIndex(int index) { @@ -735,7 +734,7 @@ public class OptionsGui extends JPanel { /** * This listener will be notified when changes are made that need to be applied. - * + * * @param listener The listener to be notified. */ void setOptionsPropertyChangeListener(PropertyChangeListener listener) { @@ -774,9 +773,9 @@ public class OptionsGui extends JPanel { setSelectedIndex(selectedIndex); } -//================================================================================================== +//================================================================================================== // Inner Classes -//================================================================================================== +//================================================================================================== /** * Simple layoutModel to be used for the preview panel. @@ -850,7 +849,7 @@ public class OptionsGui extends JPanel { /** * Constructor - * + * * @param size the number of fields in the layout */ LayoutBuilder(int size) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/ConsoleTextPane.java b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/ConsoleTextPane.java index 77891c21ae..0d7a51e43c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/ConsoleTextPane.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/ConsoleTextPane.java @@ -21,9 +21,8 @@ import java.util.LinkedList; import javax.swing.JTextPane; import javax.swing.text.*; -import generic.theme.GColor; +import generic.theme.*; import generic.theme.GThemeDefaults.Ids.Fonts; -import generic.theme.Gui; import ghidra.framework.options.*; import ghidra.framework.plugintool.PluginTool; import ghidra.util.Msg; @@ -31,9 +30,9 @@ import ghidra.util.SystemUtilities; import ghidra.util.exception.AssertException; import ghidra.util.task.SwingUpdateManager; -/** +/** * A generic text pane that is used as a console to which text can be written. - * + * * There is not test for this class, but it is indirectly tested by FrontEndGuiTest. */ public class ConsoleTextPane extends JTextPane implements OptionsChangeListener { @@ -52,8 +51,8 @@ public class ConsoleTextPane extends JTextPane implements OptionsChangeListener /** % of characters to delete when truncation is necessary */ private static double DEFAULT_TRUNCATION_FACTOR = .10; - private static SimpleAttributeSet outputAttributeSet; - private static SimpleAttributeSet errorAttributeSet; + private static SimpleAttributeSet outputAttributes; + private static SimpleAttributeSet errorAttributes; // don't update more than once per second if lots of messages are being written private SwingUpdateManager updateManager = new SwingUpdateManager(100, 1000, () -> doUpdate()); @@ -99,7 +98,7 @@ public class ConsoleTextPane extends JTextPane implements OptionsChangeListener } //================================================================================================== // Non-interface Methods -//================================================================================================== +//================================================================================================== private void initOptions(Options options) { options.registerOption(MAXIMUM_CHARACTERS_OPTION_NAME, DEFAULT_MAXIMUM_CHARS, null, @@ -192,10 +191,10 @@ public class ConsoleTextPane extends JTextPane implements OptionsChangeListener private AttributeSet getAttributeSetByName(String attributeSetName) { if (OUTPUT_ATTRIBUTE_VALUE.equals(attributeSetName)) { - return outputAttributeSet; + return outputAttributes; } else if (ERROR_ATTRIBUTE_VALUE.equals(attributeSetName)) { - return errorAttributeSet; + return errorAttributes; } else { // we found an attribute type that we do not know about @@ -208,23 +207,12 @@ public class ConsoleTextPane extends JTextPane implements OptionsChangeListener } private void createAttributes(Font font) { - outputAttributeSet = new SimpleAttributeSet(); - outputAttributeSet.addAttribute(CUSTOM_ATTRIBUTE_KEY, OUTPUT_ATTRIBUTE_VALUE); - outputAttributeSet.addAttribute(StyleConstants.FontFamily, font.getFamily()); - outputAttributeSet.addAttribute(StyleConstants.FontSize, font.getSize()); - outputAttributeSet.addAttribute(StyleConstants.Italic, font.isItalic()); - outputAttributeSet.addAttribute(StyleConstants.Bold, font.isBold()); - outputAttributeSet.addAttribute(StyleConstants.Foreground, - new GColor("color.fg.consoletextpane")); - errorAttributeSet = new SimpleAttributeSet(); - errorAttributeSet.addAttribute(CUSTOM_ATTRIBUTE_KEY, ERROR_ATTRIBUTE_VALUE); - errorAttributeSet.addAttribute(StyleConstants.FontFamily, font.getFamily()); - errorAttributeSet.addAttribute(StyleConstants.FontSize, font.getSize()); - errorAttributeSet.addAttribute(StyleConstants.Italic, font.isItalic()); - errorAttributeSet.addAttribute(StyleConstants.Bold, font.isBold()); - errorAttributeSet.addAttribute(StyleConstants.Foreground, - new GColor("color.fg.error.consoletextpane")); + outputAttributes = new GAttributes(font, new GColor("color.fg.consoletextpane")); + outputAttributes.addAttribute(CUSTOM_ATTRIBUTE_KEY, OUTPUT_ATTRIBUTE_VALUE); + + errorAttributes = new GAttributes(font, new GColor("color.fg.error.consoletextpane")); + errorAttributes.addAttribute(CUSTOM_ATTRIBUTE_KEY, ERROR_ATTRIBUTE_VALUE); } private void doUpdate() { @@ -316,7 +304,7 @@ public class ConsoleTextPane extends JTextPane implements OptionsChangeListener } AttributeSet getAttributes() { - return outputAttributeSet; + return outputAttributes; } } @@ -327,7 +315,7 @@ public class ConsoleTextPane extends JTextPane implements OptionsChangeListener @Override AttributeSet getAttributes() { - return errorAttributeSet; + return errorAttributes; } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/InfoPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/InfoPanel.java index 63356c6165..0578913623 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/InfoPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/InfoPanel.java @@ -29,6 +29,7 @@ import docking.widgets.*; import docking.widgets.label.*; import generic.theme.GColor; import generic.theme.GThemeDefaults.Colors.Palette; +import generic.theme.Gui; import generic.util.WindowUtilities; import ghidra.framework.Application; import ghidra.framework.ApplicationProperties; @@ -44,16 +45,19 @@ class InfoPanel extends JPanel { private final static int MARGIN = 10; + private final static String SPLASH_FILENAME = "splash.txt"; + private final static String CLOUD_REV_FILENAME = "images/cloudbarReversed.jpg"; + private final static String GHIDRA_FILENAME = "images/GHIDRA_Splash.png"; + private final static String CLOUD_FILENAME = "images/cloudbar.jpg"; + + private static final String FONT_ID = "font.splash.infopanel"; + private String version; private String marking; private String distributionInfo; private Color bgColor; // background color for all panels private int imageWidth; - private final static String SPLASH_FILENAME = "splash.txt"; - private final static String CLOUD_REV_FILENAME = "images/cloudbarReversed.jpg"; - private final static String GHIDRA_FILENAME = "images/GHIDRA_Splash.png"; - private final static String CLOUD_FILENAME = "images/cloudbar.jpg"; InfoPanel() { getAboutInfo(); @@ -170,9 +174,7 @@ class InfoPanel extends JPanel { private Component buildVersionLabel() { MultiLineLabel versionLabel = new MultiLineLabel(version, 0, 3, MultiLineLabel.CENTER); - Font font = versionLabel.getFont(); - font = font.deriveFont(14f).deriveFont(Font.BOLD); - versionLabel.setFont(font); + Gui.registerFont(versionLabel, FONT_ID); versionLabel.setForeground(new GColor("color.fg.infopanel.version")); return versionLabel; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterDialog.java index 120b80228e..07fc5ba591 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterDialog.java @@ -38,6 +38,7 @@ import docking.widgets.dialogs.MultiLineMessageDialog; import docking.widgets.label.GLabel; import docking.widgets.list.GListCellRenderer; import generic.theme.GIcon; +import generic.theme.Gui; import ghidra.app.services.ProgramManager; import ghidra.app.util.*; import ghidra.app.util.bin.ByteProvider; @@ -240,8 +241,7 @@ public class ImporterDialog extends DialogComponentProvider { validateFormInput(); }); - Font font = languageButton.getFont(); - languageButton.setFont(font.deriveFont(Font.BOLD)); + Gui.registerFont(languageButton, Font.BOLD); JPanel panel = new JPanel(new BorderLayout()); panel.add(languageTextField, BorderLayout.CENTER); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/NewLanguagePanel.java b/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/NewLanguagePanel.java index 2322163d2d..0a9f2d2b2b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/NewLanguagePanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/NewLanguagePanel.java @@ -26,6 +26,7 @@ import javax.swing.border.Border; import docking.widgets.checkbox.GCheckBox; import docking.widgets.label.GDLabel; import generic.theme.GThemeDefaults.Colors.Messages; +import generic.theme.Gui; import ghidra.program.model.lang.*; import ghidra.program.util.DefaultLanguageService; import ghidra.util.table.*; @@ -67,7 +68,7 @@ public class NewLanguagePanel extends JPanel { tableFilterPanel = new GhidraTableFilterPanel<>(table, tableModel); descriptionLabel = new GDLabel(DEFAULT_DESCRIPTION_TEXT); - descriptionLabel.setFont(descriptionLabel.getFont().deriveFont(Font.ITALIC)); + Gui.registerFont(descriptionLabel, Font.ITALIC); recommendedCheckbox = new GCheckBox("Show Only Recommended Language/Compiler Specs"); recommendedCheckbox.addItemListener(e -> { @@ -211,7 +212,6 @@ public class NewLanguagePanel extends JPanel { LanguageCompilerSpecPair selectedLcsPair = getSelectedLcsPair(); if (selectedLcsPair == null) { descriptionLabel.setText(DEFAULT_DESCRIPTION_TEXT); - descriptionLabel.setFont(descriptionLabel.getFont().deriveFont(Font.ITALIC)); } else { try { @@ -220,7 +220,6 @@ public class NewLanguagePanel extends JPanel { catch (LanguageNotFoundException e) { descriptionLabel.setText(""); } - descriptionLabel.setFont(descriptionLabel.getFont().deriveFont(Font.PLAIN)); } // notifyListenersOfValidityChanged(); if (!listeners.isEmpty()) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/util/ProgramDiffDetails.java b/Ghidra/Features/Base/src/main/java/ghidra/program/util/ProgramDiffDetails.java index 23547e268e..489ab24a10 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/program/util/ProgramDiffDetails.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/program/util/ProgramDiffDetails.java @@ -109,7 +109,7 @@ public class ProgramDiffDetails { // FUTURE : Add checks to make sure programs are comparable. // Throw exception if not comparable. initDetails(); - initAttributes(); + textAttrSet = new SimpleAttributeSet(); } private static String getIndentString(int indentCount) { @@ -121,11 +121,6 @@ public class ProgramDiffDetails { return buf.toString(); } - private void initAttributes() { - textAttrSet = new SimpleAttributeSet(); - textAttrSet.addAttribute(StyleConstants.FontSize, 12); - } - /** * Gets a string indicating the types of differences for the code units at the indicated * address. The string contains information from each program where there are differences. diff --git a/Ghidra/Features/Base/src/main/java/ghidra/util/table/field/AddressTableDataTableColumn.java b/Ghidra/Features/Base/src/main/java/ghidra/util/table/field/AddressTableDataTableColumn.java index 5daa606f79..57562cdc0c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/util/table/field/AddressTableDataTableColumn.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/util/table/field/AddressTableDataTableColumn.java @@ -15,8 +15,7 @@ */ package ghidra.util.table.field; -import javax.swing.JTable; -import javax.swing.table.TableModel; +import java.awt.Font; import ghidra.app.plugin.core.disassembler.AddressTable; import ghidra.docking.settings.Settings; @@ -34,9 +33,10 @@ public class AddressTableDataTableColumn private final GColumnRenderer monospacedRenderer = new AbstractGColumnRenderer() { + @Override - protected void configureFont(JTable table, TableModel model, int column) { - setFont(getFixedWidthFont()); + protected Font getDefaultFont() { + return fixedWidthFont; } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/util/table/field/MonospacedByteRenderer.java b/Ghidra/Features/Base/src/main/java/ghidra/util/table/field/MonospacedByteRenderer.java index 92299dd144..23767c0ecf 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/util/table/field/MonospacedByteRenderer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/util/table/field/MonospacedByteRenderer.java @@ -16,10 +16,9 @@ package ghidra.util.table.field; import java.awt.Component; +import java.awt.Font; import javax.swing.JLabel; -import javax.swing.JTable; -import javax.swing.table.TableModel; import docking.widgets.table.GTableCellRenderingData; import ghidra.docking.settings.FormatSettingsDefinition; @@ -29,14 +28,15 @@ import ghidra.util.StringFormat; import ghidra.util.table.column.AbstractGColumnRenderer; public class MonospacedByteRenderer extends AbstractGColumnRenderer { + @Override - protected void configureFont(JTable table, TableModel model, int column) { - setFont(getFixedWidthFont()); + protected Font getDefaultFont() { + return fixedWidthFont; } private String formatBytes(Byte[] bytes, Settings settings) { - boolean bigEndian = (EndianSettingsDefinition.DEF - .getChoice(settings) != EndianSettingsDefinition.LITTLE); + boolean bigEndian = + (EndianSettingsDefinition.DEF.getChoice(settings) != EndianSettingsDefinition.LITTLE); int startIx = 0; int endIx = bytes.length; diff --git a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerComponentProvider.java b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerComponentProvider.java index 33175e0944..c7aff4649b 100644 --- a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerComponentProvider.java +++ b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerComponentProvider.java @@ -34,7 +34,8 @@ import ghidra.app.util.viewer.listingpanel.AddressSetDisplayListener; import ghidra.framework.options.*; import ghidra.framework.plugintool.ComponentProviderAdapter; import ghidra.framework.plugintool.PluginTool; -import ghidra.util.*; +import ghidra.util.HelpLocation; +import ghidra.util.Msg; import ghidra.util.classfinder.ClassSearcher; import ghidra.util.task.SwingUpdateManager; @@ -60,13 +61,13 @@ public abstract class ByteViewerComponentProvider extends ComponentProviderAdapt //@formatter:off static final String FG = "byteviewer.color.fg"; static final String CURSOR = "byteviewer.color.cursor"; - - static final GColor SEPARATOR_COLOR = new GColor("color.fg.byteviewer.separator"); + + static final GColor SEPARATOR_COLOR = new GColor("color.fg.byteviewer.separator"); static final GColor CHANGED_VALUE_COLOR = new GColor("color.fg.byteviewer.changed"); static final GColor CURSOR_ACTIVE_COLOR = new GColor("color.cursor.byteviewer.focused.active"); static final GColor CURSOR_NON_ACTIVE_COLOR = new GColor("color.cursor.byteviewer.focused.not.active"); static final GColor CURSOR_NOT_FOCUSED_COLOR = new GColor("color.cursor.byteviewer.unfocused"); - + static final GColor CURRENT_LINE_COLOR = GhidraOptions.DEFAULT_CURSOR_LINE_COLOR; //@formatter:on @@ -162,7 +163,7 @@ public abstract class ByteViewerComponentProvider extends ComponentProviderAdapt /** * Notification that an option changed. - * + * * @param options options object containing the property that changed * @param optionName name of option that changed * @param oldValue old value of the option @@ -173,7 +174,7 @@ public abstract class ByteViewerComponentProvider extends ComponentProviderAdapt Object newValue) { if (options.getName().equals("ByteViewer")) { if (optionName.equals(OPTION_FONT)) { - setFont(SystemUtilities.adjustForFontSizeOverride((Font) newValue)); + setFont((Font) newValue); } } else if (options.getName().equals(CATEGORY_BROWSER_FIELDS)) { @@ -460,7 +461,7 @@ public abstract class ByteViewerComponentProvider extends ComponentProviderAdapt /** * Set the status info on the tool. - * + * * @param message non-html text to display */ void setStatusMessage(String message) { @@ -505,7 +506,7 @@ public abstract class ByteViewerComponentProvider extends ComponentProviderAdapt /** * Add the {@link AddressSetDisplayListener} to the byte viewer panel - * + * * @param listener the listener to add */ public void addDisplayListener(AddressSetDisplayListener listener) { @@ -514,7 +515,7 @@ public abstract class ByteViewerComponentProvider extends ComponentProviderAdapt /** * Remove the {@link AddressSetDisplayListener} from the byte viewer panel - * + * * @param listener the listener to remove */ public void removeDisplayListener(AddressSetDisplayListener listener) { diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/ListingGraphComponentPanel.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/ListingGraphComponentPanel.java index 7d0bd9a296..3e1988f215 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/ListingGraphComponentPanel.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/graph/vertex/ListingGraphComponentPanel.java @@ -39,8 +39,7 @@ import docking.widgets.fieldpanel.Layout; import docking.widgets.fieldpanel.field.Field; import docking.widgets.fieldpanel.support.BackgroundColorModel; import docking.widgets.label.GDLabel; -import generic.theme.GColor; -import generic.theme.GIcon; +import generic.theme.*; import generic.theme.GThemeDefaults.Colors; import generic.theme.GThemeDefaults.Colors.Tooltips; import ghidra.app.plugin.core.codebrowser.MarkerServiceBackgroundColorModel; @@ -245,8 +244,7 @@ public class ListingGraphComponentPanel extends AbstractGraphComponentPanel { tooltipTitleLabel.setHorizontalAlignment(SwingConstants.LEADING); tooltipTitleLabel.setBackground(Tooltips.BACKGROUND); tooltipTitleLabel.setOpaque(true); - Font labelFont = tooltipTitleLabel.getFont(); - tooltipTitleLabel.setFont(labelFont.deriveFont(Font.BOLD)); + Gui.registerFont(tooltipTitleLabel, Font.BOLD); JPanel headerPanel = new JPanel(new BorderLayout()); headerPanel.add(tooltipTitleLabel); diff --git a/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/debug/FidSearchResultFrame.java b/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/debug/FidSearchResultFrame.java index 113fda52dc..e45c729fe4 100644 --- a/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/debug/FidSearchResultFrame.java +++ b/Ghidra/Features/FunctionID/src/main/java/ghidra/feature/fid/debug/FidSearchResultFrame.java @@ -15,11 +15,12 @@ */ package ghidra.feature.fid.debug; -import java.awt.BorderLayout; -import java.awt.Dimension; +import java.awt.*; import java.awt.event.*; import java.io.IOException; -import java.util.*; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; import javax.swing.*; import javax.swing.table.TableColumn; @@ -63,8 +64,13 @@ public class FidSearchResultFrame extends JFrame implements FidQueryCloseListene } private void buildFrame() { - GTableCellRenderer renderer = new GTableCellRenderer(); - renderer.setFont(renderer.getFixedWidthFont()); + GTableCellRenderer renderer = new GTableCellRenderer() { + @Override + protected Font getDefaultFont() { + return fixedWidthFont; + } + }; + int columnCount = table.getColumnCount(); for (int ii = 0; ii < columnCount; ++ii) { Class columnClass = table.getColumnClass(ii); @@ -314,7 +320,7 @@ public class FidSearchResultFrame extends JFrame implements FidQueryCloseListene } @Override - public void fidQueryClosed(FidQueryService service) { + public void fidQueryClosed(FidQueryService fqs) { dispose(); } } diff --git a/Ghidra/Framework/Docking/data/docking.theme.properties b/Ghidra/Framework/Docking/data/docking.theme.properties index e984f54c65..844505ec28 100644 --- a/Ghidra/Framework/Docking/data/docking.theme.properties +++ b/Ghidra/Framework/Docking/data/docking.theme.properties @@ -133,10 +133,18 @@ icon.task.progress.hourglass.11 = hourglass24_11.png // Fonts -font.splash.header.default = Serif-BOLD-35 -font.splash.status = Serif-BOLD-12 -font.table.header.number = arial-BOLD-12 -font.input.hint = monospaced-PLAIN-10 +font.splash.header.default = serif-bold-35 +font.splash.status = serif-bold-12 + +// default table renderer uses the JLabel font, which is mapped to system.font.control +font.table.base = [font]system.font.control +font.table.header.number = arial-bold-12 + +font.input.hint = monospaced-plain-10 + +font.task.monitor.label.message = sansserif-plain-10 + +font.wizard.border.title = sansserif-plain-10 @@ -144,7 +152,6 @@ font.input.hint = monospaced-PLAIN-10 [Dark Defaults] - color.fg.filterfield = color.palette.darkslategray color.bg.highlight = #703401 // orangish 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 233752f8a2..4fe5ad4b66 100644 --- a/Ghidra/Framework/Docking/src/main/help/help/TOC_Source.xml +++ b/Ghidra/Framework/Docking/src/main/help/help/TOC_Source.xml @@ -59,9 +59,9 @@ - - - + + + diff --git a/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingDeveloperDocs.html b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingDeveloperDocs.html index 0d967d4ccb..047695b974 100644 --- a/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingDeveloperDocs.html +++ b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingDeveloperDocs.html @@ -13,6 +13,14 @@ plugins, actions, scripts, etc., that use colors, fonts, or icons. By following these guidelines, developers can easily make use of Ghidra's theming capabilities.

    +
    +
    +

    TipMost classes referenced in this document + live in the generic.theme package. +

    +
    +
    +

    Theme Resource Types

    When developing application code for Ghidra such as plugins, actions, etc., developers often @@ -122,8 +130,58 @@

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

    Font Usage in Tables, Lists and Custom Painting

    +

    + Ghidra makes great use of tables and to a lesser extent, lists. Both tables and lists + use renderers to paint cell values. +

    +
      +
    • + Java - By default, Java will use the font of the table/list as the font used during rendering. +
    • +
    • + Ghidra Tables - Ghidra does not use the table's font for rendering by default. Instead, + the renderer is initialized with the fonts used by JLabel, with additional + fonts for bold and monospaced text. +
    • +
    • + Ghidra Lists - Ghidra does not currently use custom rendering for lists. Thus, list cell + rendering will make use of the list's font, which is Java's default behavior. +
    • +
    + +

    + We point out this difference between Java and Ghidra here so that developers understand + that changing fonts used for tables differs from Java. Specifically, calling +

    +
    +
    +
    +     table.setFont(newFont);
    +
    +
    +

    + will not affect the font used when rendering the table. To programmatically change the + fonts used for tables, you can set the font directly on each cell renderer. As with a + any custom fonts used, be sure to define theme properties file and register then with the + Gui class as outlined above. +

    +

    + The fonts used for any painting operations, including table and list cell rendering, as well + as any code that overrides paint will work correctly within the theming + environment as long as the fonts are derived from the default Look and Feel values or are + obtained from the Gui class. In other words, as long as the + fonts used in custom painting are not hard-coded, any changes to the fonts via the theming + API will appear on the next call to paint the UI. +

    + + diff --git a/Ghidra/Framework/Docking/src/main/java/docking/actions/KeyEntryDialog.java b/Ghidra/Framework/Docking/src/main/java/docking/actions/KeyEntryDialog.java index 0f72911e2d..e3323cc881 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/actions/KeyEntryDialog.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/actions/KeyEntryDialog.java @@ -26,7 +26,9 @@ import docking.action.DockingActionIf; import docking.action.KeyBindingData; import docking.tool.ToolConstants; import docking.widgets.label.GIconLabel; +import generic.theme.GAttributes; import generic.theme.GThemeDefaults.Colors.Messages; +import generic.theme.Gui; import ghidra.util.HelpLocation; import resources.Icons; @@ -43,7 +45,8 @@ public class KeyEntryDialog extends DialogComponentProvider { private KeyEntryTextField keyEntryField; private JTextPane collisionPane; private StyledDocument doc; - private SimpleAttributeSet textAttrSet; + + private SimpleAttributeSet textAttrs; private Color bgColor; public KeyEntryDialog(Tool tool, DockingActionIf action) { @@ -172,10 +175,8 @@ public class KeyEntryDialog extends DialogComponentProvider { } private void setUpAttributes() { - textAttrSet = new SimpleAttributeSet(); - textAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); - textAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11)); - textAttrSet.addAttribute(StyleConstants.Foreground, Messages.NORMAL); + Font font = Gui.getFont("font.standard"); + textAttrs = new GAttributes(font, Messages.NORMAL); } private void updateCollisionPane(KeyStroke ks) { @@ -194,7 +195,7 @@ public class KeyEntryDialog extends DialogComponentProvider { String ksName = KeyBindingUtils.parseKeyStroke(ks); String text = keyBindings.getActionsForKeyStrokeText(ksName); try { - doc.insertString(0, text, textAttrSet); + doc.insertString(0, text, textAttrs); collisionPane.setCaretPosition(0); } catch (BadLocationException e) { diff --git a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/FontPropertyEditor.java b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/FontPropertyEditor.java index 3af96b8769..6fb04af51b 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/FontPropertyEditor.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/FontPropertyEditor.java @@ -26,6 +26,7 @@ import javax.swing.*; import docking.widgets.combobox.GComboBox; import docking.widgets.label.GDLabel; +import generic.theme.Gui; import ghidra.util.Swing; /** @@ -133,7 +134,7 @@ public class FontPropertyEditor extends PropertyEditorSupport { JPanel panel = new JPanel(new GridLayout(2, 1)); GDLabel styleLabel = new GDLabel("Styles"); - styleLabel.setFont(getFont().deriveFont(1)); + Gui.registerFont(styleLabel, Font.BOLD); styleLabel.setHorizontalAlignment(SwingConstants.CENTER); panel.add(styleLabel); @@ -150,7 +151,7 @@ public class FontPropertyEditor extends PropertyEditorSupport { JPanel panel = new JPanel(new GridLayout(2, 1)); GDLabel sizeLabel = new GDLabel("Sizes"); - sizeLabel.setFont(getFont().deriveFont(1)); + Gui.registerFont(sizeLabel, Font.BOLD); sizeLabel.setHorizontalAlignment(SwingConstants.CENTER); panel.add(sizeLabel); @@ -168,7 +169,7 @@ public class FontPropertyEditor extends PropertyEditorSupport { JPanel panel = new JPanel(new GridLayout(2, 1)); GDLabel fontLabel = new GDLabel("Fonts"); - fontLabel.setFont(getFont().deriveFont(1)); + Gui.registerFont(fontLabel, Font.BOLD); fontLabel.setHorizontalAlignment(SwingConstants.CENTER); panel.add(fontLabel); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/AbstractGCellRenderer.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/AbstractGCellRenderer.java index 9fcef6dc82..e04d1b72a0 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/AbstractGCellRenderer.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/AbstractGCellRenderer.java @@ -25,22 +25,32 @@ import javax.swing.plaf.basic.BasicHTML; import javax.swing.table.DefaultTableCellRenderer; import docking.widgets.label.GDHtmlLabel; -import generic.theme.GColor; -import generic.theme.GColorUIResource; +import generic.theme.*; import generic.theme.GThemeDefaults.Colors.Palette; import generic.theme.GThemeDefaults.Colors.Tables; +import ghidra.util.Msg; +import util.CollectionUtils; +import utilities.util.reflection.ReflectionUtilities; /** * A common base class for list and table renderer objects, unifying the Ghidra look and feel. *

    - * It allows (but default-disables) HTML content, automatically paints alternating row - * background colors, and highlights the drop target in a drag-n-drop operation. - * + * It allows (but default-disables) HTML content, automatically paints alternating row background + * colors, and highlights the drop target in a drag-n-drop operation. + *

    + * The preferred method to change the font used by this renderer is {@link #setBaseFontId(String)}. + * If you would like this renderer to use a monospaced font, then, as an alternative to creating a + * font ID, you can instead override {@link #getDefaultFont()} to return this + * class's {@link #fixedWidthFont}. Also, the fixed width font of this class is based on the + * default font set when calling {@link #setBaseFontId(String)}, so it stays up-to-date with theme + * changes. */ public abstract class AbstractGCellRenderer extends GDHtmlLabel { private static final Color BACKGROUND_COLOR = new GColor("color.bg.table.row"); private static final Color ALT_BACKGROUND_COLOR = new GColor("color.bg.table.row.alt"); + private static final String BASE_FONT_ID = "font.table.base"; + /** Allows the user to disable alternating row colors on JLists and JTables */ private static final String DISABLE_ALTERNATING_ROW_COLORS_PROPERTY = "disable.alternating.row.colors"; @@ -61,6 +71,9 @@ public abstract class AbstractGCellRenderer extends GDHtmlLabel { private boolean instanceAlternateRowColors = true; public AbstractGCellRenderer() { + + setBaseFontId(BASE_FONT_ID); + noFocusBorder = BorderFactory.createEmptyBorder(0, 5, 0, 5); Border innerBorder = BorderFactory.createEmptyBorder(0, 4, 0, 4); Border outerBorder = BorderFactory.createLineBorder(Palette.YELLOW, 1); @@ -114,34 +127,48 @@ public abstract class AbstractGCellRenderer extends GDHtmlLabel { return getBackgroundColorForRow(row); } + /** + * Sets this renderer's theme font id. This will be used to load the base font and to create + * the derived fonts, such as bold and fixed width. + * @param fontId the font id + * @see Gui#registerFont(Component, String) + */ + public void setBaseFontId(String fontId) { + Font f = Gui.getFont(fontId); + defaultFont = f; + fixedWidthFont = new Font("monospaced", f.getStyle(), f.getSize()); + boldFont = f.deriveFont(Font.BOLD); + + Gui.registerFont(this, fontId); + } + @Override public void setFont(Font f) { super.setFont(f); - defaultFont = f; - fixedWidthFont = new Font("monospaced", defaultFont.getStyle(), defaultFont.getSize()); - boldFont = f.deriveFont(Font.BOLD); - } - protected void superSetFont(Font font) { - super.setFont(font); - } + // + // Due to the nature of how setFont() is typically used (external client setup vs internal + // rendering), we created setBaseFontId() to allow external clients to set the base font in + // a way that is consistent with theming. Ignore any request to use one of our existing + // fonts, as some clients may do that from the getTableCellRendererComponent() method. + // + if (defaultFont != null && + !CollectionUtils.isOneOf(f, defaultFont, fixedWidthFont, boldFont)) { - // sets the font of this renderer to be bold until the next time that - // getTableCellRenderer() is called, as it resets the font to the default font on each pass - protected void setBold() { - super.setFont(boldFont); + String caller = + ReflectionUtilities.getClassNameOlderThan(getClass().getName(), "generic.theme"); + Msg.debug(this, "Calling setFont() on the renderer is discouraged. " + + "To change the font, call setBaseFontId(). Called from " + caller); + } } /** - * Sets the row where DnD would perform drop operation. - * @param dropRow the drop row + * Sets the font of this renderer to be bold until the next time that getTableCellRenderer() is + * called, as it resets the font to the default font on each pass. + * @see #getDefaultFont() */ - public void setDropRow(int dropRow) { - this.dropRow = dropRow; - } - - protected Border getNoFocusBorder() { - return noFocusBorder; + protected void setBold() { + super.setFont(boldFont); } protected Font getDefaultFont() { @@ -156,6 +183,18 @@ public abstract class AbstractGCellRenderer extends GDHtmlLabel { return boldFont; } + /** + * Sets the row where DnD would perform drop operation. + * @param dropRow the drop row + */ + public void setDropRow(int dropRow) { + this.dropRow = dropRow; + } + + protected Border getNoFocusBorder() { + return noFocusBorder; + } + protected Color getDefaultBackgroundColor() { return BACKGROUND_COLOR; } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/DropDownTextField.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/DropDownTextField.java index 1eb818676e..3a3878ffda 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/DropDownTextField.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/DropDownTextField.java @@ -72,7 +72,8 @@ public class DropDownTextField extends JTextField implements GComponent { new DropDownWindowVisibilityListener<>(); private GDHtmlLabel previewLabel; - protected GList list = new GList<>(); + protected DropDownList list = new DropDownList(); + private WeakSet> choiceListeners = WeakDataStructureFactory.createSingleThreadAccessWeakSet(); private Collection cellEditorListeners = new HashSet<>(); @@ -82,7 +83,6 @@ public class DropDownTextField extends JTextField implements GComponent { private WindowComponentListener parentWindowListener = new WindowComponentListener(); private T selectedValue; - private int cellHeight; private int matchingWindowHeight = MIN_HEIGHT; private Point lastLocation; protected final DropDownTextFieldDataModel dataModel; @@ -278,15 +278,6 @@ public class DropDownTextField extends JTextField implements GComponent { private void initDataList() { - Font font = list.getFont(); - FontMetrics fontMetrics = list.getFontMetrics(font); - int padding = 2; // top and bottom border height - int lineHeight = fontMetrics.getHeight() + padding; - int iconAndPaddingHeight = 16 + padding; - cellHeight = Math.max(lineHeight, iconAndPaddingHeight); - - list.setFixedCellHeight(cellHeight); - list.setFixedCellWidth(MIN_WIDTH - 20); // add some fudge for scrollbars list.setCellRenderer(dataModel.getListRenderer()); list.addKeyListener(keyListener); @@ -654,7 +645,7 @@ public class DropDownTextField extends JTextField implements GComponent { * signalling to use the clicked item. When pressing Enter, they may have been typing and * ignoring the list, so we have to do some validation. */ - @SuppressWarnings("unchecked") // for the cast to T + @SuppressWarnings("unchecked") // the item better be our type private void setTextFromListOnEnterPress() { Object selectedItem = list.getSelectedValue(); if (selectedItem == null) { @@ -747,6 +738,30 @@ public class DropDownTextField extends JTextField implements GComponent { // Inner Classes //================================================================================================= + protected class DropDownList extends GList { + @Override + public void setFont(Font f) { + super.setFont(f); + updateCellDimensions(f); + } + + private void updateCellDimensions(Font font) { + + if (font == null || list == null) { + return; // UI is initializing + } + + FontMetrics fontMetrics = list.getFontMetrics(font); + int padding = 2; // top and bottom border height + int lineHeight = fontMetrics.getHeight() + padding; + int iconAndPaddingHeight = 16 + padding; + int cellHeight = Math.max(lineHeight, iconAndPaddingHeight); + + list.setFixedCellHeight(cellHeight); + list.setFixedCellWidth(MIN_WIDTH - 20); // add some fudge for scrollbars + } + } + private class HideWindowFocusListener extends FocusAdapter { @Override public void focusLost(FocusEvent event) { 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 b7bfb1848e..4b81cd1873 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 @@ -15,7 +15,8 @@ */ package docking.widgets.dialogs; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Dimension; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; @@ -26,6 +27,7 @@ import docking.DockingUtils; import docking.widgets.label.GDLabel; import docking.widgets.label.GLabel; import generic.theme.GThemeDefaults.Colors.Messages; +import generic.theme.Gui; import ghidra.framework.OperatingSystem; import ghidra.framework.Platform; @@ -34,6 +36,8 @@ public class MultiLineInputDialog extends DialogComponentProvider { private static final KeyStroke SUBMIT_KEYSTROKE = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, DockingUtils.CONTROL_KEY_MODIFIER_MASK); + private static final String FONT_ID = "font.input.hint"; + private boolean isCanceled; private JTextArea inputTextArea; @@ -84,10 +88,7 @@ public class MultiLineInputDialog extends DialogComponentProvider { } JLabel hintLabel = new GLabel("(" + metaKeyText + "-Enter to accept)"); hintLabel.setHorizontalAlignment(SwingConstants.CENTER); - Font font = hintLabel.getFont(); - Font smallerFont = font.deriveFont(12F); - Font smallItalicFont = smallerFont.deriveFont(Font.ITALIC); - hintLabel.setFont(smallItalicFont); + Gui.registerFont(hintLabel, FONT_ID); hintLabel.setForeground(Messages.HINT); dataPanel.add(messageLabel, BorderLayout.NORTH); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/filechooser/DirectoryList.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/filechooser/DirectoryList.java index 6748e12e4d..df9251c326 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/filechooser/DirectoryList.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/filechooser/DirectoryList.java @@ -49,39 +49,54 @@ class DirectoryList extends GList implements GhidraFileChooserDirectoryMod /** * Create a new DirectoryList instance. - * + * * @param chooser the {@link GhidraFileChooser} this instance is nested in * @param model the {@link DirectoryListModel} - * @param font the parent component's font, used to calculate row height in the list once */ - DirectoryList(GhidraFileChooser chooser, DirectoryListModel model, Font font) { + DirectoryList(GhidraFileChooser chooser, DirectoryListModel model) { super(model); this.chooser = chooser; this.model = model; - build(font); + build(); } - private void build(Font font) { + @Override + public void setFont(Font font) { + super.setFont(font); + updateCellDimensions(font); + } + + private void updateCellDimensions(Font font) { + + if (font == null) { + return; // UI is being updated + } + + FileListCellRenderer cellRenderer = (FileListCellRenderer) getCellRenderer(); + if (cellRenderer == null) { + return; // initializing + } + + // Enable the list to calculate the width of the cells on its own, but manually specify the + // height to ensure some padding between rows. + // + // Use 1/3 of the line height of the font to ensure visually consistent padding between + // rows. (Historically, 5px was used as the padding between the default 12pt (15px line + // height) rows, so 15px line height/5px padding equals .333 ratio.) + FontMetrics metrics = cellRenderer.getFontMetrics(font); + setFixedCellHeight(Math.max(metrics.getHeight(), DEFAULT_ICON_SIZE) + + Math.max(metrics.getHeight() / 3, MIN_HEIGHT_PADDING)); + setFixedCellWidth(-1); + } + + private void build() { setLayoutOrientation(JList.VERTICAL_WRAP); FileListCellRenderer cellRenderer = new FileListCellRenderer(chooser); setCellRenderer(cellRenderer); - // Enable the list to calculate the width of the cells on its own, but manually - // specify the height to ensure some padding between rows. - // We need the parent component's Font instead of using our - // own #getFont() because we are not a child of the parent yet and - // the font may be set to something other than the default. - // Use 1/3 of the line height of the font to ensure visually consistent - // padding between rows. (historically, 5px was used as the padding - // between the default 12pt (15px lineht) rows, so 15px lineht/5px padding - // equals .333 ratio.) - FontMetrics metrics = cellRenderer.getFontMetrics(font); - setFixedCellHeight( - Math.max(metrics.getHeight(), DEFAULT_ICON_SIZE) + - Math.max(metrics.getHeight() / 3, MIN_HEIGHT_PADDING)); - setFixedCellWidth(-1); + updateCellDimensions(getFont()); addMouseListener(new GMouseListenerAdapter() { @Override diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/filechooser/GhidraFileChooser.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/filechooser/GhidraFileChooser.java index 67c3eeaf81..386a80aacd 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/filechooser/GhidraFileChooser.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/filechooser/GhidraFileChooser.java @@ -558,7 +558,7 @@ public class GhidraFileChooser extends ReusableDialogComponentProvider implement private JScrollPane buildDirectoryList() { directoryListModel = new DirectoryListModel(); - directoryList = new DirectoryList(this, directoryListModel, rootPanel.getFont()); + directoryList = new DirectoryList(this, directoryListModel); directoryList.setName("LIST"); directoryList.setBackground(BACKGROUND_COLOR); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableCellRenderer.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableCellRenderer.java index 400bcf3e7c..01df7ad851 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableCellRenderer.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableCellRenderer.java @@ -51,18 +51,17 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe private static final Color BG_DRAG = new GColor("color.bg.table.row.drag"); /* - * The map uses thread local variables to ensure that rendering and background model + * The map uses thread local variables to ensure that rendering and background model * manipulation are thread safe. */ - private static Map> decimalFormatCache = - new HashMap<>(); + private static Map> decimalFormatCache = new HashMap<>(); static { int n = FloatingPointPrecisionSettingsDefinition.MAX_PRECISION; for (int i = 0; i <= n; i++) { int precision = i; - ThreadLocal localFormatter = ThreadLocal.withInitial( - () -> new DecimalFormat(createDecimalFormat(precision))); + ThreadLocal localFormatter = + ThreadLocal.withInitial(() -> new DecimalFormat(createDecimalFormat(precision))); decimalFormatCache.put(precision, localFormatter); } } @@ -84,7 +83,7 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe /** * Constructs a new GTableCellRenderer using the specified font. - * + * * @param f the font to use when rendering text in the table cells */ public GTableCellRenderer(Font f) { @@ -94,7 +93,7 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe /** * Return the cell renderer text - * + * * @param value Cell object value * @return A string interpretation of value; generated by calling value.toString() */ @@ -149,7 +148,7 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe * Provide basic cell rendering -- setting foreground and background colors, font, text, * alignment, drop color, and border. Additional data that may be of use to the renderer is * passed through the {@link docking.widgets.table.GTableCellRenderingData} object. - * + * * @param data Context data used in the rendering of a data cell. * @return The component used for drawing the table cell. */ @@ -158,7 +157,6 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe Object value = data.getValue(); JTable table = data.getTable(); int row = data.getRowViewIndex(); - int column = data.getColumnViewIndex(); boolean isSelected = data.isSelected(); boolean hasFocus = data.hasFocus(); Settings settings = data.getColumnSettings(); @@ -173,7 +171,7 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe } TableModel model = table.getModel(); - configureFont(table, model, column); + setFont(getDefaultFont()); if (isSelected) { setForeground(table.getSelectionForeground()); @@ -199,8 +197,14 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe setForeground(table.getForeground()); } - protected void configureFont(JTable table, TableModel model, int column) { - setFont(defaultFont); + /** + * Override to change the font that will be used each time the renderer is initialized inside + * of {@link #getTableCellRendererComponent(GTableCellRenderingData)} + * @return the font + */ + @Override + protected Font getDefaultFont() { + return defaultFont; } protected int getRadix(Settings settings) { @@ -217,7 +221,7 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe /** * Format a Number per the Settings parameters. - * + * * @param value the number to format * @param settings settings controlling the display of the Number parameter * @return a formatted representation of the Number value diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/textfield/HintTextField.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/textfield/HintTextField.java index e2a29ed68e..1efc6e0371 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/textfield/HintTextField.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/textfield/HintTextField.java @@ -67,7 +67,7 @@ public class HintTextField extends JTextField { /** * Constructor - * + * * @param hint the hint text * @param required true, if the field should be marked as required * @param verifier input verifier, or null if none needed @@ -78,7 +78,6 @@ public class HintTextField extends JTextField { this.verifier = verifier; addListeners(); - setFont(getFont().deriveFont(Font.PLAIN)); validateField(); } @@ -143,7 +142,7 @@ public class HintTextField extends JTextField { /** * Sets whether the field is required or not. If so, it will be rendered * differently to indicate that to the user. - * + * * @param required true if required, false otherwise */ public void setRequired(boolean required) { @@ -161,7 +160,7 @@ public class HintTextField extends JTextField { /** * Returns true if the field contains valid input. - * + * * @return true if valid, false otherwise */ public boolean isFieldValid() { @@ -179,7 +178,7 @@ public class HintTextField extends JTextField { } /** - * Checks the validity of the field and sets the appropriate + * Checks the validity of the field and sets the appropriate * field attributes. */ private void validateField() { diff --git a/Ghidra/Framework/Docking/src/main/java/docking/wizard/WizardManager.java b/Ghidra/Framework/Docking/src/main/java/docking/wizard/WizardManager.java index a80170bd5a..c0267a5b39 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/wizard/WizardManager.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/wizard/WizardManager.java @@ -28,6 +28,7 @@ import docking.ReusableDialogComponentProvider; import docking.widgets.EmptyBorderButton; import docking.widgets.label.GDLabel; import generic.theme.GThemeDefaults.Colors.Messages; +import generic.theme.Gui; import ghidra.util.*; import help.Help; import help.HelpService; @@ -47,6 +48,8 @@ public class WizardManager extends ReusableDialogComponentProvider implements Wi private final static String INIT_TITLE = "<< untitled >>"; + private static final String FONT_ID = "font.wizard.border.title"; + private PanelManager panelMgr; private WizardPanel currWizPanel; private JButton backButton; @@ -91,7 +94,7 @@ public class WizardManager extends ReusableDialogComponentProvider implements Wi } /** - * + * * @see docking.wizard.WizardPanelListener#validityChanged() */ @Override @@ -108,7 +111,7 @@ public class WizardManager extends ReusableDialogComponentProvider implements Wi return getStatusText(); } - /** + /** * @see docking.wizard.WizardPanelListener#setStatusMessage(String) */ @Override @@ -220,8 +223,7 @@ public class WizardManager extends ReusableDialogComponentProvider implements Wi titleLabel = (wizardIcon == null ? new GDLabel(INIT_TITLE) : new GDLabel(INIT_TITLE, wizardIcon, SwingConstants.TRAILING)); - EmptyBorderButton helpButton = - new EmptyBorderButton(Icons.INFO_ICON); + EmptyBorderButton helpButton = new EmptyBorderButton(Icons.INFO_ICON); helpButton.setToolTipText("Help (F1)"); helpButton.addActionListener( e -> DockingWindowManager.getHelpService().showHelp(rootPanel, false, rootPanel)); @@ -438,7 +440,7 @@ if (!visitedMap.containsKey(currWizPanel)) { return; // nothing to do } - // this will have no effect if we are not showing, but the above call will handle that + // this will have no effect if we are not showing, but the above call will handle that // case defaultFocusComponent.requestFocusInWindow(); } @@ -465,14 +467,12 @@ if (!visitedMap.containsKey(currWizPanel)) { if (scrollPane.getVerticalScrollBar().isShowing()) { TitledBorder titledBorder = new TitledBorder(BorderFactory.createEmptyBorder(), "(scroll for more options)"); - - Font font = titledBorder.getTitleFont(); - if (font == null) { - // workaround for bug on Java 7 - font = titleLabel.getFont(); - } - - titledBorder.setTitleFont(font.deriveFont(10f)); + Gui.addThemeListener(e -> { + if (e.isFontChanged(FONT_ID)) { + titledBorder.setTitleFont(Gui.getFont(FONT_ID)); + } + }); + titledBorder.setTitleFont(Gui.getFont(FONT_ID)); titledBorder.setTitleColor(Messages.NORMAL); titledBorder.setTitlePosition(TitledBorder.BOTTOM); titledBorder.setTitleJustification(TitledBorder.TRAILING); diff --git a/Ghidra/Framework/Docking/src/main/java/ghidra/docking/util/LookAndFeelUtils.java b/Ghidra/Framework/Docking/src/main/java/ghidra/docking/util/LookAndFeelUtils.java index 1e9d3a2e9e..410efd1450 100644 --- a/Ghidra/Framework/Docking/src/main/java/ghidra/docking/util/LookAndFeelUtils.java +++ b/Ghidra/Framework/Docking/src/main/java/ghidra/docking/util/LookAndFeelUtils.java @@ -15,20 +15,14 @@ */ package ghidra.docking.util; -import java.awt.Font; import java.awt.Taskbar; -import java.util.Iterator; -import java.util.Map.Entry; -import java.util.Set; -import javax.swing.*; +import javax.swing.LookAndFeel; import javax.swing.plaf.ComponentUI; import docking.framework.ApplicationInformationDisplayFactory; import generic.theme.LafType; import generic.theme.ThemeManager; -import ghidra.framework.preferences.Preferences; -import ghidra.util.SystemUtilities; /** * A utility class to manage LookAndFeel (LaF) settings. @@ -40,38 +34,12 @@ public class LookAndFeelUtils { } /** - * Loads settings from {@link Preferences}. + * This method does nothing. This is not handled by the theming system in the look and feel + * manager. */ + @Deprecated(since = "11.1", forRemoval = true) public static void installGlobalOverrides() { - // - // Users can change this via the SystemUtilities.FONT_SIZE_OVERRIDE_PROPERTY_NAME - // system property. - // - Integer fontOverride = SystemUtilities.getFontSizeOverrideValue(); - if (fontOverride != null) { - setGlobalFontSizeOverride(fontOverride); - } - } - - /** Allows you to globally set the font size (don't use this method!) */ - private static void setGlobalFontSizeOverride(int fontSize) { - UIDefaults defaults = UIManager.getDefaults(); - - Set> set = defaults.entrySet(); - Iterator> iterator = set.iterator(); - while (iterator.hasNext()) { - Entry entry = iterator.next(); - Object key = entry.getKey(); - - if (key.toString().toLowerCase().indexOf("font") != -1) { - Font currentFont = defaults.getFont(key); - if (currentFont != null) { - Font newFont = currentFont.deriveFont((float) fontSize); - UIManager.put(key, newFont); - } - } - } } public static void performPlatformSpecificFixups() { diff --git a/Ghidra/Framework/Docking/src/main/java/ghidra/util/task/TaskMonitorComponent.java b/Ghidra/Framework/Docking/src/main/java/ghidra/util/task/TaskMonitorComponent.java index 5a2de51f17..acc4b9b28b 100644 --- a/Ghidra/Framework/Docking/src/main/java/ghidra/util/task/TaskMonitorComponent.java +++ b/Ghidra/Framework/Docking/src/main/java/ghidra/util/task/TaskMonitorComponent.java @@ -28,6 +28,7 @@ import org.apache.commons.lang3.StringUtils; import docking.widgets.EmptyBorderButton; import docking.widgets.OptionDialog; import docking.widgets.label.GDHtmlLabel; +import generic.theme.Gui; import ghidra.util.Swing; import ghidra.util.datastruct.WeakDataStructureFactory; import ghidra.util.datastruct.WeakSet; @@ -43,6 +44,8 @@ import resources.Icons; */ public class TaskMonitorComponent extends JPanel implements TaskMonitor { + private static final String MESSAGE_FONT_ID = "font.task.monitor.label.message"; + private WeakSet listeners = WeakDataStructureFactory.createCopyOnReadWeakSet(); @@ -458,7 +461,7 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor { // don't care } }; - messageLabel.setFont(messageLabel.getFont().deriveFont((float) 10.0)); + Gui.registerFont(messageLabel, MESSAGE_FONT_ID); Dimension d = messageLabel.getPreferredSize(); d.width = 180; messageLabel.setPreferredSize(d); diff --git a/Ghidra/Framework/Generic/src/test/java/utilities/util/reflection/ReflectionUtilitiesTest.java b/Ghidra/Framework/Generic/src/test/java/utilities/util/reflection/ReflectionUtilitiesTest.java index 581b4374f3..74751aa026 100644 --- a/Ghidra/Framework/Generic/src/test/java/utilities/util/reflection/ReflectionUtilitiesTest.java +++ b/Ghidra/Framework/Generic/src/test/java/utilities/util/reflection/ReflectionUtilitiesTest.java @@ -35,7 +35,7 @@ public class ReflectionUtilitiesTest { @Test public void testGetClassNameAfter_NoClasses() { - String caller = ReflectionUtilities.getClassNameOlderThan(); + String caller = ReflectionUtilities.getClassNameOlderThan(new String[0]); assertThat(caller, is(equalTo(ReflectionUtilitiesTest.class.getName()))); } diff --git a/Ghidra/Framework/Graph/data/graph.theme.properties b/Ghidra/Framework/Graph/data/graph.theme.properties index 8767f993f6..817ac58291 100644 --- a/Ghidra/Framework/Graph/data/graph.theme.properties +++ b/Ghidra/Framework/Graph/data/graph.theme.properties @@ -23,12 +23,13 @@ color.visualgraph.view.satellite.edge.focused = color.palette.green color.visualgraph.view.satellite.edge.selected = color.palette.lime color.visualgraph.view.satellite.edge.hovered = color.palette.lime - color.graphdisplay.vertex.default = color.palette.green color.graphdisplay.edge.default = color.palette.green color.graphdisplay.vertex.selected = color.palette.blue color.graphdisplay.edge.selected = color.palette.blue +font.visualgraph.view.label.message = SansSerif-PLAIN-22 // bigger for legibility in the graph + icon.graph.satellite = network-wireless-16.png icon.graph.satellite.large = network-wireless.png icon.graph.layout.default = color_swatch.png diff --git a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/VisualGraphView.java b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/VisualGraphView.java index 720fcac7bd..7f8dab9d7f 100644 --- a/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/VisualGraphView.java +++ b/Ghidra/Framework/Graph/src/main/java/ghidra/graph/viewer/VisualGraphView.java @@ -27,6 +27,7 @@ import docking.widgets.label.GDLabel; import edu.uci.ics.jung.visualization.RenderContext; import edu.uci.ics.jung.visualization.VisualizationViewer; import edu.uci.ics.jung.visualization.control.ScalingControl; +import generic.theme.Gui; import ghidra.graph.VisualGraph; import ghidra.graph.viewer.event.mouse.VertexTooltipProvider; import ghidra.graph.viewer.event.mouse.VisualGraphMousePlugin; @@ -38,18 +39,18 @@ import ghidra.graph.viewer.vertex.VertexFocusListener; * A view object, where 'view' is used in the sense of the Model-View-Controller (MVC) pattern. * This class will contain all UI widgets need to display and interact with a graph. * - *

    Implementation Note: + *

    Implementation Note: *

      - *
    1. The graph of this component can be null, changing to non-null values over the - * lifetime of this view. This allows this view to be installed in a UI component, with the - * contents changing as needed. + *
    2. The graph of this component can be null, changing to non-null values over the + * lifetime of this view. This allows this view to be installed in a UI component, with the + * contents changing as needed. *
    3. *
    4. * When the graph is {@link #setGraph(VisualGraph) set}, the view portion of the class is * recreated. *
    5. *
    6. - * At any given point in time there may not be a {@link #graphComponent}. This means that + * At any given point in time there may not be a {@link #graphComponent}. This means that * this class must maintain settings state that it will apply when the component is created. * This state is atypical and makes this class a bit harder to understand. *
    7. @@ -60,14 +61,16 @@ import ghidra.graph.viewer.vertex.VertexFocusListener; * @param the graph type */ //@formatter:off -public class VisualGraphView, +public class VisualGraphView, G extends VisualGraph> { -//@formatter:on +//@formatter:on private static final float ZOOM_OUT_AMOUNT = .9f; private static final float ZOOM_IN_AMOUNT = 1.1f; + private static final String MESSAGE_FONT_ID = "font.visualgraph.view.label.message"; + private JPanel viewPanel; private JPanel viewContentPanel; @@ -76,7 +79,7 @@ public class VisualGraphView clientSatelliteListener = Optional.empty(); - // this internal listener is the way we manage keeping our state in sync with the + // this internal listener is the way we manage keeping our state in sync with the // graph component, as well as how we notify the client listener private GraphSatelliteListener internalSatelliteListener = (docked, visible) -> { @@ -190,10 +193,10 @@ public class VisualGraphView l) { @@ -290,9 +293,9 @@ public class VisualGraphView getPrimaryGraphViewer() { @@ -308,7 +311,7 @@ public class VisualGraphView newPerspective) { @@ -350,8 +353,7 @@ public class VisualGraphView + * Calling this method will trigger a call to {@link JComponent#setFont(Font)}. + * * @param component the component to set/update the font * @param fontId the id of the font to register with the given component */ @@ -153,6 +159,37 @@ public class Gui { themeManager.registerFont(component, fontId); } + /** + * Registers the given component with the given font style. This method allows clients to not + * define a font id in the theme system, but instead to signal that they want the default font + * for the given component, modified with the given style. As the underlying font is changed, + * the client will be updated with that new font with the given style applied. + *

      + * Most clients should not be using this method. Instead, use + * {@link #registerFont(JComponent, int)}. + *

      + * The downside of using this method is that the end user cannot modify the style of the font. + * By using the standard theming mechanism for registering fonts, the end user has full control. + * + * @param component the component to set/update the font + * @param fontStyle the font style, one of Font.BOLD, Font.ITALIC, + */ + public static void registerFont(JComponent component, int fontStyle) { + + if (fontStyle == Font.PLAIN) { + Msg.warn(Gui.class, + "Gui.registerFont(Component, int) may only be used for a non-plain font style. " + + "Use registerFont(Component, String) instead."); + return; + } + + String id = component.getUIClassID(); // e.g., ButtonUI + String name = id.substring(0, id.length() - 2); // strip off "UI" + String fontId = FontValue.LAF_ID_PREFIX + name + FONT_SUFFIX; // e.g., laf.font.Button.font + + themeManager.registerFont(component, fontId, fontStyle); + } + /** * Returns true if the active theme is using dark defaults * @return true if the active theme is using dark defaults diff --git a/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeManager.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeManager.java index 90cad746d6..990bea4df1 100644 --- a/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeManager.java +++ b/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeManager.java @@ -575,6 +575,21 @@ public abstract class ThemeManager { // do nothing } + /** + * Binds the component to the font identified by the given font id. Whenever the font for + * the font id changes, the component will updated with the new font. + *

      + * This method is fairly niche and should not be called by most clients. Instead, call + * {@link #registerFont(Component, String)}. + * + * @param component the component to set/update the font + * @param fontId the id of the font to register with the given component + * @param fontStyle the font style + */ + public void registerFont(Component component, String fontId, int fontStyle) { + // do nothing + } + /** * Returns true if the current theme use dark default values. * @return true if the current theme use dark default values. diff --git a/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/ComponentFontRegistry.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/ComponentFontRegistry.java index 13ffc5b842..96caf98907 100644 --- a/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/ComponentFontRegistry.java +++ b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/ComponentFontRegistry.java @@ -28,7 +28,8 @@ import ghidra.util.datastruct.WeakSet; * for the font id, this class will update the component's font to the new value. */ public class ComponentFontRegistry { - private WeakSet components = WeakDataStructureFactory.createCopyOnReadWeakSet(); + private WeakSet components = + WeakDataStructureFactory.createCopyOnReadWeakSet(); private String fontId; /** @@ -45,8 +46,18 @@ public class ComponentFontRegistry { * @param component the component to add */ public void addComponent(Component component) { - component.setFont(Gui.getFont(fontId)); - components.add(component); + addComponent(component, Font.PLAIN); + } + + /** + * Allows clients to update the default font being used for a component to use the given style. + * @param component the component + * @param fontStyle the font style (e.g., {@link Font#BOLD}) + */ + public void addComponent(Component component, int fontStyle) { + StyledComponent sc = new StyledComponent(component, fontStyle); + sc.setFont(Gui.getFont(fontId)); + components.add(sc); } /** @@ -54,10 +65,26 @@ public class ComponentFontRegistry { */ public void updateComponentFonts() { Font font = Gui.getFont(fontId); - for (Component component : components) { + for (StyledComponent c : components) { + c.setFont(font); + } + } + + private record StyledComponent(Component component, int fontStyle) { + + void setFont(Font font) { Font existingFont = component.getFont(); - if (!Objects.equals(existingFont, font)) { - component.setFont(font); + Font styledFont = font; + int style = fontStyle(); + if (style != Font.PLAIN) { + // Only style the font when it is not plain. Doing this means that clients cannot + // override a non-plain font to be plain. If clients need that behavior, they must + // create their own custom font id and register their component with Gui. + styledFont = font.deriveFont(style); + } + + if (!Objects.equals(existingFont, styledFont)) { + component.setFont(styledFont); } } } diff --git a/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/LookAndFeelManager.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/LookAndFeelManager.java index 04d5b72762..65a2671e5e 100644 --- a/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/LookAndFeelManager.java +++ b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/LookAndFeelManager.java @@ -30,6 +30,7 @@ import generic.theme.*; import generic.util.action.*; import ghidra.util.Msg; import ghidra.util.SystemUtilities; +import utilities.util.reflection.ReflectionUtilities; /** * Manages installing and updating a {@link LookAndFeel} @@ -38,6 +39,7 @@ public abstract class LookAndFeelManager { private LafType laf; private Map fontRegistryMap = new HashMap<>(); + private Map componentToIdMap = new WeakHashMap<>(); protected ApplicationThemeManager themeManager; protected Map normalizedIdToLafIdMap; @@ -158,7 +160,7 @@ public abstract class LookAndFeelManager { * Called when one or more fonts have changed. *

      * This will update the Java {@link UIManager} and trigger a reload of the UIs. - * + * * @param changedFontIds the set of Java Font ids that are affected by this change; these are * the normalized ids */ @@ -202,12 +204,49 @@ public abstract class LookAndFeelManager { * @param fontId the id of the font to register with the given component */ public void registerFont(Component component, String fontId) { + + checkForAlreadyRegistered(component, fontId); + componentToIdMap.put(component, fontId); + ComponentFontRegistry register = fontRegistryMap.computeIfAbsent(fontId, id -> new ComponentFontRegistry(id)); register.addComponent(component); } + /** + * Binds the component to the font identified by the given font id. Whenever the font for + * the font id changes, the component will be updated with the new font. + *

      + * This method is fairly niche and should not be called by most clients. Instead, call + * {@link #registerFont(Component, String)}. + * + * @param component the component to set/update the font + * @param fontId the id of the font to register with the given component + * @param fontStyle the font style + */ + public void registerFont(Component component, String fontId, int fontStyle) { + + checkForAlreadyRegistered(component, fontId); + componentToIdMap.put(component, fontId); + + ComponentFontRegistry register = + fontRegistryMap.computeIfAbsent(fontId, id -> new ComponentFontRegistry(id)); + + register.addComponent(component, fontStyle); + } + + private void checkForAlreadyRegistered(Component component, String newFontId) { + String existingFontId = componentToIdMap.get(component); + if (existingFontId != null) { + Msg.warn(this, """ + Component has a Font ID registered more than once. \ + Previously registered ID: '%s'. Newly registered ID: '%s'. + """.formatted(existingFontId, newFontId), + ReflectionUtilities.createJavaFilteredThrowable()); + } + } + private Font toUiResource(Font font) { if (!(font instanceof UIResource)) { return new FontUIResource(font); @@ -292,8 +331,7 @@ public abstract class LookAndFeelManager { return false; } - protected void setKeyBinding(String existingKsText, String newKsText, - String[] prefixValues) { + protected void setKeyBinding(String existingKsText, String newKsText, String[] prefixValues) { KeyStroke existingKs = KeyStroke.getKeyStroke(existingKsText); KeyStroke newKs = KeyStroke.getKeyStroke(newKsText); diff --git a/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/UiDefaultsMapper.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/UiDefaultsMapper.java index 8ebd94e3ca..433717b7d7 100644 --- a/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/UiDefaultsMapper.java +++ b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/UiDefaultsMapper.java @@ -153,8 +153,8 @@ public class UiDefaultsMapper { * the user changeable values for affecting the Java LookAndFeel colors, fonts, and icons. *

      * The keys in the returned map have been normalized and all start with 'laf.' - * - * + * + * * @return a map of changeable values that affect java LookAndFeel values */ public GThemeValueMap getNormalizedJavaDefaults() { @@ -184,7 +184,7 @@ public class UiDefaultsMapper { * Returns a mapping of normalized LaF Ids so that when fonts and icons get changed using the * normalized ids that are presented to the user, we know which LaF ids need to be updated in * the UiDefaults so that the LookAndFeel will pick up and use the changes. - * + * * @return a mapping of normalized LaF ids to original LaF ids. */ public Map getNormalizedIdToLafIdMap() { @@ -281,7 +281,7 @@ public class UiDefaultsMapper { /** * This allows clients to hard-code a chosen color for a group - * + * * @param group the system color id to assign the given color * @param color the color to be assigned to the system color id */ @@ -291,7 +291,7 @@ public class UiDefaultsMapper { /** * This allows clients to hard-code a chosen font for a group - * + * * @param group the system font id to assign the given font * @param font the font to be assigned to the system font id */ @@ -693,7 +693,7 @@ public class UiDefaultsMapper { * Groups allow us to use the same group id for many components that by default have the same * value (Color or Font). This grouper allows us to specify the precedence to use when * searching for the best group. - * + * * @param The theme value type (Color or Font) */ private abstract class ValueGrouper { diff --git a/Ghidra/Framework/Gui/src/main/java/ghidra/util/HTMLUtilities.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/HTMLUtilities.java index 9c1044dc10..6c17637dee 100644 --- a/Ghidra/Framework/Gui/src/main/java/ghidra/util/HTMLUtilities.java +++ b/Ghidra/Framework/Gui/src/main/java/ghidra/util/HTMLUtilities.java @@ -22,9 +22,10 @@ import java.util.regex.Pattern; import javax.swing.JLabel; import javax.swing.plaf.basic.BasicHTML; -import javax.swing.text.View; +import javax.swing.text.*; import generic.text.TextLayoutGraphics; +import generic.theme.GAttributes; import ghidra.util.html.HtmlLineSplitter; import utilities.util.reflection.ReflectionUtilities; @@ -343,6 +344,67 @@ public class HTMLUtilities { return buffy.toString(); } + /** + * Escapes and wraps the given text in {@code SPAN} tag with font attributes specified in the + * given attributes. Specifically, these attributes are used: + * + *

        + *
      • {@link StyleConstants#Foreground} - {@link Color} object
      • + *
      • {@link StyleConstants#FontFamily} - font name
      • + *
      • {@link StyleConstants#FontSize} - size in pixels
      • + *
      • {@link StyleConstants#Italic} - true if italic
      • + *
      • {@link StyleConstants#Bold} - true if bold
      • + *
      + *

      + * See {@link GAttributes} for a convenient way to create the correct attributes for a font and + * color. + * + * @param attributes the attributes + * @param text the content to style + * @return the styled content + * @see GAttributes + */ + public static String styleText(SimpleAttributeSet attributes, String text) { + + // StyleConstants.Foreground color: #00FF00; + // StyleConstants.FontFamily font-family: "Tahoma"; + // StyleConstants.FontSize font-size: 40px; + // StyleConstants.Italic font-style: italic; + // StyleConstants.Bold font-weight: bold; + + String family = attributes.getAttribute(StyleConstants.FontFamily).toString(); + String size = attributes.getAttribute(StyleConstants.FontSize).toString(); + String style = "plain"; + String weight = "plain"; + Boolean isItalic = (Boolean) attributes.getAttribute(StyleConstants.Italic); + Boolean isBold = (Boolean) attributes.getAttribute(StyleConstants.Bold); + if (Boolean.TRUE.equals(isItalic)) { + style = "italic"; + } + + if (Boolean.TRUE.equals(isBold)) { + weight = "bold"; + } + + // color is optional and defaults to the containing component's color + String color = ""; + Object colorAttribute = attributes.getAttribute(StyleConstants.Foreground); + if (colorAttribute instanceof Color fgColor) { + String hexColor = HTMLUtilities.toHexString(fgColor); + color = "color: % s;".formatted(hexColor); + } + + String escaped = escapeHTML(text); + + //@formatter:off + return """ + \ + %s\ + + """.formatted(color, family, size, style, weight, escaped); + //@formatter:on + } + /** * Returns the given text wrapped in {@link #LINK_PLACEHOLDER_OPEN} and close tags. * If foo is passed for the HTML text, with a content value of 123456, then @@ -510,7 +572,7 @@ public class HTMLUtilities { /** * See {@link #friendlyEncodeHTML(String)} - * + * * @param text string to be encoded * @param skipLeadingWhitespace true signals to ignore any leading whitespace characters. * This is useful when line wrapping to force wrapped lines to the left @@ -593,8 +655,7 @@ public class HTMLUtilities { * Calling this twice will result in text being double-escaped, which will not display correctly. *

      * See also StringEscapeUtils#escapeHtml3(String) if you need quote-safe html encoding. - *

      - * + * * @param text plain-text that might have some characters that should NOT be interpreted as HTML * @param makeSpacesNonBreaking true to convert spaces into {@value #HTML_SPACE} * @return string with any html characters replaced with equivalents @@ -634,7 +695,7 @@ public class HTMLUtilities { /** * Escapes any HTML special characters in the specified text. - * + * * @param text plain-text that might have some characters that should NOT be interpreted as HTML * @return string with any html characters replaced with equivalents * @see #escapeHTML(String, boolean) @@ -647,7 +708,7 @@ public class HTMLUtilities { * Tests a unicode code point (i.e., 32 bit character) to see if it needs to be escaped before * being added to a HTML document because it is non-printable or a non-standard control * character - * + * * @param codePoint character to test * @return boolean true if character should be escaped */ diff --git a/Ghidra/Framework/Project/data/project.theme.properties b/Ghidra/Framework/Project/data/project.theme.properties index 5705e198e9..1fc29cfa51 100644 --- a/Ghidra/Framework/Project/data/project.theme.properties +++ b/Ghidra/Framework/Project/data/project.theme.properties @@ -84,8 +84,12 @@ icon.plugin.manager.default = plasma.png font.help.about = font.monospaced font.keybindings.status = sansserif-plain-11 font.task.viewer = sansserif-bold-36 -font.user.agreement = sansserif-plain-16 +font.task.progress.label.message = sansserif-plain-12 +font.user.agreement = sansserif-italic-22 +font.panel.details = font.standard +font.panel.details.monospaced = font.monospaced[bold] +font.pluginpanel.name = sansserif-plain-18 diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/UserAgreementDialog.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/UserAgreementDialog.java index 095ca5290c..731ff35b22 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/UserAgreementDialog.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/UserAgreementDialog.java @@ -15,7 +15,8 @@ */ package ghidra.framework.main; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Insets; import java.io.InputStream; import javax.swing.*; @@ -57,11 +58,10 @@ public class UserAgreementDialog extends DialogComponentProvider { } private JComponent buildWorkPanel() { - Font font = Gui.getFont(FONT_ID); JPanel panel = new JPanel(new BorderLayout()); JLabel label = new GDLabel("Ghidra User Agreement", SwingConstants.CENTER); label.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0)); - label.setFont(font.deriveFont(Font.ITALIC, 22f)); + Gui.registerFont(label, FONT_ID); panel.add(label, BorderLayout.NORTH); panel.setBorder(BorderFactory.createEmptyBorder(10, 40, 40, 40)); JEditorPane editorPane = new JEditorPane(); diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ViewProjectAccessPanel.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ViewProjectAccessPanel.java index f565856151..821e50897f 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ViewProjectAccessPanel.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ViewProjectAccessPanel.java @@ -23,6 +23,7 @@ import java.util.List; import javax.swing.*; import docking.widgets.label.GDLabel; +import generic.theme.Gui; import ghidra.framework.client.RepositoryAdapter; import ghidra.framework.plugintool.PluginTool; import ghidra.framework.remote.User; @@ -33,9 +34,9 @@ import ghidra.framework.remote.User; */ public class ViewProjectAccessPanel extends ProjectAccessPanel { - /** + /** * Construct a new panel. - * + * * @param repository handle to the repository adapter * @param tool the plugin tool * @throws IOException if there's an error processing repository information @@ -47,13 +48,13 @@ public class ViewProjectAccessPanel extends ProjectAccessPanel { /** * Constructs a new panel. - * + * * @param knownUsers names of the users that are known to the remote server * @param currentUser the current user * @param allUsers all users known to the repository * @param repositoryName the name of the repository * @param anonymousServerAccessAllowed true if the server allows anonymous access - * @param anonymousAccessEnabled true if the repository allows anonymous access + * @param anonymousAccessEnabled true if the repository allows anonymous access * (ignored if anonymousServerAccessAllowed is false) * @param tool the current tool */ @@ -66,7 +67,7 @@ public class ViewProjectAccessPanel extends ProjectAccessPanel { } /** - * Creates the main gui panel, containing the known users, button, and user access + * Creates the main gui panel, containing the known users, button, and user access * panels. */ @Override @@ -82,9 +83,7 @@ public class ViewProjectAccessPanel extends ProjectAccessPanel { if (anonymousServerAccessAllowed && origAnonymousAccessEnabled) { JLabel anonymousAccessLabel = new GDLabel("Anonymous Read-Only Access Enabled"); anonymousAccessLabel.setBorder(BorderFactory.createEmptyBorder(5, 2, 0, 0)); - Font f = anonymousAccessLabel.getFont().deriveFont(Font.ITALIC); - anonymousAccessLabel.setFont(f); - + Gui.registerFont(anonymousAccessLabel, Font.ITALIC); mainPanel.add(anonymousAccessLabel, BorderLayout.SOUTH); } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/dialog/AbstractDetailsPanel.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/dialog/AbstractDetailsPanel.java index 5179d0bd5f..dd1a901332 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/dialog/AbstractDetailsPanel.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/dialog/AbstractDetailsPanel.java @@ -17,79 +17,57 @@ package ghidra.framework.plugintool.dialog; import static ghidra.util.HTMLUtilities.*; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Dimension; import javax.swing.*; -import javax.swing.text.SimpleAttributeSet; -import javax.swing.text.StyleConstants; import docking.widgets.label.GDHtmlLabel; -import generic.theme.GColor; -import ghidra.util.HTMLUtilities; +import generic.theme.*; /** * Abstract class that defines a panel for displaying name/value pairs with html-formatting. */ public abstract class AbstractDetailsPanel extends JPanel { + protected static final String FONT_DEFAULT = "font.panel.details"; + protected static final String FONT_MONOSPACED = "font.panel.details.monospaced"; + private static final int MIN_WIDTH = 700; protected static final int LEFT_COLUMN_WIDTH = 150; protected static final int RIGHT_MARGIN = 30; // Font attributes for the title of each row. - protected static SimpleAttributeSet titleAttrSet; + protected static GAttributes titleAttrs; protected JLabel textLabel; protected JScrollPane sp; + private ThemeListener themeListener = e -> { + + if (e.isFontChanged(FONT_DEFAULT) || e.isFontChanged(FONT_MONOSPACED)) { + updateFieldAttributes(); + } + }; + + protected AbstractDetailsPanel() { + createFieldAttributes(); + Gui.addThemeListener(themeListener); + } + + private void updateFieldAttributes() { + createFieldAttributes(); + refresh(); + repaint(); + } + /** - * Sets attributes for the different pieces of information being displayed in this + * Sets attributes for the different pieces of information being displayed in this * panel. */ protected abstract void createFieldAttributes(); - /** - * Returns a new {@link SimpleAttributeSet} with all attributes set by the caller. - * - * @param fontFamily the font to use - * @param fontSize the font size - * @param bold if true, render text bold - * @param color the foreground text color - * @return a new attribute set - */ - protected SimpleAttributeSet createAttributeSet(String fontFamily, int fontSize, boolean bold, - Color color) { - - SimpleAttributeSet attrSet = new SimpleAttributeSet(); - attrSet.addAttribute(StyleConstants.FontFamily, fontFamily); - attrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(fontSize)); - attrSet.addAttribute(StyleConstants.Bold, bold); - attrSet.addAttribute(StyleConstants.Foreground, color); - - return attrSet; - } - - /** - * Returns a new {@link SimpleAttributeSet} with the following default attributes set: - *

        - *
      • FontFamily: "Tahoma"
      • - *
      • FontSize: 11
      • - *
      • Bold: True
      • - *
      - * - * @param color the foreground text color - * @return a new attribute set - */ - protected SimpleAttributeSet createAttributeSet(Color color) { - - SimpleAttributeSet attrSet = new SimpleAttributeSet(); - attrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); - attrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11)); - attrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE); - attrSet.addAttribute(StyleConstants.Foreground, color); - - return attrSet; - } + protected abstract void refresh(); /** * Clears the text in the details pane. @@ -127,27 +105,26 @@ public abstract class AbstractDetailsPanel extends JPanel { /** * Inserts an html-formatted string into the given buffer. This is meant to be used * for inserting the name of each row in the description text. - * + * * @param buffer the string buffer to add to * @param rowName the name of the row to add */ protected void insertRowTitle(StringBuilder buffer, String rowName) { buffer.append(""); buffer.append(""); - insertHTMLLine(buffer, rowName + ":", titleAttrSet); + insertHTMLLine(buffer, rowName + ":", titleAttrs); buffer.append(""); } /** * Inserts an html-formatted string into the given buffer. This is meant to be used * for inserting the value of each row in the description text. - * + * * @param buffer the string buffer to add to * @param value the text to add - * @param attributes the structure containing formatting information + * @param attributes the structure containing formatting information */ - protected void insertRowValue(StringBuilder buffer, String value, - SimpleAttributeSet attributes) { + protected void insertRowValue(StringBuilder buffer, String value, GAttributes attributes) { buffer.append(""); insertHTMLLine(buffer, value, attributes); buffer.append(""); @@ -161,33 +138,13 @@ public abstract class AbstractDetailsPanel extends JPanel { * @param string the string to add * @param attributes the formatting instructions */ - protected void insertHTMLString(StringBuilder buffer, String string, - SimpleAttributeSet attributes) { + protected void insertHTMLString(StringBuilder buffer, String string, GAttributes attributes) { if (string == null) { return; } - buffer.append(""); - - Boolean isBold = (Boolean) attributes.getAttribute(StyleConstants.Bold); - isBold = (isBold == null) ? Boolean.FALSE : isBold; - String text = HTMLUtilities.escapeHTML(string); - if (isBold) { - text = HTMLUtilities.bold(text); - } - - buffer.append(text); - - buffer.append(""); + buffer.append(attributes.toStyledHtml(string)); } /** @@ -196,8 +153,7 @@ public abstract class AbstractDetailsPanel extends JPanel { * @param string the string to insert * @param attributes the attributes to apply */ - protected void insertHTMLLine(StringBuilder buffer, String string, - SimpleAttributeSet attributes) { + protected void insertHTMLLine(StringBuilder buffer, String string, GAttributes attributes) { if (string == null) { return; } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/dialog/PluginDetailsPanel.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/dialog/PluginDetailsPanel.java index 22b56f039e..ff21c5e6d7 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/dialog/PluginDetailsPanel.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/dialog/PluginDetailsPanel.java @@ -15,17 +15,16 @@ */ package ghidra.framework.plugintool.dialog; +import java.awt.Font; import java.awt.Point; import java.util.*; import javax.swing.KeyStroke; -import javax.swing.text.SimpleAttributeSet; -import javax.swing.text.StyleConstants; import docking.action.DockingActionIf; import docking.action.MenuData; import docking.actions.KeyBindingUtils; -import generic.theme.GColor; +import generic.theme.*; import ghidra.framework.plugintool.PluginConfigurationModel; import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.util.PluginDescription; @@ -37,29 +36,52 @@ import ghidra.util.HTMLUtilities; */ class PluginDetailsPanel extends AbstractDetailsPanel { - private SimpleAttributeSet nameAttrSet; - private SimpleAttributeSet depNameAttrSet; - private SimpleAttributeSet descrAttrSet; - private SimpleAttributeSet categoriesAttrSet; - private SimpleAttributeSet classAttrSet; - private SimpleAttributeSet locAttrSet; - private SimpleAttributeSet developerAttrSet; - private SimpleAttributeSet dependencyAttrSet; - private SimpleAttributeSet noValueAttrSet; + private static final GColor NO_VALUE_COLOR = new GColor("color.fg.pluginpanel.details.novalue"); + private static final GColor DEPENDENCY_COLOR = + new GColor("color.fg.pluginpanel.details.dependency"); + private static final GColor LOCATION_COLOR = new GColor("color.fg.pluginpanel.details.loc"); + private static final GColor DEVELOPER_COLOR = + new GColor("color.fg.pluginpanel.details.developer"); + private static final GColor CLASS_COLOR = new GColor("color.fg.pluginpanel.details.class"); + private static final GColor CATEGORIES_COLOR = + new GColor("color.fg.pluginpanel.details.category"); + private static final GColor TITLE_COLOR = new GColor("color.fg.pluginpanel.details.title"); + private static final GColor DESCRIPTION_COLOR = + new GColor("color.fg.pluginpanel.details.description"); + private static final GColor NAME_NO_DEPENDENTS_COLOR = + new GColor("color.fg.pluginpanel.details.name.no.dependents"); + private static final GColor NAME_DEPENDENTS_COLOR = + new GColor("color.fg.pluginpanel.details.name.has.dependents"); + + private GAttributes nameAttrs; + private GAttributes dependenciesNameAttrs; + private GAttributes descriptionAttrs; + private GAttributes categoriesAttrs; + private GAttributes classAttrs; + private GAttributes locationAttrs; + private GAttributes developerAttrs; + private GAttributes dependencyAttrs; + private GAttributes noValueAttrs; private final PluginConfigurationModel model; private PluginTool tool; + private PluginDescription currentDescriptor; PluginDetailsPanel(PluginTool tool, PluginConfigurationModel model) { - super(); this.tool = tool; this.model = model; createFieldAttributes(); createMainPanel(); } + @Override + protected void refresh() { + setPluginDescription(currentDescriptor); + } + void setPluginDescription(PluginDescription descriptor) { + this.currentDescriptor = descriptor; textLabel.setText(""); if (descriptor == null) { return; @@ -74,43 +96,43 @@ class PluginDetailsPanel extends AbstractDetailsPanel { insertRowTitle(buffer, "Name"); insertRowValue(buffer, descriptor.getName(), - !dependencies.isEmpty() ? depNameAttrSet : nameAttrSet); + !dependencies.isEmpty() ? dependenciesNameAttrs : nameAttrs); insertRowTitle(buffer, "Description"); - insertRowValue(buffer, descriptor.getDescription(), descrAttrSet); + insertRowValue(buffer, descriptor.getDescription(), descriptionAttrs); insertRowTitle(buffer, "Status"); insertRowValue(buffer, descriptor.getStatus().getDescription(), - (descriptor.getStatus() == PluginStatus.RELEASED) ? titleAttrSet : developerAttrSet); + (descriptor.getStatus() == PluginStatus.RELEASED) ? titleAttrs : developerAttrs); insertRowTitle(buffer, "Package"); - insertRowValue(buffer, descriptor.getPluginPackage().getName(), categoriesAttrSet); + insertRowValue(buffer, descriptor.getPluginPackage().getName(), categoriesAttrs); insertRowTitle(buffer, "Category"); - insertRowValue(buffer, descriptor.getCategory(), categoriesAttrSet); + insertRowValue(buffer, descriptor.getCategory(), categoriesAttrs); insertRowTitle(buffer, "Plugin Class"); - insertRowValue(buffer, descriptor.getPluginClass().getName(), classAttrSet); + insertRowValue(buffer, descriptor.getPluginClass().getName(), classAttrs); insertRowTitle(buffer, "Class Location"); - insertRowValue(buffer, descriptor.getSourceLocation(), locAttrSet); + insertRowValue(buffer, descriptor.getSourceLocation(), locationAttrs); insertRowTitle(buffer, "Used By"); buffer.append(""); if (dependencies.isEmpty()) { - insertHTMLLine(buffer, "None", noValueAttrSet); + insertHTMLLine(buffer, "None", noValueAttrs); } else { for (int i = 0; i < dependencies.size(); i++) { insertHTMLString(buffer, dependencies.get(i).getPluginClass().getName(), - dependencyAttrSet); + dependencyAttrs); if (i < dependencies.size() - 1) { buffer.append(HTMLUtilities.BR); } } - insertHTMLLine(buffer, "", titleAttrSet); // add a newline + insertHTMLLine(buffer, "", titleAttrs); // add a newline } buffer.append(""); buffer.append(""); @@ -121,16 +143,16 @@ class PluginDetailsPanel extends AbstractDetailsPanel { List> servicesRequired = descriptor.getServicesRequired(); if (servicesRequired.isEmpty()) { - insertHTMLLine(buffer, "None", noValueAttrSet); + insertHTMLLine(buffer, "None", noValueAttrs); } else { for (int i = 0; i < servicesRequired.size(); i++) { - insertHTMLString(buffer, servicesRequired.get(i).getName(), dependencyAttrSet); + insertHTMLString(buffer, servicesRequired.get(i).getName(), dependencyAttrs); if (i < servicesRequired.size() - 1) { buffer.append(HTMLUtilities.BR); } } - insertHTMLLine(buffer, "", titleAttrSet); // add a newline + insertHTMLLine(buffer, "", titleAttrs); // add a newline } buffer.append(""); buffer.append(""); @@ -158,7 +180,7 @@ class PluginDetailsPanel extends AbstractDetailsPanel { buffer.append(""); buffer.append(""); - insertHTMLLine(buffer, "Loaded Actions:", titleAttrSet); + insertHTMLLine(buffer, "Loaded Actions:", titleAttrs); buffer.append(""); Set actions = Collections.emptySet(); @@ -169,7 +191,7 @@ class PluginDetailsPanel extends AbstractDetailsPanel { if (actions.isEmpty()) { buffer.append(""); - insertHTMLLine(buffer, "No actions for plugin", noValueAttrSet); + insertHTMLLine(buffer, "No actions for plugin", noValueAttrs); buffer.append(""); buffer.append(""); return; @@ -182,7 +204,7 @@ class PluginDetailsPanel extends AbstractDetailsPanel { for (DockingActionIf dockableAction : actions) { buffer.append(""); - insertHTMLString(buffer, dockableAction.getName(), locAttrSet); + insertHTMLString(buffer, dockableAction.getName(), locationAttrs); buffer.append(""); buffer.append(""); @@ -190,17 +212,17 @@ class PluginDetailsPanel extends AbstractDetailsPanel { String[] menuPath = menuBarData == null ? null : menuBarData.getMenuPath(); String menuPathString = createStringForMenuPath(menuPath); if (menuPathString != null) { - insertHTMLString(buffer, menuPathString, locAttrSet); + insertHTMLString(buffer, menuPathString, locationAttrs); } else { MenuData popupMenuData = dockableAction.getPopupMenuData(); String[] popupPath = popupMenuData == null ? null : popupMenuData.getMenuPath(); if (popupPath != null) { - insertHTMLString(buffer, "(in a context popup menu)", noValueAttrSet); + insertHTMLString(buffer, "(in a context popup menu)", noValueAttrs); } else { - insertHTMLString(buffer, "Not in a menu", noValueAttrSet); + insertHTMLString(buffer, "Not in a menu", noValueAttrs); } } @@ -210,10 +232,10 @@ class PluginDetailsPanel extends AbstractDetailsPanel { KeyStroke keyBinding = dockableAction.getKeyBinding(); if (keyBinding != null) { String keyStrokeString = KeyBindingUtils.parseKeyStroke(keyBinding); - insertHTMLString(buffer, keyStrokeString, locAttrSet); + insertHTMLString(buffer, keyStrokeString, locationAttrs); } else { - insertHTMLString(buffer, "No keybinding", noValueAttrSet); + insertHTMLString(buffer, "No keybinding", noValueAttrs); } buffer.append(""); @@ -242,74 +264,19 @@ class PluginDetailsPanel extends AbstractDetailsPanel { @Override protected void createFieldAttributes() { - titleAttrSet = new SimpleAttributeSet(); - titleAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); - titleAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11)); - titleAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE); - titleAttrSet.addAttribute(StyleConstants.Foreground, - new GColor("color.fg.pluginpanel.details.title")); + Font font = Gui.getFont(FONT_DEFAULT); + titleAttrs = new GAttributes(font, TITLE_COLOR); + nameAttrs = new GAttributes(font, NAME_NO_DEPENDENTS_COLOR); + dependenciesNameAttrs = new GAttributes(font, NAME_DEPENDENTS_COLOR); + descriptionAttrs = new GAttributes(font, DESCRIPTION_COLOR); + categoriesAttrs = new GAttributes(font, CATEGORIES_COLOR); + locationAttrs = new GAttributes(font, LOCATION_COLOR); + developerAttrs = new GAttributes(font, DEVELOPER_COLOR); - nameAttrSet = new SimpleAttributeSet(); - nameAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); - nameAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11)); - nameAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE); - nameAttrSet.addAttribute(StyleConstants.Foreground, - new GColor("color.fg.pluginpanel.details.name.no.dependents")); + Font fontMonospaced = Gui.getFont(FONT_MONOSPACED); + classAttrs = new GAttributes(fontMonospaced, CLASS_COLOR); + dependencyAttrs = new GAttributes(fontMonospaced, DEPENDENCY_COLOR); - depNameAttrSet = new SimpleAttributeSet(); - depNameAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); - depNameAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11)); - depNameAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE); - depNameAttrSet.addAttribute(StyleConstants.Foreground, - new GColor("color.fg.pluginpanel.details.name.has.dependents")); - - descrAttrSet = new SimpleAttributeSet(); - descrAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); - descrAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11)); - descrAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE); - descrAttrSet.addAttribute(StyleConstants.Foreground, - new GColor("color.fg.pluginpanel.details.description")); - - categoriesAttrSet = new SimpleAttributeSet(); - categoriesAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); - categoriesAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11)); - categoriesAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE); - categoriesAttrSet.addAttribute(StyleConstants.Foreground, - new GColor("color.fg.pluginpanel.details.category")); - - classAttrSet = new SimpleAttributeSet(); - classAttrSet.addAttribute(StyleConstants.FontFamily, "monospaced"); - classAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11)); - classAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE); - classAttrSet.addAttribute(StyleConstants.Foreground, - new GColor("color.fg.pluginpanel.details.class")); - - locAttrSet = new SimpleAttributeSet(); - locAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); - locAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11)); - locAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE); - locAttrSet.addAttribute(StyleConstants.Foreground, - new GColor("color.fg.pluginpanel.details.loc")); - - developerAttrSet = new SimpleAttributeSet(); - developerAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); - developerAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11)); - developerAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE); - developerAttrSet.addAttribute(StyleConstants.Foreground, - new GColor("color.fg.pluginpanel.details.developer")); - - dependencyAttrSet = new SimpleAttributeSet(); - dependencyAttrSet.addAttribute(StyleConstants.FontFamily, "monospaced"); - dependencyAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11)); - dependencyAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE); - dependencyAttrSet.addAttribute(StyleConstants.Foreground, - new GColor("color.fg.pluginpanel.details.dependency")); - - noValueAttrSet = new SimpleAttributeSet(); - noValueAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); - noValueAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11)); - noValueAttrSet.addAttribute(StyleConstants.Italic, Boolean.TRUE); - noValueAttrSet.addAttribute(StyleConstants.Foreground, - new GColor("color.fg.pluginpanel.details.novalue")); + noValueAttrs = new GAttributes(font, NO_VALUE_COLOR); } } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/dialog/PluginInstallerDialog.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/dialog/PluginInstallerDialog.java index 2c4c202252..56faef6675 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/dialog/PluginInstallerDialog.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/dialog/PluginInstallerDialog.java @@ -15,11 +15,14 @@ */ package ghidra.framework.plugintool.dialog; +import static ghidra.framework.plugintool.dialog.PluginInstallerTableModel.*; + import java.awt.*; import java.util.List; import javax.swing.*; import javax.swing.table.TableColumn; +import javax.swing.table.TableColumnModel; import docking.DialogComponentProvider; import docking.widgets.table.*; @@ -149,30 +152,23 @@ public class PluginInstallerDialog extends DialogComponentProvider { tableFilterPanel = new GTableFilterPanel<>(table, tableModel); JScrollPane sp = new JScrollPane(table); - pluginTablePanel.add(sp, BorderLayout.CENTER); pluginTablePanel.add(tableFilterPanel, BorderLayout.SOUTH); // Restrict the size of the first couple columns - the default size is // way too large. This is annoying but our table column classes don't have a nice // way to restrict column width. - TableColumn inst_col = - table.getColumnModel().getColumn(PluginInstallerTableModel.INSTALLED_COL); - inst_col.setMaxWidth(30); - TableColumn status_col = - table.getColumnModel().getColumn(PluginInstallerTableModel.STATUS_COL); - status_col.setMaxWidth(24); + TableColumnModel columnModel = table.getColumnModel(); + TableColumn installedColumn = columnModel.getColumn(INSTALLED_COL); + installedColumn.setMaxWidth(30); + TableColumn statusColumn = columnModel.getColumn(STATUS_COL); + statusColumn.setMaxWidth(24); - tableModel.setTableSortState( - TableSortState.createDefaultSortState(PluginInstallerTableModel.NAME_COL)); + tableModel.setTableSortState(TableSortState.createDefaultSortState(NAME_COL)); tableModel.refresh(); - table.getColumnModel() - .getColumn(PluginInstallerTableModel.NAME_COL) - .setCellRenderer(new NameCellRenderer()); - table.getColumnModel() - .getColumn(PluginInstallerTableModel.STATUS_COL) - .setCellRenderer(new StatusCellRenderer()); + columnModel.getColumn(NAME_COL).setCellRenderer(new NameCellRenderer()); + columnModel.getColumn(STATUS_COL).setCellRenderer(new StatusCellRenderer()); HelpService help = Help.getHelpService(); help.registerHelp(table, new HelpLocation(GenericHelpTopics.TOOL, "PluginDialog")); @@ -214,10 +210,10 @@ public class PluginInstallerDialog extends DialogComponentProvider { renderer.setIcon((value instanceof Icon) ? (Icon) value : null); String toolTipText = ""; - if (value == PluginInstallerTableModel.EXPERIMENTAL_ICON) { + if (value == EXPERIMENTAL_ICON) { toolTipText = "This plugin is usable, but not fully tested or documented"; } - else if (value == PluginInstallerTableModel.DEV_ICON) { + else if (value == DEV_ICON) { toolTipText = "This plugin is under development and not intended for general use.\n" + "It could cause Ghidra to become unstable!"; diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/dialog/PluginManagerComponent.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/dialog/PluginManagerComponent.java index 7f46d08f94..7cd36dfb0e 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/dialog/PluginManagerComponent.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/dialog/PluginManagerComponent.java @@ -176,7 +176,7 @@ public class PluginManagerComponent extends JPanel implements Scrollable { labelPanel.setBackground(BG); GLabel nameLabel = new GLabel(pluginPackage.getName()); - nameLabel.setFont(nameLabel.getFont().deriveFont(18f)); + Gui.registerFont(nameLabel, "font.pluginpanel.name"); nameLabel.setForeground(new GColor("color.fg.pluginpanel.name")); labelPanel.add(nameLabel); diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/project/extensions/ExtensionDetailsPanel.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/project/extensions/ExtensionDetailsPanel.java index ae55a701e6..b9329c3744 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/project/extensions/ExtensionDetailsPanel.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/project/extensions/ExtensionDetailsPanel.java @@ -15,13 +15,11 @@ */ package ghidra.framework.project.extensions; -import java.awt.Color; +import java.awt.Font; import java.awt.Point; -import javax.swing.text.SimpleAttributeSet; - import docking.widgets.table.threaded.ThreadedTableModelListener; -import generic.theme.GColor; +import generic.theme.*; import ghidra.framework.plugintool.dialog.AbstractDetailsPanel; import ghidra.util.extensions.ExtensionDetails; @@ -33,27 +31,28 @@ import ghidra.util.extensions.ExtensionDetails; */ class ExtensionDetailsPanel extends AbstractDetailsPanel { - private static final Color FG_COLOR_AUTHOR = + private static final GColor FG_COLOR_AUTHOR = new GColor("color.fg.extensionpanel.details.author"); - private static final Color FG_COLOR_DATE = new GColor("color.fg.extensionpanel.details.date"); - private static final Color FG_COLOR_DESCRIPTION = + private static final GColor FG_COLOR_DATE = new GColor("color.fg.extensionpanel.details.date"); + private static final GColor FG_COLOR_DESCRIPTION = new GColor("color.fg.extensionpanel.details.description"); - private static final Color FG_COLOR_NAME = new GColor("color.fg.extensionpanel.details.name"); - private static final Color FG_COLOR_PATH = new GColor("color.fg.extensionpanel.path"); - private static final Color FG_COLOR_TITLE = new GColor("color.fg.extensionpanel.details.title"); - private static final Color FG_COLOR_VERSION = + private static final GColor FG_COLOR_NAME = new GColor("color.fg.extensionpanel.details.name"); + private static final GColor FG_COLOR_PATH = new GColor("color.fg.extensionpanel.path"); + private static final GColor FG_COLOR_TITLE = + new GColor("color.fg.extensionpanel.details.title"); + private static final GColor FG_COLOR_VERSION = new GColor("color.fg.extensionpanel.details.version"); /** Attribute sets define the visual characteristics for each field */ - private SimpleAttributeSet nameAttrSet; - private SimpleAttributeSet descrAttrSet; - private SimpleAttributeSet authorAttrSet; - private SimpleAttributeSet createdOnAttrSet; - private SimpleAttributeSet versionAttrSet; - private SimpleAttributeSet pathAttrSet; + private GAttributes nameAttrSet; + private GAttributes descrAttrSet; + private GAttributes authorAttrSet; + private GAttributes createdOnAttrSet; + private GAttributes versionAttrSet; + private GAttributes pathAttrSet; + private ExtensionDetails currentDetails; ExtensionDetailsPanel(ExtensionTablePanel tablePanel) { - super(); createFieldAttributes(); createMainPanel(); @@ -82,13 +81,19 @@ class ExtensionDetailsPanel extends AbstractDetailsPanel { }); } + @Override + protected void refresh() { + setDescription(currentDetails); + } + /** * Updates this panel with the given extension. - * + * * @param details the extension to display */ public void setDescription(ExtensionDetails details) { + this.currentDetails = details; clear(); if (details == null) { return; @@ -134,12 +139,14 @@ class ExtensionDetailsPanel extends AbstractDetailsPanel { @Override protected void createFieldAttributes() { - titleAttrSet = createAttributeSet(FG_COLOR_TITLE); - nameAttrSet = createAttributeSet(FG_COLOR_NAME); - descrAttrSet = createAttributeSet(FG_COLOR_DESCRIPTION); - authorAttrSet = createAttributeSet(FG_COLOR_AUTHOR); - createdOnAttrSet = createAttributeSet(FG_COLOR_DATE); - versionAttrSet = createAttributeSet(FG_COLOR_VERSION); - pathAttrSet = createAttributeSet(FG_COLOR_PATH); + + Font font = Gui.getFont(FONT_DEFAULT); + titleAttrs = new GAttributes(font, FG_COLOR_TITLE); + nameAttrSet = new GAttributes(font, FG_COLOR_NAME); + descrAttrSet = new GAttributes(font, FG_COLOR_DESCRIPTION); + authorAttrSet = new GAttributes(font, FG_COLOR_AUTHOR); + createdOnAttrSet = new GAttributes(font, FG_COLOR_DATE); + versionAttrSet = new GAttributes(font, FG_COLOR_VERSION); + pathAttrSet = new GAttributes(font, FG_COLOR_PATH); } } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/task/gui/GProgressBar.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/task/gui/GProgressBar.java index 19c75a6485..e94af95015 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/task/gui/GProgressBar.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/task/gui/GProgressBar.java @@ -25,6 +25,7 @@ import docking.util.AnimatedIcon; import docking.widgets.EmptyBorderButton; import docking.widgets.label.GDHtmlLabel; import docking.widgets.label.GIconLabel; +import generic.theme.Gui; import ghidra.util.Msg; import ghidra.util.SystemUtilities; import ghidra.util.layout.VerticalLayout; @@ -36,6 +37,8 @@ import resources.ResourceManager; public class GProgressBar extends JPanel { private static final NumberFormat PERCENT_FORMAT = NumberFormat.getPercentInstance(); + private static final String MESSAGE_FONT_ID = "font.task.progress.label.message"; + private volatile long lastProgress = -1; private volatile long progress; private volatile long scaleFactor = 1; @@ -47,7 +50,6 @@ public class GProgressBar extends JPanel { private volatile boolean paintProgressValue = true; private boolean showingIcon = true; - private final float fontSize; private JProgressBar progressBar; private JLabel messageLabel; private JLabel imageLabel; @@ -61,10 +63,9 @@ public class GProgressBar extends JPanel { private CancelledListener cancelledListener; public GProgressBar(CancelledListener cancelledListener, boolean includeTextField, - boolean includeCancelButton, boolean includeAnimatedIcon, float fontSize) { + boolean includeCancelButton, boolean includeAnimatedIcon) { super(new BorderLayout(5, 1)); this.cancelledListener = cancelledListener; - this.fontSize = fontSize; buildProgressPanel(includeTextField, includeCancelButton, includeAnimatedIcon); @@ -217,7 +218,7 @@ public class GProgressBar extends JPanel { // don't care } }; - messageLabel.setFont(messageLabel.getFont().deriveFont(fontSize)); + Gui.registerFont(messageLabel, MESSAGE_FONT_ID); Dimension d = messageLabel.getPreferredSize(); d.width = 180; messageLabel.setPreferredSize(d); diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/task/gui/taskview/ScheduledTaskPanel.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/task/gui/taskview/ScheduledTaskPanel.java index d99660a98d..1b2f8de957 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/task/gui/taskview/ScheduledTaskPanel.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/task/gui/taskview/ScheduledTaskPanel.java @@ -31,7 +31,6 @@ public class ScheduledTaskPanel extends JPanel { private ScheduledElementLayout layout; public ScheduledTaskPanel(String labelText, int indention) { - super(); this.indention = indention; setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0)); @@ -44,7 +43,7 @@ public class ScheduledTaskPanel extends JPanel { } void addProgressBar() { - progressBar = new GProgressBar(null, true, true, false, 12); + progressBar = new GProgressBar(null, true, true, false); progressBar.setBackgroundColor(Colors.BACKGROUND); add(progressBar); layout.clearPreferredSize(); @@ -71,7 +70,7 @@ public class ScheduledTaskPanel extends JPanel { //================================================================================================== // Inner Classes -//================================================================================================== +//================================================================================================== // This layout handles the scrolling based on the scrollOffset as set by the setHiddenViewAmount() // It also optionally shows the scrollbar for the task or group. diff --git a/Ghidra/Framework/Project/src/test.slow/java/ghidra/framework/task/GProgressBarTest.java b/Ghidra/Framework/Project/src/test.slow/java/ghidra/framework/task/GProgressBarTest.java index b5e9971392..9b90d3621f 100644 --- a/Ghidra/Framework/Project/src/test.slow/java/ghidra/framework/task/GProgressBarTest.java +++ b/Ghidra/Framework/Project/src/test.slow/java/ghidra/framework/task/GProgressBarTest.java @@ -15,8 +15,7 @@ */ package ghidra.framework.task; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; @@ -46,11 +45,11 @@ public class GProgressBarTest extends AbstractDockingTest { cancelled = true; } }; - progressBar = new GProgressBar(cancelledListener, true, true, true, 10.0f); + progressBar = new GProgressBar(cancelledListener, true, true, true); } @Test - public void testBasicProgress() { + public void testBasicProgress() { progressBar.initialize(100); assertEquals(0, progressBar.getProgress()); assertEquals(100, progressBar.getMax()); @@ -62,7 +61,7 @@ public class GProgressBarTest extends AbstractDockingTest { } @Test - public void testLongValues() { + public void testLongValues() { progressBar.initialize(0x400000000L); progressBar.setProgress(10); assertEquals(10, progressBar.getProgress()); @@ -73,7 +72,7 @@ public class GProgressBarTest extends AbstractDockingTest { } @Test - public void testMessage() { + public void testMessage() { progressBar.initialize(100); progressBar.setMessage("Hey"); assertEquals("Hey", progressBar.getMessage()); @@ -91,7 +90,7 @@ public class GProgressBarTest extends AbstractDockingTest { } @Test - public void testCancel() { + public void testCancel() { progressBar.initialize(100); progressBar.setProgress(50); assertTrue(!cancelled); diff --git a/Ghidra/Framework/Utility/src/main/java/ghidra/util/SystemUtilities.java b/Ghidra/Framework/Utility/src/main/java/ghidra/util/SystemUtilities.java index e2c0edabe2..de27bb7cc2 100644 --- a/Ghidra/Framework/Utility/src/main/java/ghidra/util/SystemUtilities.java +++ b/Ghidra/Framework/Utility/src/main/java/ghidra/util/SystemUtilities.java @@ -100,7 +100,7 @@ public class SystemUtilities { } /** - * Clean the specified user name to eliminate any spaces or leading domain name + * Clean the specified user name to eliminate any spaces or leading domain name * which may be present (e.g., "MyDomain\John Doe" becomes "JohnDoe"). * @param name user name string to be cleaned-up * @return the clean user name @@ -127,8 +127,8 @@ public class SystemUtilities { } /** - * Get the user that is running the application. This name may be modified to - * eliminate any spaces or leading domain name which may be present in Java's + * Get the user that is running the application. This name may be modified to + * eliminate any spaces or leading domain name which may be present in Java's * {@code user.name} system property (see {@link #getCleanUserName(String)}). * @return the user name */ @@ -173,20 +173,15 @@ public class SystemUtilities { } /** - * Checks to see if the font size override setting is enabled and adjusts - * the given font as necessary to match the override setting. If the setting - * is not enabled, then font is returned. + * No longer supported. Use the theming system for fonts * - * @param font - * The current font to adjust, if necessary. - * @return a font object with the proper size. + * @param font the font + * @return the same font passed in + * @deprecated Use the theming system for fonts */ + @Deprecated(since = "11.1", forRemoval = true) public static Font adjustForFontSizeOverride(Font font) { - if (FONT_SIZE_OVERRIDE_VALUE == null) { - return font; - } - - return font.deriveFont((float) FONT_SIZE_OVERRIDE_VALUE.intValue()); + return font; } /** @@ -350,10 +345,10 @@ public class SystemUtilities { } /** - * Returns a file that contains the given class. If the class is in a jar file, then - * the jar file will be returned. If the file is in a .class file, then the directory + * Returns a file that contains the given class. If the class is in a jar file, then + * the jar file will be returned. If the file is in a .class file, then the directory * containing the package root will be returned (i.e. the "bin" directory). - * + * * @param classObject the class for which to get the location * @return the containing location */ diff --git a/Ghidra/Framework/Utility/src/main/java/utilities/util/reflection/ReflectionUtilities.java b/Ghidra/Framework/Utility/src/main/java/utilities/util/reflection/ReflectionUtilities.java index c40990b929..0a360e8bb1 100644 --- a/Ghidra/Framework/Utility/src/main/java/utilities/util/reflection/ReflectionUtilities.java +++ b/Ghidra/Framework/Utility/src/main/java/utilities/util/reflection/ReflectionUtilities.java @@ -42,12 +42,12 @@ public class ReflectionUtilities { } /** - * Locates the field of the name fieldName on the given - * class. If the given class does not contain the field, then this - * method will recursively call up containingClass's - * implementation tree looking for a parent implementation of the + * Locates the field of the name fieldName on the given + * class. If the given class does not contain the field, then this + * method will recursively call up containingClass's + * implementation tree looking for a parent implementation of the * requested field. - * + * * @param fieldName The name of the field to locate. * @param containingClass The class that contains the desired field. * @return The Field object that matches the given name, or null if not @@ -73,12 +73,12 @@ public class ReflectionUtilities { } /** - * Locates the field of the name fieldName on the given - * class. If the given class does not contain the field, then this - * method will recursively call up containingClass's - * implementation tree looking for a parent implementation of the + * Locates the field of the name fieldName on the given + * class. If the given class does not contain the field, then this + * method will recursively call up containingClass's + * implementation tree looking for a parent implementation of the * requested field. - * + * * @param fieldName The name of the field to locate. * @param containingClass The class that contains the desired field. * @return The Field object that matches the given name, or null if not @@ -104,12 +104,12 @@ public class ReflectionUtilities { } /** - * Locates the method of the name methodName on the given - * class. If the given class does not contain the method, then this - * method will recursively call up containingClass's - * implementation tree looking for a parent implementation of the + * Locates the method of the name methodName on the given + * class. If the given class does not contain the method, then this + * method will recursively call up containingClass's + * implementation tree looking for a parent implementation of the * requested method. - * + * * @param methodName The name of the method to locate. * @param containingClass The class that contains the desired method. * @param parameterTypes The parameters of the desired method (may be null). @@ -158,7 +158,7 @@ public class ReflectionUtilities { /** * Get the first field specification contained within containingClass which has the type classType. - * This method is only really useful if it is known that only a single field of + * This method is only really useful if it is known that only a single field of * classType exists within the containingClass hierarchy. * @param classType the class * @param containingClass the class that contains a field of the given type @@ -184,40 +184,52 @@ public class ReflectionUtilities { /** * Returns the class name of the entry in the stack that comes before all references to the * given classes. This is useful for figuring out at runtime who is calling a particular - * method. + * method. *

      - * This method can take multiple classes, but you really only need to pass the oldest + * This method can take multiple classes, but you really only need to pass the oldest * class of disinterest. - * + * * @param classes the classes to ignore * @return the desired class name */ public static String getClassNameOlderThan(Class... classes) { - Throwable t = createThrowableWithStackOlderThan(classes); StackTraceElement[] stackTrace = t.getStackTrace(); return stackTrace[0].getClassName(); } /** - * Creates a throwable whose stack trace is based upon the current call stack, with any - * information coming before, and including, the given classes removed. - *

      - * This method can take multiple classes, but you really only need to pass the oldest - * class of disinterest. - * - * @param classes the classes to ignore - * @return the new throwable + * Returns the class name of the entry in the stack that comes before all references to the + * given patterns. This is useful for figuring out at runtime who is calling a particular + * method. + * + * @param patterns the patterns to ignore + * @return the desired class name */ - public static Throwable createThrowableWithStackOlderThan(Class... classes) { + public static String getClassNameOlderThan(String... patterns) { + Throwable t = createThrowableWithStackOlderThan(patterns); + StackTraceElement[] stackTrace = t.getStackTrace(); + return stackTrace[0].getClassName(); + } - List toFind = - Arrays.stream(classes).map(c -> c.getName()).collect(Collectors.toList()); + /** + * Creates a throwable whose stack trace is based upon the current call stack, with any + * information coming before, and including, the given patterns removed. + * + * @param patterns the strings to ignore (e.g., class or package names) + * @return the new throwable + * @see #createThrowableWithStackOlderThan(Class...) + */ + public static Throwable createThrowableWithStackOlderThan(String... patterns) { + return createThrowableWithStackOlderThan(List.of(patterns)); + } - if (toFind.isEmpty()) { - // Always ignore our class. We get this for free if the client passes in any - // classes. - toFind.add(0, ReflectionUtilities.class.getName()); + private static Throwable createThrowableWithStackOlderThan(List patterns) { + + if (patterns.isEmpty()) { + // always ignore our class. We get this for free if the client passes in any classes + patterns = new ArrayList<>(); + patterns.add(0, ReflectionUtilities.class.getName()); } Throwable t = new Throwable(); @@ -227,7 +239,7 @@ public class ReflectionUtilities { StackTraceElement element = trace[i]; String className = element.getClassName(); - int nameIndex = toFind.indexOf(className); + int nameIndex = patterns.indexOf(className); if (nameIndex != -1) { lastIgnoreIndex = i; } @@ -242,13 +254,13 @@ public class ReflectionUtilities { if (lastIgnoreIndex == -1) { Msg.error(ReflectionUtilities.class, "Change call to ReflectionUtils. Did not find the " + - "following classes in the call stack: " + Arrays.toString(classes)); + "following patterns in the call stack: " + patterns); } if (lastIgnoreIndex == trace.length - 1) { Msg.error(ReflectionUtilities.class, - "Change call to ReflectionUtils. Call stack only contains the classes to ignore: " + - Arrays.toString(classes)); + "Change call to ReflectionUtils. Call stack contains only ignored patterns: " + + patterns); } int startIndex = lastIgnoreIndex + 1; @@ -258,11 +270,27 @@ public class ReflectionUtilities { } /** - * Finds the first occurrence of the given pattern and then stops filtering when it finds + * Creates a throwable whose stack trace is based upon the current call stack, with any + * information coming before, and including, the given classes removed. + *

      + * This method can take multiple classes, but you really only need to pass the oldest + * class of disinterest. + * + * @param classes the classes to ignore + * @return the new throwable + */ + public static Throwable createThrowableWithStackOlderThan(Class... classes) { + List patterns = + Arrays.stream(classes).map(c -> c.getName()).collect(Collectors.toList()); + return createThrowableWithStackOlderThan(patterns); + } + + /** + * Finds the first occurrence of the given pattern and then stops filtering when it finds * something that is not that pattern - * + * * @param trace the trace to update - * @param pattern the non-regex patterns used to perform a + * @param pattern the non-regex patterns used to perform a * {@link String#contains(CharSequence)} on each {@link StackTraceElement} line * @return the updated trace */ @@ -296,12 +324,12 @@ public class ReflectionUtilities { } /** - * Uses the given patterns to remove elements from the given stack trace. + * Uses the given patterns to remove elements from the given stack trace. * The current implementation will simply perform a toString() on each element and * then check to see if that string contains any of the patterns. - * + * * @param trace the trace to filter - * @param patterns the non-regex patterns used to perform a + * @param patterns the non-regex patterns used to perform a * {@link String#contains(CharSequence)} on each {@link StackTraceElement} * line. * @return the filtered trace @@ -325,15 +353,15 @@ public class ReflectionUtilities { /** * A convenience method to create a throwable, filtering any lines that contain the given * non-regex patterns. This can be useful for emitting diagnostic stack traces. - * - * @param patterns the non-regex patterns used to perform a + * + * @param patterns the non-regex patterns used to perform a * {@link String#contains(CharSequence)} on each {@link StackTraceElement} * line. * @return the new throwable */ public static Throwable createFilteredThrowable(String... patterns) { - Throwable t = createThrowableWithStackOlderThan(); + Throwable t = createThrowableWithStackOlderThan(new ArrayList<>()); StackTraceElement[] trace = t.getStackTrace(); StackTraceElement[] filtered = filterStackTrace(trace, patterns); t.setStackTrace(filtered); @@ -341,40 +369,39 @@ public class ReflectionUtilities { } /** - * A convenience method to create a throwable, filtering boiler-plate Java-related - * lines (e.g., AWT, Swing, Security, etc). + * A convenience method to create a throwable, filtering boiler-plate Java-related + * lines (e.g., AWT, Swing, Security, etc). * This can be useful for emitting diagnostic stack traces with reduced noise. - * + * * @return the new throwable */ public static Throwable createJavaFilteredThrowable() { - - Throwable t = createThrowableWithStackOlderThan(); + Throwable t = createThrowableWithStackOlderThan(List.of()); return filterJavaThrowable(t); } /** - * A convenience method to create a throwable, filtering boiler-plate Java-related - * lines (e.g., AWT, Swing, Security, etc). - * This can be useful for emitting diagnostic stack traces with reduced noise. - * + * A convenience method to create a throwable, filtering boiler-plate Java-related + * lines (e.g., AWT, Swing, Security, etc). + * This can be useful for emitting diagnostic stack traces with reduced noise. + * *

      This method differs from {@link #createJavaFilteredThrowable()} in that this method * returns a String, which is useful when printing log messages without having to directly * print the stack trace. - * + * * @return the new throwable */ public static String createJavaFilteredThrowableString() { - Throwable t = createThrowableWithStackOlderThan(); + Throwable t = createThrowableWithStackOlderThan(List.of()); Throwable filtered = filterJavaThrowable(t); return stackTraceToString(filtered); } /** - * A convenience method to take a throwable, filter boiler-plate Java-related - * lines (e.g., AWT, Swing, Security, etc). + * A convenience method to take a throwable, filter boiler-plate Java-related + * lines (e.g., AWT, Swing, Security, etc). * This can be useful for emitting diagnostic stack traces with reduced noise. - * + * * @param t the throwable to filter * @return the throwable */ @@ -418,15 +445,15 @@ public class ReflectionUtilities { } /** - * Returns an ordered set of interfaces and classes that are shared amongst the items in + * Returns an ordered set of interfaces and classes that are shared amongst the items in * the list. *

      - * The order of the items is as they are first encountered, favoring interfaces before + * The order of the items is as they are first encountered, favoring interfaces before * classes. Further, interface hierarchies are examined before concrete parent extensions. *

      * If the given items have no parents in common, then the result will be a list with * only Object.class. - * + * * @param list the items to examine * @return the set of items */ @@ -461,15 +488,15 @@ public class ReflectionUtilities { } /** - * Returns an ordered set of parent interfaces and classes that are shared + * Returns an ordered set of parent interfaces and classes that are shared * amongst the items in the list. *

      - * The order of the items is as they are first encountered, favoring interfaces before + * The order of the items is as they are first encountered, favoring interfaces before * classes. Further, interface hierarchies are examined before concrete parent extensions. *

      * If the given items have no parents in common, then the result will be a list with * only Object.class. - * + * * @param list the items to examine * @return the set of items */ @@ -494,9 +521,9 @@ public class ReflectionUtilities { } /** - * Turns the given {@link Throwable} into a String version of its + * Turns the given {@link Throwable} into a String version of its * {@link Throwable#printStackTrace()} method. - * + * * @param t the throwable * @return the string */ @@ -505,9 +532,9 @@ public class ReflectionUtilities { } /** - * Turns the given {@link Throwable} into a String version of its + * Turns the given {@link Throwable} into a String version of its * {@link Throwable#printStackTrace()} method. - * + * * @param message the preferred message to use. If null, the throwable message will be used * @param t the throwable * @return the string @@ -543,11 +570,11 @@ public class ReflectionUtilities { /** * Returns an order set of all interfaces implemented and classes extended for the entire - * type structure of the given class. + * type structure of the given class. *

      - * If Object.class is passed to this method, then it will be returned in the + * If Object.class is passed to this method, then it will be returned in the * result of this method. - * + * * @param c the class to introspect * @return the set of parents */ @@ -581,7 +608,7 @@ public class ReflectionUtilities { /** * Returns the type arguments for the given base class and extension. - * + * *

      Caveat: this lookup will only work if the given child class is a concrete class that * has its type arguments specified. For example, these cases will work: *

      @@ -592,17 +619,17 @@ public class ReflectionUtilities {
       	 *
       	 *		// class definition
       	 *		public class MyList implements List<String> {
      -	 * 
      - * + * + * * Whereas this case will not work: *
       	 * 		// local variable with the type specified
       	 * 		List<String> myList = new ArrayList<String>();
       	 * 
      - * + * *

      Note: a null entry in the result list will exist for any type that was unrecoverable - * - * + * + * * @param the type of the base and child class * @param baseClass the base class * @param childClass the child class @@ -618,7 +645,7 @@ public class ReflectionUtilities { Type baseClassAsType = walkClassHierarchyAndResolveTypes(baseClass, resolvedTypesDictionary, childClass); - // try to resolve type arguments defined by 'baseClass' to the raw runtime class + // try to resolve type arguments defined by 'baseClass' to the raw runtime class Type[] baseClassDeclaredTypeArguments = getDeclaredTypeArguments(baseClassAsType); return resolveBaseClassTypeArguments(resolvedTypesDictionary, baseClassDeclaredTypeArguments); 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 bcd7fb20ba..22db2e7696 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/RepositoryCustomScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/RepositoryCustomScreenShots.java @@ -33,7 +33,6 @@ import resources.ResourceManager; public class RepositoryCustomScreenShots extends GhidraScreenShotGenerator { public RepositoryCustomScreenShots() { - super(); } @Test @@ -127,8 +126,6 @@ public class RepositoryCustomScreenShots extends GhidraScreenShotGenerator { int y = p.y - radius; g.fillOval(x, y, radius * 2, 2 * radius); - Font f = g.getFont().deriveFont(12f); - g.setFont(f); FontMetrics metrics = g.getFontMetrics(); int height = metrics.getHeight(); g.setColor(Palette.BLACK); @@ -154,8 +151,6 @@ public class RepositoryCustomScreenShots extends GhidraScreenShotGenerator { BasicStroke stroke = new BasicStroke(1); g.setStroke(stroke); - Font f = g.getFont().deriveFont(12f); - g.setFont(f); FontMetrics metrics = g.getFontMetrics(); int margin = 5; int height = metrics.getHeight() * text.length + 2 * margin; @@ -189,8 +184,6 @@ public class RepositoryCustomScreenShots extends GhidraScreenShotGenerator { Graphics2D g = ((BufferedImage) image).createGraphics(); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - Font f = g.getFont().deriveFont(12f); - g.setFont(f); FontMetrics metrics = g.getFontMetrics(); // int margin = 5; int height = metrics.getHeight() * text.length;