Merge remote-tracking branch 'origin/GP-4154-dragonmacher-theme-font-updates--SQUASHED'

This commit is contained in:
Ryan Kurtz 2024-02-23 13:19:46 -05:00
commit 86516b1718
91 changed files with 1309 additions and 1191 deletions

View File

@ -26,7 +26,8 @@ import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.swing.*; import javax.swing.*;
import javax.swing.table.*; import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import db.Transaction; import db.Transaction;
import docking.action.DockingAction; import docking.action.DockingAction;
@ -265,8 +266,8 @@ public class DebuggerPcodeStepperProvider extends ComponentProviderAdapter {
} }
@Override @Override
protected void configureFont(JTable table, TableModel model, int column) { protected Font getDefaultFont() {
setFont(fixedWidthFont); return fixedWidthFont;
} }
@Override @Override

View File

@ -25,7 +25,6 @@ import java.util.function.BiFunction;
import javax.swing.*; import javax.swing.*;
import javax.swing.plaf.basic.BasicHTML; import javax.swing.plaf.basic.BasicHTML;
import javax.swing.table.TableModel;
import javax.swing.text.View; import javax.swing.text.View;
import ghidra.docking.settings.Settings; import ghidra.docking.settings.Settings;
@ -92,11 +91,7 @@ public class CustomToStringCellRenderer<T> extends AbstractGColumnRenderer<T> {
} }
@Override @Override
protected void configureFont(JTable table, TableModel model, int column) { protected Font getDefaultFont() {
setFont(getCustomFont());
}
protected Font getCustomFont() {
switch (customFont) { switch (customFont) {
default: default:
case DEFAULT: case DEFAULT:

View File

@ -15,11 +15,9 @@
*/ */
package ghidra.machinelearning.functionfinding; package ghidra.machinelearning.functionfinding;
import java.awt.Font;
import java.util.List; import java.util.List;
import javax.swing.JTable;
import javax.swing.table.TableModel;
import docking.widgets.table.AbstractDynamicTableColumn; import docking.widgets.table.AbstractDynamicTableColumn;
import docking.widgets.table.TableColumnDescriptor; import docking.widgets.table.TableColumnDescriptor;
import ghidra.docking.settings.Settings; import ghidra.docking.settings.Settings;
@ -48,7 +46,7 @@ public class SimilarStartsTableModel extends AddressBasedTableModel<SimilarStart
* Construct a table model for a table to display the closest function starts to * Construct a table model for a table to display the closest function starts to
* a potential function start * a potential function start
* @param plugin owning program * @param plugin owning program
* @param program program * @param program program
* @param rows similar function starts * @param rows similar function starts
* @param randomForestRow model and params * @param randomForestRow model and params
*/ */
@ -123,9 +121,10 @@ public class SimilarStartsTableModel extends AddressBasedTableModel<SimilarStart
@Override @Override
public GColumnRenderer<String> getColumnRenderer() { public GColumnRenderer<String> getColumnRenderer() {
final GColumnRenderer<String> monospacedRenderer = new AbstractGColumnRenderer<>() { final GColumnRenderer<String> monospacedRenderer = new AbstractGColumnRenderer<>() {
@Override @Override
protected void configureFont(JTable table, TableModel model, int column) { protected Font getDefaultFont() {
setFont(getFixedWidthFont()); return fixedWidthFont;
} }
@Override @Override

View File

@ -15,7 +15,8 @@
*/ */
package ghidra.examples; package ghidra.examples;
import java.awt.*; import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.*; import java.awt.event.*;
import javax.swing.*; import javax.swing.*;
@ -30,8 +31,8 @@ import ghidra.util.HelpLocation;
import ghidra.util.Msg; import ghidra.util.Msg;
public class HelloWorldComponentProvider extends ComponentProviderAdapter { public class HelloWorldComponentProvider extends ComponentProviderAdapter {
private final static HelpLocation HELP = new HelpLocation("SampleHelpTopic", private final static HelpLocation HELP =
"SampleHelpTopic_Anchor_Name"); new HelpLocation("SampleHelpTopic", "SampleHelpTopic_Anchor_Name");
private MyButton activeButtonObj; private MyButton activeButtonObj;
private JPanel mainPanel; private JPanel mainPanel;
private DockingAction action; private DockingAction action;
@ -64,8 +65,8 @@ public class HelloWorldComponentProvider extends ComponentProviderAdapter {
// the menu item will appear on the local toolbar drop down. // the menu item will appear on the local toolbar drop down.
Icon icon = new GIcon("icon.sample.action.hello.world"); Icon icon = new GIcon("icon.sample.action.hello.world");
action.setMenuBarData(new MenuData(new String[] { "Misc", "Hello World" }, icon)); action.setMenuBarData(new MenuData(new String[] { "Misc", "Hello World" }, icon));
action.setKeyBindingData(new KeyBindingData(KeyStroke.getKeyStroke(KeyEvent.VK_W, action.setKeyBindingData(
InputEvent.CTRL_MASK))); new KeyBindingData(KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.CTRL_MASK)));
// puts the action on the local toolbar. // puts the action on the local toolbar.
action.setToolBarData(new ToolBarData(icon)); action.setToolBarData(new ToolBarData(icon));
@ -81,11 +82,11 @@ public class HelloWorldComponentProvider extends ComponentProviderAdapter {
public void actionPerformed(ActionContext context) { public void actionPerformed(ActionContext context) {
announce("Hello World"); announce("Hello World");
// To get the context object, // To get the context object,
Object contextObject = context.getContextObject(); Object contextObject = context.getContextObject();
// ...now we can cast activeObj to be a object of MyButton // ...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 // will not add the popup action if the context object is not our button
@SuppressWarnings("unused") @SuppressWarnings("unused")
@ -120,8 +121,6 @@ public class HelloWorldComponentProvider extends ComponentProviderAdapter {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER)); JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER));
panel.setBorder(BorderFactory.createTitledBorder("Example of a Component")); panel.setBorder(BorderFactory.createTitledBorder("Example of a Component"));
activeButtonObj = new MyButton("Hello World"); activeButtonObj = new MyButton("Hello World");
Font f = activeButtonObj.getFont();
activeButtonObj.setFont(f.deriveFont(Font.BOLD, 14));
panel.add(activeButtonObj); panel.add(activeButtonObj);
mainPanel.add(panel, BorderLayout.CENTER); mainPanel.add(panel, BorderLayout.CENTER);
} }

View File

@ -16,12 +16,11 @@
package ghidra.features.bsim.gui.overview; package ghidra.features.bsim.gui.overview;
import java.awt.Component; import java.awt.Component;
import java.awt.Font;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.TableModel;
import docking.widgets.table.*; import docking.widgets.table.*;
import generic.lsh.vector.LSHVectorFactory; import generic.lsh.vector.LSHVectorFactory;
@ -233,8 +232,8 @@ public class BSimOverviewModel extends AddressBasedTableModel<BSimOverviewRowObj
} }
@Override @Override
protected void configureFont(JTable table, TableModel model, int column) { protected Font getDefaultFont() {
setFont(fixedWidthFont); return fixedWidthFont;
} }
@Override @Override

View File

@ -28,6 +28,7 @@ import docking.DockingWindowManager;
import docking.widgets.EmptyBorderButton; import docking.widgets.EmptyBorderButton;
import docking.widgets.combobox.GComboBox; import docking.widgets.combobox.GComboBox;
import docking.widgets.textfield.FloatingPointTextField; import docking.widgets.textfield.FloatingPointTextField;
import generic.theme.Gui;
import ghidra.features.bsim.query.BSimServerInfo; import ghidra.features.bsim.query.BSimServerInfo;
import ghidra.features.bsim.query.description.DatabaseInformation; import ghidra.features.bsim.query.description.DatabaseInformation;
import ghidra.features.bsim.query.facade.QueryDatabaseException; import ghidra.features.bsim.query.facade.QueryDatabaseException;
@ -243,7 +244,7 @@ public abstract class AbstractBSimSearchDialog extends DialogComponentProvider {
contentPanel.add(comp, fullWidth ? BorderLayout.CENTER : BorderLayout.WEST); contentPanel.add(comp, fullWidth ? BorderLayout.CENTER : BorderLayout.WEST);
JLabel label = new JLabel(name); JLabel label = new JLabel(name);
label.setFont(label.getFont().deriveFont(Font.BOLD)); Gui.registerFont(label, Font.BOLD);
titlePanel.add(label, BorderLayout.NORTH); titlePanel.add(label, BorderLayout.NORTH);
return panel; return panel;
@ -260,7 +261,7 @@ public abstract class AbstractBSimSearchDialog extends DialogComponentProvider {
//================================================================================================== //==================================================================================================
// test methods // test methods
//================================================================================================== //==================================================================================================
protected void setServer(BSimServerInfo info) { protected void setServer(BSimServerInfo info) {
initializeConnection(info); initializeConnection(info);
} }
@ -271,7 +272,7 @@ public abstract class AbstractBSimSearchDialog extends DialogComponentProvider {
//================================================================================================== //==================================================================================================
// Inner Classes // Inner Classes
//================================================================================================== //==================================================================================================
protected abstract class BSimQueryTask extends Task { protected abstract class BSimQueryTask extends Task {
protected Exception errorException; protected Exception errorException;

View File

@ -18,11 +18,10 @@ package ghidra.features.bsim.gui.search.results;
import static ghidra.features.bsim.gui.search.results.BSimResultStatus.*; import static ghidra.features.bsim.gui.search.results.BSimResultStatus.*;
import java.awt.Component; import java.awt.Component;
import java.awt.Font;
import java.util.*; import java.util.*;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.TableModel;
import docking.widgets.table.*; import docking.widgets.table.*;
import generic.lsh.vector.LSHVectorFactory; import generic.lsh.vector.LSHVectorFactory;
@ -56,7 +55,7 @@ public class BSimMatchResultsModel extends AddressBasedTableModel<BSimMatchResul
private Collection<BSimMatchResult> results = new ArrayList<BSimMatchResult>(); private Collection<BSimMatchResult> results = new ArrayList<BSimMatchResult>();
// Maps functions (represented by addresses) to the number of matches in the query. // 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<Address, Integer> functionMatchMap = new HashMap<>(); private Map<Address, Integer> functionMatchMap = new HashMap<>();
public BSimMatchResultsModel(PluginTool tool, DatabaseInformation info, public BSimMatchResultsModel(PluginTool tool, DatabaseInformation info,
@ -70,15 +69,15 @@ public class BSimMatchResultsModel extends AddressBasedTableModel<BSimMatchResul
return; // Info can be null, even if FunctionDatabase return Ready (not created yet) return; // Info can be null, even if FunctionDatabase return Ready (not created yet)
} }
if (info.execats != null) { if (info.execats != null) {
for (int i = 0; i < info.execats.size(); ++i) { for (String element : info.execats) {
addTableColumn(new ExecCategoryColumn(info.execats.get(i))); addTableColumn(new ExecCategoryColumn(element));
} }
} }
if (info.functionTags != null) { if (info.functionTags != null) {
int mask = 1; int mask = 1;
mask <<= FunctionTagBSimFilterType.RESERVED_BITS; mask <<= FunctionTagBSimFilterType.RESERVED_BITS;
for (int i = 0; i < info.functionTags.size(); ++i) { for (String element : info.functionTags) {
addTableColumn(new FunctionTagColumn(info.functionTags.get(i), mask)); addTableColumn(new FunctionTagColumn(element, mask));
mask <<= 1; mask <<= 1;
} }
} }
@ -90,7 +89,7 @@ public class BSimMatchResultsModel extends AddressBasedTableModel<BSimMatchResul
} }
// Must add this column here because it requires that the queryManager // Must add this column here because it requires that the queryManager
// be available. At the time createTableColumnDescriptor() is called this // be available. At the time createTableColumnDescriptor() is called this
// is not the case. The index is set to '-1' so it will be placed at the end // is not the case. The index is set to '-1' so it will be placed at the end
// of the list. // of the list.
if (lshVectorFactory != null) { if (lshVectorFactory != null) {
@ -114,12 +113,12 @@ public class BSimMatchResultsModel extends AddressBasedTableModel<BSimMatchResul
descriptor.addHiddenColumn(new CompilerMatchColumn()); descriptor.addHiddenColumn(new CompilerMatchColumn());
descriptor.addHiddenColumn(new MatchCountTableColumn()); descriptor.addHiddenColumn(new MatchCountTableColumn());
descriptor.addHiddenColumn(new FunctionSizeTableColumn()); descriptor.addHiddenColumn(new FunctionSizeTableColumn());
descriptor.addHiddenColumn(new FunctionTagColumn("Known Library", descriptor.addHiddenColumn(
FunctionTagBSimFilterType.KNOWN_LIBRARY_MASK)); new FunctionTagColumn("Known Library", FunctionTagBSimFilterType.KNOWN_LIBRARY_MASK));
descriptor.addHiddenColumn(new FunctionTagColumn("Has Unimplemented", descriptor.addHiddenColumn(new FunctionTagColumn("Has Unimplemented",
FunctionTagBSimFilterType.HAS_UNIMPLEMENTED_MASK)); FunctionTagBSimFilterType.HAS_UNIMPLEMENTED_MASK));
descriptor.addHiddenColumn(new FunctionTagColumn("Has Bad Data", descriptor.addHiddenColumn(
FunctionTagBSimFilterType.HAS_BADDATA_MASK)); new FunctionTagColumn("Has Bad Data", FunctionTagBSimFilterType.HAS_BADDATA_MASK));
descriptor.addVisibleColumn( descriptor.addVisibleColumn(
DiscoverableTableUtils.adaptColumForModel(this, new AddressTableColumn())); DiscoverableTableUtils.adaptColumForModel(this, new AddressTableColumn()));
descriptor.addHiddenColumn(new MatchingFunctionAddressTableColumn()); descriptor.addHiddenColumn(new MatchingFunctionAddressTableColumn());
@ -171,9 +170,9 @@ public class BSimMatchResultsModel extends AddressBasedTableModel<BSimMatchResul
} }
/** /**
* Parses the given result set to find the number of matches associated with * Parses the given result set to find the number of matches associated with
* each base function. * each base function.
* *
* @param queryResults the query results to inspect * @param queryResults the query results to inspect
*/ */
private void parseFunctionMatchCounts(Collection<BSimMatchResult> queryResults) { private void parseFunctionMatchCounts(Collection<BSimMatchResult> queryResults) {
@ -192,7 +191,7 @@ public class BSimMatchResultsModel extends AddressBasedTableModel<BSimMatchResul
/** /**
* Associate a given FunctionDescription with the entry point of the matching function in a program * Associate a given FunctionDescription with the entry point of the matching function in a program
* @param desc is the FunctionDescription to recover * @param desc is the FunctionDescription to recover
* @param prog is the Program (possibly) containing the Function object * @param prog is the Program (possibly) containing the Function object
* @return the entry point address of the function (if it exists), or just the address within the default space * @return the entry point address of the function (if it exists), or just the address within the default space
*/ */
public static Address recoverAddress(FunctionDescription desc, Program prog) { public static Address recoverAddress(FunctionDescription desc, Program prog) {
@ -288,10 +287,10 @@ public class BSimMatchResultsModel extends AddressBasedTableModel<BSimMatchResul
} }
@Override @Override
public String getValue(BSimMatchResult rowObject, Settings settings, Program program, public String getValue(BSimMatchResult rowObject, Settings settings, Program p,
ServiceProvider serviceProvider) throws IllegalArgumentException { ServiceProvider serviceProvider) throws IllegalArgumentException {
Address address = rowObject.getAddress(); Address address = rowObject.getAddress();
Function function = program.getFunctionManager().getFunctionAt(address); Function function = p.getFunctionManager().getFunctionAt(address);
boolean showNamespace = SHOW_NAMESPACE.getValue(settings); boolean showNamespace = SHOW_NAMESPACE.getValue(settings);
if (function != null) { if (function != null) {
return function.getName(showNamespace); return function.getName(showNamespace);
@ -319,7 +318,7 @@ public class BSimMatchResultsModel extends AddressBasedTableModel<BSimMatchResul
} }
@Override @Override
public String getValue(BSimMatchResult rowObject, Settings settings, Program program, public String getValue(BSimMatchResult rowObject, Settings settings, Program p,
ServiceProvider serviceProvider) throws IllegalArgumentException { ServiceProvider serviceProvider) throws IllegalArgumentException {
String name = rowObject.getSimilarFunctionName(); String name = rowObject.getSimilarFunctionName();
boolean showNamespace = SHOW_NAMESPACE.getValue(settings); boolean showNamespace = SHOW_NAMESPACE.getValue(settings);
@ -365,7 +364,7 @@ public class BSimMatchResultsModel extends AddressBasedTableModel<BSimMatchResul
/** /**
* Column for showing the number of matches each base function has. * Column for showing the number of matches each base function has.
* *
* Note the use of the {@link BSimMatchResultsModel#functionMatchMap}; this is * Note the use of the {@link BSimMatchResultsModel#functionMatchMap}; this is
* for performance reasons. We don't want this class looping over the entire * for performance reasons. We don't want this class looping over the entire
* result set calculating match counts every time the table is refreshed. * result set calculating match counts every time the table is refreshed.
@ -380,7 +379,7 @@ public class BSimMatchResultsModel extends AddressBasedTableModel<BSimMatchResul
} }
@Override @Override
public Integer getValue(BSimMatchResult rowObject, Settings settings, Program program, public Integer getValue(BSimMatchResult rowObject, Settings settings, Program p,
ServiceProvider provider) throws IllegalArgumentException { ServiceProvider provider) throws IllegalArgumentException {
return functionMatchMap.get(rowObject.getAddress()); return functionMatchMap.get(rowObject.getAddress());
} }
@ -392,7 +391,7 @@ public class BSimMatchResultsModel extends AddressBasedTableModel<BSimMatchResul
} }
/** /**
* Column for showing the address of the matching function. * Column for showing the address of the matching function.
*/ */
private static class MatchingFunctionAddressTableColumn private static class MatchingFunctionAddressTableColumn
extends AbstractProgramBasedDynamicTableColumn<BSimMatchResult, Long> { extends AbstractProgramBasedDynamicTableColumn<BSimMatchResult, Long> {
@ -404,7 +403,7 @@ public class BSimMatchResultsModel extends AddressBasedTableModel<BSimMatchResul
} }
@Override @Override
public Long getValue(BSimMatchResult rowObject, Settings settings, Program data, public Long getValue(BSimMatchResult rowObject, Settings settings, Program p,
ServiceProvider serviceProvider) throws IllegalArgumentException { ServiceProvider serviceProvider) throws IllegalArgumentException {
Long addr = rowObject.getMatchFunctionDescription().getAddress(); Long addr = rowObject.getMatchFunctionDescription().getAddress();
return addr; return addr;
@ -437,8 +436,8 @@ public class BSimMatchResultsModel extends AddressBasedTableModel<BSimMatchResul
} }
@Override @Override
protected void configureFont(JTable table, TableModel model, int column) { protected Font getDefaultFont() {
setFont(fixedWidthFont); return fixedWidthFont;
} }
@Override @Override
@ -464,10 +463,10 @@ public class BSimMatchResultsModel extends AddressBasedTableModel<BSimMatchResul
} }
@Override @Override
public Long getValue(BSimMatchResult rowObject, Settings settings, Program program, public Long getValue(BSimMatchResult rowObject, Settings settings, Program p,
ServiceProvider provider) throws IllegalArgumentException { ServiceProvider provider) throws IllegalArgumentException {
Address address = rowObject.getAddress(); Address address = rowObject.getAddress();
Function function = program.getFunctionManager().getFunctionAt(address); Function function = p.getFunctionManager().getFunctionAt(address);
return function.getBody().getNumAddresses(); return function.getBody().getNumAddresses();
} }
@ -482,7 +481,6 @@ public class BSimMatchResultsModel extends AddressBasedTableModel<BSimMatchResul
private String columnName; private String columnName;
ExecDateColumn(String name) { ExecDateColumn(String name) {
super();
columnName = name; columnName = name;
} }
@ -492,7 +490,7 @@ public class BSimMatchResultsModel extends AddressBasedTableModel<BSimMatchResul
} }
@Override @Override
public Date getValue(BSimMatchResult rowObject, Settings settings, Program program, public Date getValue(BSimMatchResult rowObject, Settings settings, Program p,
ServiceProvider serviceProvider) throws IllegalArgumentException { ServiceProvider serviceProvider) throws IllegalArgumentException {
return rowObject.getDate(); return rowObject.getDate();
} }
@ -519,7 +517,7 @@ public class BSimMatchResultsModel extends AddressBasedTableModel<BSimMatchResul
} }
@Override @Override
public String getValue(BSimMatchResult rowObject, Settings settings, Program program, public String getValue(BSimMatchResult rowObject, Settings settings, Program p,
ServiceProvider serviceProvider) throws IllegalArgumentException { ServiceProvider serviceProvider) throws IllegalArgumentException {
return rowObject.getExeCategoryAlphabetic(columnName); return rowObject.getExeCategoryAlphabetic(columnName);
} }
@ -540,7 +538,7 @@ public class BSimMatchResultsModel extends AddressBasedTableModel<BSimMatchResul
} }
@Override @Override
public String getValue(BSimMatchResult rowObject, Settings settings, Program program, public String getValue(BSimMatchResult rowObject, Settings settings, Program p,
ServiceProvider serviceProvider) throws IllegalArgumentException { ServiceProvider serviceProvider) throws IllegalArgumentException {
return rowObject.getArchitecture(); return rowObject.getArchitecture();
} }
@ -561,7 +559,7 @@ public class BSimMatchResultsModel extends AddressBasedTableModel<BSimMatchResul
} }
@Override @Override
public String getValue(BSimMatchResult rowObject, Settings settings, Program program, public String getValue(BSimMatchResult rowObject, Settings settings, Program p,
ServiceProvider serviceProvider) throws IllegalArgumentException { ServiceProvider serviceProvider) throws IllegalArgumentException {
return rowObject.getCompilerName(); return rowObject.getCompilerName();
} }
@ -582,7 +580,7 @@ public class BSimMatchResultsModel extends AddressBasedTableModel<BSimMatchResul
} }
@Override @Override
public String getValue(BSimMatchResult rowObject, Settings settings, Program program, public String getValue(BSimMatchResult rowObject, Settings settings, Program p,
ServiceProvider serviceProvider) throws IllegalArgumentException { ServiceProvider serviceProvider) throws IllegalArgumentException {
return rowObject.getMd5(); return rowObject.getMd5();
} }
@ -604,7 +602,7 @@ public class BSimMatchResultsModel extends AddressBasedTableModel<BSimMatchResul
} }
@Override @Override
public Double getValue(BSimMatchResult rowObject, Settings settings, Program program, public Double getValue(BSimMatchResult rowObject, Settings settings, Program p,
ServiceProvider serviceProvider) throws IllegalArgumentException { ServiceProvider serviceProvider) throws IllegalArgumentException {
return rowObject.getSimilarity(); return rowObject.getSimilarity();
} }
@ -630,7 +628,7 @@ public class BSimMatchResultsModel extends AddressBasedTableModel<BSimMatchResul
} }
@Override @Override
public Double getValue(BSimMatchResult rowObject, Settings settings, Program program, public Double getValue(BSimMatchResult rowObject, Settings settings, Program p,
ServiceProvider serviceProvider) throws IllegalArgumentException { ServiceProvider serviceProvider) throws IllegalArgumentException {
return rowObject.getSignificance(); return rowObject.getSignificance();
} }
@ -662,7 +660,7 @@ public class BSimMatchResultsModel extends AddressBasedTableModel<BSimMatchResul
} }
@Override @Override
public Double getValue(BSimMatchResult rowObject, Settings settings, Program program, public Double getValue(BSimMatchResult rowObject, Settings settings, Program p,
ServiceProvider serviceProvider) throws IllegalArgumentException { ServiceProvider serviceProvider) throws IllegalArgumentException {
return vectorFactory.getSelfSignificance( return vectorFactory.getSelfSignificance(
rowObject.getMatchFunctionDescription().getSignatureRecord().getLSHVector()); rowObject.getMatchFunctionDescription().getSignatureRecord().getLSHVector());
@ -696,7 +694,7 @@ public class BSimMatchResultsModel extends AddressBasedTableModel<BSimMatchResul
} }
@Override @Override
public Boolean getValue(BSimMatchResult rowObject, Settings settings, Program data, public Boolean getValue(BSimMatchResult rowObject, Settings settings, Program p,
ServiceProvider serviceProvider) throws IllegalArgumentException { ServiceProvider serviceProvider) throws IllegalArgumentException {
return rowObject.isFlagSet(mask); return rowObject.isFlagSet(mask);
} }

View File

@ -23,6 +23,7 @@ import java.util.stream.Collectors;
import javax.swing.*; import javax.swing.*;
import docking.DialogComponentProvider; import docking.DialogComponentProvider;
import generic.theme.Gui;
import ghidra.features.bsim.gui.BSimSearchPlugin; import ghidra.features.bsim.gui.BSimSearchPlugin;
import ghidra.features.bsim.gui.search.dialog.BSimFilterSet; import ghidra.features.bsim.gui.search.dialog.BSimFilterSet;
import ghidra.features.bsim.gui.search.dialog.BSimFilterSet.FilterEntry; import ghidra.features.bsim.gui.search.dialog.BSimFilterSet.FilterEntry;
@ -64,7 +65,7 @@ public class BSimSearchInfoDisplayDialog extends DialogComponentProvider {
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
JLabel dataLabel = new JLabel("Search Options:"); JLabel dataLabel = new JLabel("Search Options:");
dataLabel.setFont(dataLabel.getFont().deriveFont(Font.ITALIC)); Gui.registerFont(dataLabel, Font.ITALIC);
panel.add(dataLabel); panel.add(dataLabel);
panel.add(new JLabel("")); panel.add(new JLabel(""));
@ -89,7 +90,7 @@ public class BSimSearchInfoDisplayDialog extends DialogComponentProvider {
panel.add(new JLabel("")); panel.add(new JLabel(""));
panel.add(new JLabel("")); panel.add(new JLabel(""));
JLabel filterLabel = new JLabel("Filters:"); JLabel filterLabel = new JLabel("Filters:");
filterLabel.setFont(filterLabel.getFont().deriveFont(Font.ITALIC)); Gui.registerFont(filterLabel, Font.ITALIC);
panel.add(filterLabel); panel.add(filterLabel);
panel.add(new JLabel("")); panel.add(new JLabel(""));

View File

@ -166,19 +166,26 @@ color.bg.plugin.windowlocation.screens = color.palette.orange
color.bg.plugin.windowlocation.window.selected = color.palette.lime color.bg.plugin.windowlocation.window.selected = color.palette.lime
color.fg.plugin.windowlocation.window.text = color.palette.gray color.fg.plugin.windowlocation.window.text = color.palette.gray
font.print = SansSerif-PLAIN-10 font.print = SansSerif-PLAIN-10
font.splash.infopanel = SansSerif-BOLD-14
font.plugin.assembly.dual.text.field = font.monospaced
font.plugin.console = font.monospaced font.plugin.console = font.monospaced
font.plugin.entropy.label.knot = sansserif-bold-12
font.plugin.function.text.editor = sansserif-plain-18
font.plugin.instruction.table.renderer = courier-plain-14
font.plugin.instruction.info = font.monospaced[14]
font.plugin.service.text.editor = font.monospaced font.plugin.service.text.editor = font.monospaced
font.plugin.scripts.text.editor = font.monospaced font.plugin.scripts.text.editor = font.monospaced
font.plugin.assembly.dual.text.field = font.monospaced font.plugin.strings.buttons = sansserif-plain-10
font.plugin.instruction.table.renderer = courier-plain-14 font.plugin.tabs = sansserif-plain-11
font.plugin.entropy.label.knot = SansSerif-BOLD-12 font.plugin.tabs.list = sansserif-bold-9
font.plugin.instruction.info = font.monospaced[14] font.plugin.tips = dialog-plain-12
font.plugin.tabs = SansSerif-PLAIN-11 font.plugin.tips.label = font.plugin.tips[bold]
font.plugin.tabs.list = SansSerif-BOLD-9
font.plugin.tips = Dialog-PLAIN-12
font.plugin.tips.label = font.plugin.tips[BOLD]
font.plugin.terminal = font.monospaced font.plugin.terminal = font.monospaced
font.plugin.terminal.completion.list = dialog-plain-12
font.plugin.window.location = font.monospaced[40]

View File

@ -17,6 +17,7 @@ package ghidra.app.merge;
import java.awt.Color; import java.awt.Color;
import generic.theme.GColor;
import generic.theme.GThemeDefaults.Colors.Palette; import generic.theme.GThemeDefaults.Colors.Palette;
public interface MergeConstants { public interface MergeConstants {
@ -29,13 +30,13 @@ public interface MergeConstants {
public static final String LATEST_TITLE = "Latest"; public static final String LATEST_TITLE = "Latest";
public static final String MY_TITLE = "Checked Out"; public static final String MY_TITLE = "Checked Out";
public Color CONFLICT_COLOR = Palette.MAROON; public GColor CONFLICT_COLOR = Palette.MAROON;
public static final Color HIGHLIGHT_COLOR = Palette.LIGHT_GRAY; public static final Color HIGHLIGHT_COLOR = Palette.LIGHT_GRAY;
// The following are standardized names for use in passing resolve // The following are standardized names for use in passing resolve
// information between individual merge managers. // information between individual merge managers.
// For example: // For example:
// the data type merger knows what data type in the result is equivalent // the data type merger knows what data type in the result is equivalent
// to a given data type from my checked out program. The code unit and // to a given data type from my checked out program. The code unit and
// function mergers need to be able to get this information so they // function mergers need to be able to get this information so they
// don't unknowingly re-introduce a data type that was already eliminated // don't unknowingly re-introduce a data type that was already eliminated

View File

@ -16,13 +16,14 @@
package ghidra.app.merge.datatypes; package ghidra.app.merge.datatypes;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.Color; import java.awt.Font;
import java.util.Arrays; import java.util.Arrays;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JTextPane; import javax.swing.JTextPane;
import javax.swing.text.*; import javax.swing.text.*;
import generic.theme.*;
import generic.theme.GThemeDefaults.Colors.Palette; import generic.theme.GThemeDefaults.Colors.Palette;
import ghidra.app.merge.MergeConstants; import ghidra.app.merge.MergeConstants;
import ghidra.docking.settings.Settings; import ghidra.docking.settings.Settings;
@ -36,23 +37,21 @@ import ghidra.util.UniversalID;
/** /**
* Panel to show the contents of a Data Type. * Panel to show the contents of a Data Type.
*
*
*/ */
class DataTypePanel extends JPanel { class DataTypePanel extends JPanel {
public Color SOURCE_COLOR = Palette.GREEN; public GColor SOURCE_COLOR = Palette.GREEN;
private DataType dataType; private DataType dataType;
private JTextPane textPane; private JTextPane textPane;
private StyledDocument doc; private StyledDocument doc;
private SimpleAttributeSet pathAttrSet; private SimpleAttributeSet pathAttrs;
private SimpleAttributeSet nameAttrSet; private SimpleAttributeSet nameAttrs;
private SimpleAttributeSet sourceAttrSet; private SimpleAttributeSet sourceAttrs;
private SimpleAttributeSet offsetAttrSet; private SimpleAttributeSet offsetAttrs;
private SimpleAttributeSet contentAttrSet; private SimpleAttributeSet contentAttrs;
private SimpleAttributeSet fieldNameAttrSet; private SimpleAttributeSet fieldNameAttrs;
private SimpleAttributeSet commentAttrSet; private SimpleAttributeSet commentAttrs;
private SimpleAttributeSet deletedAttrSet; private SimpleAttributeSet deletedAttrs;
DataTypePanel(DataType dataType) { DataTypePanel(DataType dataType) {
super(new BorderLayout()); super(new BorderLayout());
@ -91,58 +90,27 @@ class DataTypePanel extends JPanel {
add(textPane, BorderLayout.CENTER); add(textPane, BorderLayout.CENTER);
textPane.setEditable(false); textPane.setEditable(false);
pathAttrSet = new SimpleAttributeSet(); Font monospaced = Gui.getFont("font.monospaced");
pathAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); Font bold = Gui.getFont("font.standard.bold");
pathAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11));
pathAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE);
pathAttrSet.addAttribute(StyleConstants.Foreground, MergeConstants.CONFLICT_COLOR);
nameAttrSet = new SimpleAttributeSet(); pathAttrs = new GAttributes(bold, MergeConstants.CONFLICT_COLOR);
nameAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); nameAttrs = new GAttributes(bold);
nameAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11)); sourceAttrs = new GAttributes(bold, SOURCE_COLOR);
nameAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE); offsetAttrs = new GAttributes(monospaced, Palette.BLACK);
contentAttrs = new GAttributes(monospaced, Palette.BLUE);
sourceAttrSet = new SimpleAttributeSet(); fieldNameAttrs = new GAttributes(monospaced, Palette.MAGENTA);
sourceAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); commentAttrs = new GAttributes(monospaced, Palette.LIME);
sourceAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11)); deletedAttrs = new GAttributes(bold, Palette.RED);
sourceAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE);
sourceAttrSet.addAttribute(StyleConstants.Foreground, SOURCE_COLOR);
offsetAttrSet = new SimpleAttributeSet();
offsetAttrSet.addAttribute(StyleConstants.FontFamily, "Monospaced");
offsetAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12));
offsetAttrSet.addAttribute(StyleConstants.Foreground, Palette.BLACK);
contentAttrSet = new SimpleAttributeSet();
contentAttrSet.addAttribute(StyleConstants.FontFamily, "Monospaced");
contentAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12));
contentAttrSet.addAttribute(StyleConstants.Foreground, Palette.BLUE);
fieldNameAttrSet = new SimpleAttributeSet();
fieldNameAttrSet.addAttribute(StyleConstants.FontFamily, "Monospaced");
fieldNameAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12));
fieldNameAttrSet.addAttribute(StyleConstants.Foreground, Palette.MAGENTA);
commentAttrSet = new SimpleAttributeSet();
commentAttrSet.addAttribute(StyleConstants.FontFamily, "Monospaced");
commentAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12));
commentAttrSet.addAttribute(StyleConstants.Foreground, Palette.LIME);
deletedAttrSet = new SimpleAttributeSet();
deletedAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma");
deletedAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12));
deletedAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE);
deletedAttrSet.addAttribute(StyleConstants.Foreground, Palette.RED);
setDataType(dataType); setDataType(dataType);
} }
private void formatPath(DataType dt) { private void formatPath(DataType dt) {
insertString("Path: " + dt.getCategoryPath() + "\n\n", pathAttrSet); insertString("Path: " + dt.getCategoryPath() + "\n\n", pathAttrs);
} }
private void formatSourceArchive(DataType dt) { private void formatSourceArchive(DataType dt) {
insertString("Source Archive: " + getSourceArchiveName(dt) + "\n", sourceAttrSet); insertString("Source Archive: " + getSourceArchiveName(dt) + "\n", sourceAttrs);
} }
private String getSourceArchiveName(DataType dt) { private String getSourceArchiveName(DataType dt) {
@ -156,21 +124,21 @@ class DataTypePanel extends JPanel {
private void formatAlignment(Composite composite) { private void formatAlignment(Composite composite) {
String str = CompositeInternal.getAlignmentAndPackingString(composite); String str = CompositeInternal.getAlignmentAndPackingString(composite);
insertString(str + "\n\n", sourceAttrSet); insertString(str + "\n\n", sourceAttrs);
} }
private void insertAlignment(Composite composite) { private void insertAlignment(Composite composite) {
StringBuffer alignmentBuffer = new StringBuffer(); StringBuffer alignmentBuffer = new StringBuffer();
alignmentBuffer.append("Alignment: "); alignmentBuffer.append("Alignment: ");
alignmentBuffer.append(Integer.toString(composite.getAlignment())); alignmentBuffer.append(Integer.toString(composite.getAlignment()));
insertString(alignmentBuffer.toString() + "\n", sourceAttrSet); insertString(alignmentBuffer.toString() + "\n", sourceAttrs);
} }
private void insertLength(Composite composite) { private void insertLength(Composite composite) {
StringBuffer lengthBuffer = new StringBuffer(); StringBuffer lengthBuffer = new StringBuffer();
lengthBuffer.append("Length: "); lengthBuffer.append("Length: ");
lengthBuffer.append(Integer.toString(composite.getLength())); lengthBuffer.append(Integer.toString(composite.getLength()));
insertString(lengthBuffer.toString() + "\n", sourceAttrSet); insertString(lengthBuffer.toString() + "\n", sourceAttrs);
} }
private int max(String str, int length) { private int max(String str, int length) {
@ -184,8 +152,7 @@ class DataTypePanel extends JPanel {
DataType dt = dtc.getDataType(); DataType dt = dtc.getDataType();
StringBuilder buffer = new StringBuilder(); StringBuilder buffer = new StringBuilder();
buffer.append(dt.getName()); buffer.append(dt.getName());
if (dt instanceof BitFieldDataType && if (dt instanceof BitFieldDataType && !((Composite) dtc.getParent()).isPackingEnabled()) {
!((Composite) dtc.getParent()).isPackingEnabled()) {
BitFieldDataType bfDt = (BitFieldDataType) dt; BitFieldDataType bfDt = (BitFieldDataType) dt;
buffer.append("("); buffer.append("(");
buffer.append(Integer.toString(bfDt.getBitOffset())); buffer.append(Integer.toString(bfDt.getBitOffset()));
@ -210,23 +177,23 @@ class DataTypePanel extends JPanel {
offsetStr = "0x" + Integer.toHexString(dtc.getOffset()); offsetStr = "0x" + Integer.toHexString(dtc.getOffset());
offsetStr = StringUtilities.pad(offsetStr, ' ', offsetWidth - offsetStr.length()); offsetStr = StringUtilities.pad(offsetStr, ' ', offsetWidth - offsetStr.length());
offsetStr += ": "; offsetStr += ": ";
insertString(" " + offsetStr + " ", offsetAttrSet); insertString(" " + offsetStr + " ", offsetAttrs);
} }
fieldName = pad(fieldName, fieldNameWidth); fieldName = pad(fieldName, fieldNameWidth);
String typeName = pad(getDataTypeName(dtc), dtNameWidth); String typeName = pad(getDataTypeName(dtc), dtNameWidth);
insertString(" " + typeName + " ", contentAttrSet); insertString(" " + typeName + " ", contentAttrs);
insertString(fieldName + " ", fieldNameAttrSet); insertString(fieldName + " ", fieldNameAttrs);
insertString(comment, commentAttrSet); insertString(comment, commentAttrs);
insertString("\n", contentAttrSet); insertString("\n", contentAttrs);
} }
private void formatCompositeText(Composite comp) { private void formatCompositeText(Composite comp) {
formatSourceArchive(comp); formatSourceArchive(comp);
formatPath(comp); formatPath(comp);
formatAlignment(comp); formatAlignment(comp);
insertString(comp.getDisplayName(), nameAttrSet); insertString(comp.getDisplayName(), nameAttrs);
insertString(" { \n", contentAttrSet); insertString(" { \n", contentAttrs);
boolean showComponentOffset = false; boolean showComponentOffset = false;
@ -247,7 +214,7 @@ class DataTypePanel extends JPanel {
renderComponent(component, maxDtNameLength, maxFieldNameLength, offsetLength); renderComponent(component, maxDtNameLength, maxFieldNameLength, offsetLength);
} }
insertString("}\n\n", contentAttrSet); insertString("}\n\n", contentAttrs);
insertAlignment(comp); insertAlignment(comp);
insertLength(comp); insertLength(comp);
} }
@ -279,8 +246,8 @@ class DataTypePanel extends JPanel {
private void formatEnumText(Enum enuum) { private void formatEnumText(Enum enuum) {
formatSourceArchive(enuum); formatSourceArchive(enuum);
formatPath(enuum); formatPath(enuum);
insertString(enuum.getDisplayName(), nameAttrSet); insertString(enuum.getDisplayName(), nameAttrs);
insertString(" { \n", contentAttrSet); insertString(" { \n", contentAttrs);
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
@ -303,7 +270,7 @@ class DataTypePanel extends JPanel {
renderEnumEntry(entry, maxNameLength, maxValueLength); renderEnumEntry(entry, maxNameLength, maxValueLength);
} }
sb.append("}\n"); sb.append("}\n");
insertString(sb.toString(), contentAttrSet); insertString(sb.toString(), contentAttrs);
} }
private void renderEnumEntry(EnumEntry entry, int maxNameLength, int maxValueLength) { private void renderEnumEntry(EnumEntry entry, int maxNameLength, int maxValueLength) {
@ -311,20 +278,20 @@ class DataTypePanel extends JPanel {
name = pad(name, maxNameLength); name = pad(name, maxNameLength);
String valStr = Long.toHexString(entry.value); String valStr = Long.toHexString(entry.value);
valStr = pad(valStr, maxValueLength); valStr = pad(valStr, maxValueLength);
insertString(" " + name, fieldNameAttrSet); insertString(" " + name, fieldNameAttrs);
insertString(" = 0x" + valStr, contentAttrSet); insertString(" = 0x" + valStr, contentAttrs);
if (entry.comment != null) { if (entry.comment != null) {
insertString(" " + entry.comment, commentAttrSet); insertString(" " + entry.comment, commentAttrs);
} }
insertString("\n", contentAttrSet); insertString("\n", contentAttrs);
} }
private void formatTypeDefText(TypeDef td) { private void formatTypeDefText(TypeDef td) {
formatSourceArchive(td); formatSourceArchive(td);
formatPath(td); formatPath(td);
insertString(td.getDisplayName(), nameAttrSet); insertString(td.getDisplayName(), nameAttrs);
insertString("\n", contentAttrSet); insertString("\n", contentAttrs);
insertString(" TypeDef on " + td.getDataType().getDisplayName(), contentAttrSet); insertString(" TypeDef on " + td.getDataType().getDisplayName(), contentAttrs);
} }
private void formatDataTypeSettings(DataType dt) { private void formatDataTypeSettings(DataType dt) {
@ -336,10 +303,10 @@ class DataTypePanel extends JPanel {
if (defs.length == 0) { if (defs.length == 0) {
return; return;
} }
insertString("\n\nSettings\n", sourceAttrSet); insertString("\n\nSettings\n", sourceAttrs);
for (SettingsDefinition def : defs) { for (SettingsDefinition def : defs) {
insertString(" " + def.getName() + ": " + def.getValueString(settings) + "\n", insertString(" " + def.getName() + ": " + def.getValueString(settings) + "\n",
contentAttrSet); contentAttrs);
} }
} }
@ -350,18 +317,18 @@ class DataTypePanel extends JPanel {
DataType returnType = fd.getReturnType(); DataType returnType = fd.getReturnType();
if (fd.hasNoReturn()) { if (fd.hasNoReturn()) {
insertString(FunctionSignature.NORETURN_DISPLAY_STRING + " ", contentAttrSet); insertString(FunctionSignature.NORETURN_DISPLAY_STRING + " ", contentAttrs);
} }
insertString(returnType.getDisplayName(), contentAttrSet); insertString(returnType.getDisplayName(), contentAttrs);
String callingConventionName = fd.getCallingConventionName(); String callingConventionName = fd.getCallingConventionName();
if (!Function.UNKNOWN_CALLING_CONVENTION_STRING.equals(callingConventionName)) { if (!Function.UNKNOWN_CALLING_CONVENTION_STRING.equals(callingConventionName)) {
insertString(callingConventionName + " ", contentAttrSet); insertString(callingConventionName + " ", contentAttrs);
} }
insertString(" " + fd.getDisplayName(), nameAttrSet); insertString(" " + fd.getDisplayName(), nameAttrs);
insertString(" (", contentAttrSet); insertString(" (", contentAttrs);
boolean hasVarArgs = fd.hasVarArgs(); boolean hasVarArgs = fd.hasVarArgs();
if ((vars.length == 0) && !hasVarArgs) { if ((vars.length == 0) && !hasVarArgs) {
insertString(")", contentAttrSet); insertString(")", contentAttrs);
return; return;
} }
int maxLength = 0; int maxLength = 0;
@ -390,17 +357,17 @@ class DataTypePanel extends JPanel {
sb.append(FunctionSignature.VAR_ARGS_DISPLAY_STRING); sb.append(FunctionSignature.VAR_ARGS_DISPLAY_STRING);
} }
sb.append(")"); sb.append(")");
insertString(sb.toString(), contentAttrSet); insertString(sb.toString(), contentAttrs);
} }
private void formatDataType(DataType dt) { private void formatDataType(DataType dt) {
if (dt == null) { if (dt == null) {
insertString("\n\nDeleted", deletedAttrSet); insertString("\n\nDeleted", deletedAttrs);
return; return;
} }
formatSourceArchive(dt); formatSourceArchive(dt);
formatPath(dt); formatPath(dt);
insertString(dt.getDisplayName(), nameAttrSet); insertString(dt.getDisplayName(), nameAttrs);
} }
private String pad(String str, int length) { private String pad(String str, int length) {

View File

@ -16,13 +16,16 @@
package ghidra.app.merge.datatypes; package ghidra.app.merge.datatypes;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.Font;
import java.util.Date; import java.util.Date;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JTextPane; import javax.swing.JTextPane;
import javax.swing.text.*; import javax.swing.text.*;
import generic.theme.GAttributes;
import generic.theme.GThemeDefaults.Colors.Palette; import generic.theme.GThemeDefaults.Colors.Palette;
import generic.theme.Gui;
import ghidra.program.model.data.ArchiveType; import ghidra.program.model.data.ArchiveType;
import ghidra.program.model.data.SourceArchive; import ghidra.program.model.data.SourceArchive;
import ghidra.util.Msg; import ghidra.util.Msg;
@ -35,9 +38,9 @@ class SourceArchivePanel extends JPanel {
private SourceArchive sourceArchive; private SourceArchive sourceArchive;
private JTextPane textPane; private JTextPane textPane;
private StyledDocument doc; private StyledDocument doc;
private SimpleAttributeSet headingAttrSet; private SimpleAttributeSet headingAttrs;
private SimpleAttributeSet valueAttrSet; private SimpleAttributeSet valueAttrs;
private SimpleAttributeSet deletedAttrSet; private SimpleAttributeSet deletedAttrs;
SourceArchivePanel() { SourceArchivePanel() {
super(new BorderLayout()); super(new BorderLayout());
@ -57,28 +60,19 @@ class SourceArchivePanel extends JPanel {
add(textPane, BorderLayout.CENTER); add(textPane, BorderLayout.CENTER);
textPane.setEditable(false); textPane.setEditable(false);
headingAttrSet = new SimpleAttributeSet(); Font monospaced = Gui.getFont("font.monospaced");
headingAttrSet.addAttribute(StyleConstants.FontFamily, "Monospaced"); Font bold = Gui.getFont("font.standard.bold");
headingAttrSet.addAttribute(StyleConstants.FontSize, 12);
headingAttrSet.addAttribute(StyleConstants.Foreground, Palette.BLUE);
valueAttrSet = new SimpleAttributeSet(); headingAttrs = new GAttributes(monospaced, Palette.BLUE);
valueAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); valueAttrs = new GAttributes(bold);
valueAttrSet.addAttribute(StyleConstants.FontSize, 11); deletedAttrs = new GAttributes(bold, Palette.RED);
valueAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE);
deletedAttrSet = new SimpleAttributeSet();
deletedAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma");
deletedAttrSet.addAttribute(StyleConstants.FontSize, 12);
deletedAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE);
deletedAttrSet.addAttribute(StyleConstants.Foreground, Palette.RED);
setSourceArchive(null); setSourceArchive(null);
} }
private void formatSourceArchive() { private void formatSourceArchive() {
if (sourceArchive == null) { if (sourceArchive == null) {
insertString("\n\nDeleted", deletedAttrSet); insertString("\n\nDeleted", deletedAttrs);
return; return;
} }
// formatArchiveID(); // formatArchiveID();
@ -91,19 +85,19 @@ class SourceArchivePanel extends JPanel {
@SuppressWarnings("unused") @SuppressWarnings("unused")
private void formatArchiveID() { private void formatArchiveID() {
insertString(" Archive ID: ", headingAttrSet); insertString(" Archive ID: ", headingAttrs);
insertString(sourceArchive.getSourceArchiveID().getValue() + "\n", valueAttrSet); insertString(sourceArchive.getSourceArchiveID().getValue() + "\n", valueAttrs);
} }
private void formatName() { private void formatName() {
insertString("Name: ", headingAttrSet); insertString("Name: ", headingAttrs);
insertString(sourceArchive.getName() + "\n", valueAttrSet); insertString(sourceArchive.getName() + "\n", valueAttrs);
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")
private void formatFileID() { private void formatFileID() {
insertString(" File ID: ", headingAttrSet); insertString(" File ID: ", headingAttrs);
insertString(sourceArchive.getDomainFileID() + "\n", valueAttrSet); insertString(sourceArchive.getDomainFileID() + "\n", valueAttrs);
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")
@ -112,21 +106,20 @@ class SourceArchivePanel extends JPanel {
String typeString = (archiveType == ArchiveType.FILE) ? "File Archive" String typeString = (archiveType == ArchiveType.FILE) ? "File Archive"
: (archiveType == ArchiveType.PROGRAM) ? "Program" : (archiveType == ArchiveType.PROGRAM) ? "Program"
: (archiveType == ArchiveType.PROJECT) ? "Project Archive" : (archiveType == ArchiveType.PROJECT) ? "Project Archive"
: (archiveType == ArchiveType.BUILT_IN) ? "Built-In" : (archiveType == ArchiveType.BUILT_IN) ? "Built-In" : "Invalid";
: "Invalid"; insertString(" Type: ", headingAttrs);
insertString(" Type: ", headingAttrSet); insertString(typeString + "\n", valueAttrs);
insertString(typeString + "\n", valueAttrSet);
} }
private void formatSyncTime() { private void formatSyncTime() {
String syncTime = new Date(sourceArchive.getLastSyncTime()).toString(); String syncTime = new Date(sourceArchive.getLastSyncTime()).toString();
insertString("Last Sync Time: ", headingAttrSet); insertString("Last Sync Time: ", headingAttrs);
insertString(syncTime + "\n", valueAttrSet); insertString(syncTime + "\n", valueAttrs);
} }
private void formatDirtyFlag() { private void formatDirtyFlag() {
insertString("Changed Since Last Sync? ", headingAttrSet); insertString("Changed Since Last Sync? ", headingAttrs);
insertString((sourceArchive.isDirty() ? "yes" : "no") + "\n", valueAttrSet); insertString((sourceArchive.isDirty() ? "yes" : "no") + "\n", valueAttrs);
} }
private void insertString(String str, SimpleAttributeSet attributeSet) { private void insertString(String str, SimpleAttributeSet attributeSet) {

View File

@ -24,13 +24,14 @@ import docking.widgets.label.GIconLabel;
import generic.theme.GIcon; import generic.theme.GIcon;
import generic.theme.GThemeDefaults.Colors; import generic.theme.GThemeDefaults.Colors;
import generic.theme.GThemeDefaults.Colors.Messages; import generic.theme.GThemeDefaults.Colors.Messages;
import generic.theme.Gui;
import ghidra.util.layout.PairLayout; import ghidra.util.layout.PairLayout;
import resources.Icons; import resources.Icons;
/** /**
* Panel to show whether tree name and tree structure changed. * Panel to show whether tree name and tree structure changed.
* *
* *
*/ */
class TreeChangePanel extends JPanel { class TreeChangePanel extends JPanel {
@ -74,9 +75,7 @@ class TreeChangePanel extends JPanel {
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
treeNameLabel = new GDLabel("Tree Name"); treeNameLabel = new GDLabel("Tree Name");
Font font = treeNameLabel.getFont(); Gui.registerFont(treeNameLabel, Font.BOLD);
font = font.deriveFont(Font.BOLD);
treeNameLabel.setFont(font);
nameLabel = new GDLabel("Name Changed"); nameLabel = new GDLabel("Name Changed");
nameIconLabel = new GIconLabel(CHANGED_ICON); nameIconLabel = new GIconLabel(CHANGED_ICON);

View File

@ -27,8 +27,8 @@ import ghidra.util.Msg;
/** /**
* Panel that shows the current conflict number and the total number of * Panel that shows the current conflict number and the total number of
* conflicts. * conflicts.
* *
* *
*/ */
public class ConflictCountPanel extends JPanel { public class ConflictCountPanel extends JPanel {
@ -87,7 +87,6 @@ public class ConflictCountPanel extends JPanel {
set.addAttribute(StyleConstants.Foreground, Messages.ERROR); set.addAttribute(StyleConstants.Foreground, Messages.ERROR);
textAttrSet = new SimpleAttributeSet(); textAttrSet = new SimpleAttributeSet();
textAttrSet.addAttribute(StyleConstants.FontSize, 12);
countAttrSet = new SimpleAttributeSet(); countAttrSet = new SimpleAttributeSet();
countAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE); countAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE);

View File

@ -22,6 +22,7 @@ import javax.swing.*;
import docking.widgets.label.GDLabel; import docking.widgets.label.GDLabel;
import generic.theme.GThemeDefaults.Colors; import generic.theme.GThemeDefaults.Colors;
import generic.theme.Gui;
import ghidra.framework.options.CustomOptionsEditor; import ghidra.framework.options.CustomOptionsEditor;
import ghidra.util.layout.PairLayout; import ghidra.util.layout.PairLayout;
@ -109,7 +110,7 @@ public class StoredAnalyzerTimesPropertyEditor extends PropertyEditorSupport
} }
label = new GDLabel("TOTAL", SwingConstants.RIGHT); label = new GDLabel("TOTAL", SwingConstants.RIGHT);
label.setFont(label.getFont().deriveFont(Font.BOLD)); Gui.registerFont(label, Font.BOLD);
panel.add(label); panel.add(label);
JTextField valueField = JTextField valueField =

View File

@ -25,6 +25,7 @@ import docking.widgets.OptionDialog;
import docking.widgets.filechooser.GhidraFileChooser; import docking.widgets.filechooser.GhidraFileChooser;
import docking.widgets.filechooser.GhidraFileChooserMode; import docking.widgets.filechooser.GhidraFileChooserMode;
import docking.widgets.label.GDLabel; import docking.widgets.label.GDLabel;
import generic.theme.Gui;
import ghidra.framework.GenericRunInfo; import ghidra.framework.GenericRunInfo;
import ghidra.framework.model.ProjectLocator; import ghidra.framework.model.ProjectLocator;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
@ -91,8 +92,8 @@ public class ArchiveDialog extends ReusableDialogComponentProvider {
archiveField.setText(archivePathName); archiveField.setText(archivePathName);
} }
}); });
Font font = archiveBrowse.getFont();
archiveBrowse.setFont(font.deriveFont(Font.BOLD)); Gui.registerFont(archiveBrowse, Font.BOLD);
archiveBrowse.setName("archiveBrowse"); archiveBrowse.setName("archiveBrowse");
// Layout the components. // Layout the components.
@ -179,7 +180,7 @@ public class ArchiveDialog extends ReusableDialogComponentProvider {
* @param pArchivePathName the archive file name to display when the dialog pops up. * @param pArchivePathName the archive file name to display when the dialog pops up.
* @param tool the tool * @param tool the tool
* *
* @return true if the user submitted valid values for the project and * @return true if the user submitted valid values for the project and
* archive file, false if user cancelled. * archive file, false if user cancelled.
*/ */
public boolean showDialog(ProjectLocator pProjectLocator, String pArchivePathName, public boolean showDialog(ProjectLocator pProjectLocator, String pArchivePathName,
@ -222,7 +223,7 @@ public class ArchiveDialog extends ReusableDialogComponentProvider {
///////////////////////////////////////////// /////////////////////////////////////////////
/** /**
* Check the entry to determine if the user input is valid for archiving * Check the entry to determine if the user input is valid for archiving
* a project. * a project.
* *
* @return boolean true if input is OK * @return boolean true if input is OK
@ -269,8 +270,7 @@ public class ArchiveDialog extends ReusableDialogComponentProvider {
return file.getAbsolutePath() return file.getAbsolutePath()
.toLowerCase() .toLowerCase()
.endsWith( .endsWith(ArchivePlugin.ARCHIVE_EXTENSION);
ArchivePlugin.ARCHIVE_EXTENSION);
} }
@Override @Override
@ -302,7 +302,7 @@ public class ArchiveDialog extends ReusableDialogComponentProvider {
} }
/** /**
* Brings up a file chooser for the user to specify a directory and * Brings up a file chooser for the user to specify a directory and
* filename of the archive file. * filename of the archive file.
* @param approveButtonText The label for the "Open" button on the file chooser * @param approveButtonText The label for the "Open" button on the file chooser
* @param approveToolTip The tool tip for the "Open" button on the file chooser * @param approveToolTip The tool tip for the "Open" button on the file chooser
@ -311,8 +311,7 @@ public class ArchiveDialog extends ReusableDialogComponentProvider {
private String chooseArchiveFile(String approveButtonText, String approveToolTip) { private String chooseArchiveFile(String approveButtonText, String approveToolTip) {
GhidraFileChooser jarFileChooser = GhidraFileChooser jarFileChooser =
createFileChooser(ArchivePlugin.ARCHIVE_EXTENSION, "Ghidra Archives", createFileChooser(ArchivePlugin.ARCHIVE_EXTENSION, "Ghidra Archives", archivePathName);
archivePathName);
jarFileChooser.setTitle("Archive a Ghidra Project"); jarFileChooser.setTitle("Archive a Ghidra Project");
File jarFile = null; File jarFile = null;
if (archivePathName != null && archivePathName.length() != 0) { if (archivePathName != null && archivePathName.length() != 0) {

View File

@ -26,6 +26,7 @@ import docking.ReusableDialogComponentProvider;
import docking.widgets.filechooser.GhidraFileChooser; import docking.widgets.filechooser.GhidraFileChooser;
import docking.widgets.filechooser.GhidraFileChooserMode; import docking.widgets.filechooser.GhidraFileChooserMode;
import docking.widgets.label.GDLabel; import docking.widgets.label.GDLabel;
import generic.theme.Gui;
import ghidra.framework.GenericRunInfo; import ghidra.framework.GenericRunInfo;
import ghidra.framework.model.ProjectLocator; import ghidra.framework.model.ProjectLocator;
import ghidra.framework.preferences.Preferences; import ghidra.framework.preferences.Preferences;
@ -33,7 +34,7 @@ import ghidra.util.*;
import ghidra.util.filechooser.ExtensionFileFilter; import ghidra.util.filechooser.ExtensionFileFilter;
/** /**
* Dialog to prompt the user for the archive file to restore * Dialog to prompt the user for the archive file to restore
* and where to restore it to. * and where to restore it to.
*/ */
public class RestoreDialog extends ReusableDialogComponentProvider { public class RestoreDialog extends ReusableDialogComponentProvider {
@ -112,8 +113,8 @@ public class RestoreDialog extends ReusableDialogComponentProvider {
} }
} }
}); });
Font font = archiveBrowse.getFont();
archiveBrowse.setFont(font.deriveFont(Font.BOLD)); Gui.registerFont(archiveBrowse, Font.BOLD);
restoreLabel = new GDLabel(" Restore Directory "); restoreLabel = new GDLabel(" Restore Directory ");
restoreField = new JTextField(); restoreField = new JTextField();
@ -129,8 +130,8 @@ public class RestoreDialog extends ReusableDialogComponentProvider {
restoreField.setText(dirPath); restoreField.setText(dirPath);
} }
}); });
font = restoreBrowse.getFont();
restoreBrowse.setFont(font.deriveFont(Font.BOLD)); Gui.registerFont(restoreBrowse, Font.BOLD);
projectNameLabel = new GDLabel(" Project Name "); projectNameLabel = new GDLabel(" Project Name ");
projectNameField = new JTextField(); projectNameField = new JTextField();
@ -365,7 +366,7 @@ public class RestoreDialog extends ReusableDialogComponentProvider {
} }
/** /**
* Creates a directory chooser for selecting the directory where the * Creates a directory chooser for selecting the directory where the
* archive will be restored.. * archive will be restored..
* @return the file chooser. * @return the file chooser.
*/ */
@ -380,7 +381,7 @@ public class RestoreDialog extends ReusableDialogComponentProvider {
} }
/** /**
* Brings up a file chooser for the user to specify a directory and * Brings up a file chooser for the user to specify a directory and
* filename that are used for the Project location and name * filename that are used for the Project location and name
* @param approveButtonText The label for the "Open" button on the file chooser * @param approveButtonText The label for the "Open" button on the file chooser
* @param approveToolTip The tool tip for the "Open" button on the file chooser * @param approveToolTip The tool tip for the "Open" button on the file chooser
@ -389,8 +390,7 @@ public class RestoreDialog extends ReusableDialogComponentProvider {
String chooseArchiveFile(String approveButtonText, String approveToolTip) { String chooseArchiveFile(String approveButtonText, String approveToolTip) {
GhidraFileChooser jarFileChooser = GhidraFileChooser jarFileChooser =
createFileChooser(ArchivePlugin.ARCHIVE_EXTENSION, "Ghidra Archives", createFileChooser(ArchivePlugin.ARCHIVE_EXTENSION, "Ghidra Archives", archivePathName);
archivePathName);
jarFileChooser.setTitle("Restore a Ghidra Project - Archive"); jarFileChooser.setTitle("Restore a Ghidra Project - Archive");
String lastDirSelected = Preferences.getProperty(ArchivePlugin.LAST_ARCHIVE_DIR); String lastDirSelected = Preferences.getProperty(ArchivePlugin.LAST_ARCHIVE_DIR);
if (lastDirSelected != null) { if (lastDirSelected != null) {

View File

@ -16,12 +16,13 @@
package ghidra.app.plugin.core.comments; package ghidra.app.plugin.core.comments;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.Font;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JTextPane; import javax.swing.JTextPane;
import javax.swing.text.*; import javax.swing.text.*;
import generic.theme.GColor; import generic.theme.*;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.listing.CommentHistory; import ghidra.program.model.listing.CommentHistory;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
@ -36,8 +37,8 @@ import ghidra.util.Msg;
class CommentHistoryPanel extends JPanel { class CommentHistoryPanel extends JPanel {
private final static String NO_HISTORY = "No History Found"; private final static String NO_HISTORY = "No History Found";
private SimpleAttributeSet userAttrSet; private SimpleAttributeSet userAttrs;
private SimpleAttributeSet dateAttrSet; private SimpleAttributeSet dateAttrs;
private SimpleAttributeSet textAttrSet; private SimpleAttributeSet textAttrSet;
private SimpleAttributeSet tabAttrSet; private SimpleAttributeSet tabAttrSet;
@ -47,7 +48,7 @@ class CommentHistoryPanel extends JPanel {
private int commentType; private int commentType;
/** /**
* Construct a new CommentHistoryPanel * Construct a new CommentHistoryPanel
* @param commentType comment type * @param commentType comment type
*/ */
CommentHistoryPanel(int commentType) { CommentHistoryPanel(int commentType) {
@ -60,7 +61,7 @@ class CommentHistoryPanel extends JPanel {
/** /**
* Show the comment history * Show the comment history
* @param program program * @param program program
* @param addr address of comment history * @param addr address of comment history
*/ */
void showCommentHistory(Program program, Address addr) { void showCommentHistory(Program program, Address addr) {
@ -100,11 +101,11 @@ class CommentHistoryPanel extends JPanel {
if (offset > 0) { if (offset > 0) {
userName = "\n" + userName; userName = "\n" + userName;
} }
doc.insertString(offset, userName, userAttrSet); doc.insertString(offset, userName, userAttrs);
offset = doc.getLength(); offset = doc.getLength();
doc.insertString(offset, doc.insertString(offset,
"\t" + DateUtils.formatDateTimestamp(history.getModificationDate()), dateAttrSet); "\t" + DateUtils.formatDateTimestamp(history.getModificationDate()), dateAttrs);
doc.setParagraphAttributes(offset, 1, tabAttrSet, false); doc.setParagraphAttributes(offset, 1, tabAttrSet, false);
offset = doc.getLength(); offset = doc.getLength();
@ -112,25 +113,13 @@ class CommentHistoryPanel extends JPanel {
} }
private void setUpAttributes() { 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(); Font bold = Gui.getFont("font.standard.bold");
userAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); Font monospaced = Gui.getFont("font.monospaced");
userAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(12)); textAttrSet =
userAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE); new GAttributes(monospaced, new GColor("color.fg.plugin.comments.history.text"));
userAttrSet.addAttribute(StyleConstants.Foreground, userAttrs = new GAttributes(bold, new GColor("color.fg.plugin.comments.history.user"));
new GColor("color.fg.plugin.comments.history.user")); dateAttrs = new GAttributes(bold, new GColor("color.fg.plugin.comments.history.date"));
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"));
tabAttrSet = new SimpleAttributeSet(); tabAttrSet = new SimpleAttributeSet();
TabStop tabs = new TabStop(100, StyleConstants.ALIGN_LEFT, TabStop.LEAD_NONE); TabStop tabs = new TabStop(100, StyleConstants.ALIGN_LEFT, TabStop.LEAD_NONE);

View File

@ -39,6 +39,7 @@ import docking.widgets.pathmanager.PathnameTablePanel;
import docking.widgets.table.GTableCellRenderer; import docking.widgets.table.GTableCellRenderer;
import docking.widgets.table.GTableCellRenderingData; import docking.widgets.table.GTableCellRenderingData;
import generic.jar.ResourceFile; import generic.jar.ResourceFile;
import generic.theme.Gui;
import ghidra.app.plugin.core.processors.SetLanguageDialog; import ghidra.app.plugin.core.processors.SetLanguageDialog;
import ghidra.app.util.cparser.C.CParserUtils; import ghidra.app.util.cparser.C.CParserUtils;
import ghidra.framework.Application; import ghidra.framework.Application;
@ -371,8 +372,7 @@ class ParseDialog extends ReusableDialogComponentProvider {
updateArchitectureDescription(); updateArchitectureDescription();
languageButton.setName("Set Processor Architecture"); languageButton.setName("Set Processor Architecture");
Font font = languageButton.getFont(); Gui.registerFont(languageButton, Font.BOLD);
languageButton.setFont(font.deriveFont(Font.BOLD));
JPanel panel = new JPanel(new BorderLayout()); JPanel panel = new JPanel(new BorderLayout());
panel.add(languageTextField, BorderLayout.CENTER); panel.add(languageTextField, BorderLayout.CENTER);

View File

@ -246,8 +246,6 @@ public class FunctionEditorDialog extends DialogComponentProvider implements Mod
signatureFieldUndoRedoKeeper = DockingUtils.installUndoRedo(signatureTextField); signatureFieldUndoRedoKeeper = DockingUtils.installUndoRedo(signatureTextField);
Font font = signatureTextField.getFont();
signatureTextField.setFont(font.deriveFont(18.0f));
panel.add(signatureTextField); panel.add(signatureTextField);
signatureTextField.setEscapeListener(e -> { signatureTextField.setEscapeListener(e -> {

View File

@ -15,7 +15,8 @@
*/ */
package ghidra.app.plugin.core.function.editor; package ghidra.app.plugin.core.function.editor;
import java.awt.*; import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.*; import java.awt.event.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -26,12 +27,16 @@ import javax.swing.text.*;
import docking.actions.KeyBindingUtils; import docking.actions.KeyBindingUtils;
import generic.theme.GColor; import generic.theme.GColor;
import generic.theme.Gui;
import ghidra.util.Swing; import ghidra.util.Swing;
class FunctionSignatureTextField extends JTextPane { class FunctionSignatureTextField extends JTextPane {
private static final String ENTER_ACTION_NAME = "ENTER"; private static final String ENTER_ACTION_NAME = "ENTER";
private static final String ESCAPE_ACTION_NAME = "ESCAPE"; private static final String ESCAPE_ACTION_NAME = "ESCAPE";
private static final String TAB_ACTION_NAME = "TAB"; private static final String TAB_ACTION_NAME = "TAB";
private static final String FONT_ID = "font.plugin.function.text.editor";
public static Color DEFAULT_COLOR = public static Color DEFAULT_COLOR =
new GColor("color.fg.plugin.function.editor.dialog.textfield.default"); new GColor("color.fg.plugin.function.editor.dialog.textfield.default");
public static Color PARAMETER_NAME_COLOR = public static Color PARAMETER_NAME_COLOR =
@ -52,8 +57,7 @@ class FunctionSignatureTextField extends JTextPane {
private SimpleAttributeSet errorAttributes; private SimpleAttributeSet errorAttributes;
FunctionSignatureTextField() { FunctionSignatureTextField() {
Font myFont = getFont(); Gui.registerFont(this, FONT_ID);
setFont(myFont.deriveFont(24.0f));
doc = getStyledDocument(); doc = getStyledDocument();
AttributeSet inputAttributes = getInputAttributes(); AttributeSet inputAttributes = getInputAttributes();

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package docking.widgets.textarea; package ghidra.app.plugin.core.instructionsearch.ui;
import java.awt.*; import java.awt.*;
@ -23,8 +23,8 @@ import generic.theme.GThemeDefaults.Colors;
import generic.theme.GThemeDefaults.Colors.Messages; 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 * Hint text will be shown in light grey, italicized, and in angle brackets. Normal text will
* be plain black. * be plain black.
*/ */
@ -34,7 +34,7 @@ public class HintTextArea extends JTextArea {
/** /**
* Constructs the class with the hint text to be shown. * Constructs the class with the hint text to be shown.
* *
* @param hint the hint * @param hint the hint
*/ */
public HintTextArea(String 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 * @param text the text
*/ */
@Override @Override
@ -74,7 +74,27 @@ public class HintTextArea extends JTextArea {
* Sets the text attributes to be used when NOT viewing the hint. * Sets the text attributes to be used when NOT viewing the hint.
*/ */
protected void setAttributes() { protected void setAttributes() {
this.setFont(getFont().deriveFont(Font.PLAIN));
setForeground(Colors.FOREGROUND); 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();
}
} }

View File

@ -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.
* <p>
* 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);
}
}

View File

@ -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 input text area. This is a generic JTextArea but displays a textual 'hint' to inform
// the user of what type of input is required. // the user of what type of input is required.
private HintTextAreaIS inputBytesTA; private HintTextArea inputBytesTA;
private SelectionModeWidget selectionModeWidget; private SelectionModeWidget selectionModeWidget;
private EndianFlipWidget endianFlipWidget; private EndianFlipWidget endianFlipWidget;
@ -79,7 +79,7 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement
/** /**
* Constructor. * Constructor.
* *
* @param program the current program * @param program the current program
* @param dialog the parent search dialog * @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 * Load a set of bytes (in string form; hex or binary) into the search
* dialog. The bytes are disassembled and displayed in the * dialog. The bytes are disassembled and displayed in the
* {@link InstructionTable}. * {@link InstructionTable}.
* *
* @param bytes the bytes to load * @param bytes the bytes to load
*/ */
public void loadBytes(String bytes) { public void loadBytes(String bytes) {
@ -139,7 +139,7 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement
/** /**
* Creates the visual components for this dialog. * Creates the visual components for this dialog.
* *
* @return the new panel * @return the new panel
*/ */
protected JPanel createWorkPanel() { protected JPanel createWorkPanel() {
@ -148,7 +148,7 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement
contentPanel.setMinimumSize(new Dimension(500, 300)); contentPanel.setMinimumSize(new Dimension(500, 300));
// Create the input text widget and give it a scrollbar. // 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); JScrollPane scrollPane = new JScrollPane(inputBytesTA);
inputBytesTA.addKeyListener(this); inputBytesTA.addKeyListener(this);
@ -188,7 +188,7 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement
msgPanel.clear(); msgPanel.clear();
// When bringing up the dialog, always populate it with whatever is in the main dialog so // 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. // 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 // 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<Byte> allBytes = InstructionSearchUtils.toByteArray(input); List<Byte> allBytes = InstructionSearchUtils.toByteArray(input);
// Now we have a valid byte string so we can start disassembling. To do this, we pass // 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 // 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... // 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. // once, not just one instruction at a time.
// //
// NOTE: Some instructions have operands that cannot be accurately calculated // 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 // 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; // 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 // 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 // might represent. In these cases we just use the minimum address of the loaded
// program as the base address. // program as the base address.
List<InstructionMetadata> instructions = new ArrayList<>(); List<InstructionMetadata> instructions = new ArrayList<>();
@ -272,7 +272,7 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement
while (allBytes.size() > 0) { while (allBytes.size() > 0) {
try { 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()]; Byte[] bytearray = new Byte[allBytes.size()];
bytearray = allBytes.toArray(bytearray); bytearray = allBytes.toArray(bytearray);
@ -318,10 +318,10 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement
/** /**
* Creates {@link OperandMetadata} objects for each operand in the * Creates {@link OperandMetadata} objects for each operand in the
* instruction provided. * instruction provided.
* *
* @param instruction the instruction to parse * @param instruction the instruction to parse
* @return list of operand metadata * @return list of operand metadata
* @throws MemoryAccessException * @throws MemoryAccessException if there is an exception getting instruction bytes
*/ */
private List<OperandMetadata> createOperandMetadata(PseudoInstruction instruction) private List<OperandMetadata> createOperandMetadata(PseudoInstruction instruction)
throws MemoryAccessException { throws MemoryAccessException {
@ -334,7 +334,7 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement
operandMD.setOpType(instruction.getOperandType(i)); operandMD.setOpType(instruction.getOperandType(i));
operandMD.setTextRep(instruction.getDefaultOperandRepresentation(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 // 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 // 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. // 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 * Creates a {@link InstructionMetadata} object for the instruction
* provided. * provided.
* *
* @param instruction the instruction to parse * @param instruction the instruction to parse
* @return the instruction metadata * @return the instruction metadata
* @throws MemoryAccessException * @throws MemoryAccessException if there is an exception getting instruction bytes
*/ */
private InstructionMetadata createInstructionMetadata(PseudoInstruction instruction) private InstructionMetadata createInstructionMetadata(PseudoInstruction instruction)
throws MemoryAccessException { 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 // have to figure out which bits pertain to operands and just zero them out, so we're
// just left with the instruction (mnemonic) bits. // just left with the instruction (mnemonic) bits.
InstructionPrototype prototype = instruction.getPrototype(); InstructionPrototype prototype = instruction.getPrototype();
@ -387,7 +387,7 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement
* <li>value = 01101100 10001110</li> * <li>value = 01101100 10001110</li>
* <li>--------------------------</li> * <li>--------------------------</li>
* <li>ret = 01101000 10000000</li> * <li>ret = 01101000 10000000</li>
* *
* @param mask the mnemonic mask * @param mask the mnemonic mask
* @param value the full instruction value string * @param value the full instruction value string
* @return the cleared byte array * @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: * Verifies that the input entered by the user is valid. Meaning:
* <li>The string represents a hex or binary number.</li> * <li>The string represents a hex or binary number.</li>
* <li>The string contains only full bytes.</li> * <li>The string contains only full bytes.</li>
* *
* @return true if input is valid * @return true if input is valid
*/ */
public boolean validateInput() { public boolean validateInput() {
@ -409,7 +409,7 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement
/** /**
* Verifies that the given string is valid binary or hex input. * Verifies that the given string is valid binary or hex input.
* *
* @param input the string to validate * @param input the string to validate
* @return true if valid * @return true if valid
*/ */
@ -480,7 +480,7 @@ public class InsertBytesWidget extends ReusableDialogComponentProvider implement
/** /**
* Flags the given string as invalid input * Flags the given string as invalid input
* *
*/ */
public void setInputInvalid() { public void setInputInvalid() {
inputBytesTA.setError(); 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 * 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. * 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 * 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 * handler the input widget has not officially been updated with the new
* character. * character.
* *
* @param e * @param e the event
*/ */
@Override @Override
public void keyReleased(KeyEvent e) { public void keyReleased(KeyEvent e) {

View File

@ -17,8 +17,8 @@ package ghidra.app.plugin.core.instructionsearch.ui;
import java.awt.*; import java.awt.*;
import javax.swing.*; import javax.swing.JLabel;
import javax.swing.table.TableModel; import javax.swing.SwingConstants;
import docking.widgets.table.GTableCellRenderingData; import docking.widgets.table.GTableCellRenderingData;
import generic.theme.Gui; import generic.theme.Gui;
@ -45,20 +45,12 @@ public class InstructionTableCellRenderer extends GhidraTableCellRenderer {
public Component getTableCellRendererComponent(GTableCellRenderingData data) { public Component getTableCellRendererComponent(GTableCellRenderingData data) {
Object value = data.getValue(); Object value = data.getValue();
JTable table = data.getTable();
int column = data.getColumnViewIndex();
boolean isSelected = data.isSelected(); boolean isSelected = data.isSelected();
boolean hasFocus = data.hasFocus(); 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) { if (value == null) {
return this; return this;
} }
// Get the data object backing the cell.
InstructionTableDataObject dataObject = (InstructionTableDataObject) value; InstructionTableDataObject dataObject = (InstructionTableDataObject) value;
String strData = dataObject.getData(); String strData = dataObject.getData();
@ -66,7 +58,7 @@ public class InstructionTableCellRenderer extends GhidraTableCellRenderer {
JLabel theRenderer = (JLabel) super.getTableCellRendererComponent(renderData); JLabel theRenderer = (JLabel) super.getTableCellRendererComponent(renderData);
setTextAttributes(table, value, column); setTextAttributes();
setBackgroundAttributes(isSelected, hasFocus, dataObject); setBackgroundAttributes(isSelected, hasFocus, dataObject);
setBorderAttributes(dataObject, theRenderer); setBorderAttributes(dataObject, theRenderer);
setForegroundAttributes(dataObject, theRenderer); setForegroundAttributes(dataObject, theRenderer);
@ -80,8 +72,6 @@ public class InstructionTableCellRenderer extends GhidraTableCellRenderer {
private void setForegroundAttributes(InstructionTableDataObject dataObject, private void setForegroundAttributes(InstructionTableDataObject dataObject,
JLabel theRenderer) { 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()); theRenderer.setForeground(dataObject.getForegroundColor());
Font newFont = theRenderer.getFont().deriveFont(dataObject.getFontStyle()); Font newFont = theRenderer.getFont().deriveFont(dataObject.getFontStyle());
theRenderer.setFont(newFont); theRenderer.setFont(newFont);
@ -89,8 +79,6 @@ public class InstructionTableCellRenderer extends GhidraTableCellRenderer {
private void setBackgroundAttributes(boolean isSelected, boolean hasFocus, private void setBackgroundAttributes(boolean isSelected, boolean hasFocus,
InstructionTableDataObject dataObject) { 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(); Color backgroundColor = dataObject.getBackgroundColor();
if (backgroundColor != null) { if (backgroundColor != null) {
if (isSelected || hasFocus) { 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); setHorizontalAlignment(SwingConstants.LEFT);
TableModel model = table.getModel(); setFont(getDefaultFont());
configureFont(table, model, col);
setOpaque(true); setOpaque(true);
} }
} }

View File

@ -26,6 +26,7 @@ import javax.swing.event.ListDataListener;
import docking.widgets.list.GListCellRenderer; import docking.widgets.list.GListCellRenderer;
import generic.theme.GThemeDefaults.Colors.Tooltips; import generic.theme.GThemeDefaults.Colors.Tooltips;
import generic.theme.Gui;
import generic.util.WindowUtilities; import generic.util.WindowUtilities;
import ghidra.app.plugin.core.console.CodeCompletion; import ghidra.app.plugin.core.console.CodeCompletion;
@ -34,23 +35,25 @@ import ghidra.app.plugin.core.console.CodeCompletion;
*/ */
public class CodeCompletionWindow extends JDialog { public class CodeCompletionWindow extends JDialog {
private static final String FONT_ID = "font.plugin.terminal.completion.list";
protected final InterpreterPanel console; protected final InterpreterPanel console;
protected final JTextPane outputTextField; protected final JTextPane outputTextField;
/* List of CodeCompletions. /* List of CodeCompletions.
* If the substitution value is null, then that attribute will not be * If the substitution value is null, then that attribute will not be
* selectable for substitution. * selectable for substitution.
*/ */
protected List<CodeCompletion> completion_list; protected List<CodeCompletion> completionData;
/* current list of completions */ /* current list of completions */
protected JList jlist; protected JList<CodeCompletion> jlist;
public CodeCompletionWindow(Window parent, InterpreterPanel cp, JTextPane textField) { public CodeCompletionWindow(Window parent, InterpreterPanel cp, JTextPane textField) {
super(parent); super(parent);
this.console = cp; this.console = cp;
outputTextField = textField; outputTextField = textField;
jlist = new JList(); jlist = new JList<>();
completion_list = null; completionData = null;
setUndecorated(true); setUndecorated(true);
/* don't steal focus from text input! */ /* don't steal focus from text input! */
@ -58,14 +61,14 @@ public class CodeCompletionWindow extends JDialog {
jlist.setBackground(Tooltips.BACKGROUND); jlist.setBackground(Tooltips.BACKGROUND);
jlist.setCellRenderer(new CodeCompletionListCellRenderer()); 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() { MouseListener mouseListener = new MouseAdapter() {
@Override @Override
public void mouseClicked(MouseEvent e) { public void mouseClicked(MouseEvent e) {
/* when the user clicks the popup window, make sure // when the user clicks the popup window, make sure that the outputTextField gets
* that the outputTextField gets the focus (so that the escape // the focus (so that the escape key and other hotkeys to manage the popup work
* key and other hotkeys to manage the popup work correctly // correctly
*/
outputTextField.requestFocusInWindow(); outputTextField.requestFocusInWindow();
/* double-click inserts a completion */ /* double-click inserts a completion */
if (e.getClickCount() == 2) { if (e.getClickCount() == 2) {
@ -74,9 +77,9 @@ public class CodeCompletionWindow extends JDialog {
} }
}; };
jlist.addMouseListener(mouseListener); jlist.addMouseListener(mouseListener);
/* actually put the components together */
getContentPane().add(new JScrollPane(jlist)); getContentPane().add(new JScrollPane(jlist));
updateCompletionList(completion_list); updateCompletionList(completionData);
jlist.addKeyListener(new KeyAdapter() { jlist.addKeyListener(new KeyAdapter() {
@Override @Override
@ -121,7 +124,7 @@ public class CodeCompletionWindow extends JDialog {
* @param list List of code completions * @param list List of code completions
*/ */
public void updateCompletionList(List<CodeCompletion> list) { public void updateCompletionList(List<CodeCompletion> list) {
completion_list = list; completionData = list;
jlist.setModel(new CodeCompletionListModel(list)); jlist.setModel(new CodeCompletionListModel(list));
jlist.setSelectionModel(new CodeCompletionListSelectionModel(list)); jlist.setSelectionModel(new CodeCompletionListSelectionModel(list));
jlist.clearSelection(); jlist.clearSelection();
@ -247,7 +250,7 @@ public class CodeCompletionWindow extends JDialog {
*/ */
@Override @Override
public void setFont(Font font) { 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() { public void selectPrevious() {
for (int i = jlist.getSelectedIndex() - 1; i >= 0; i--) { for (int i = jlist.getSelectedIndex() - 1; i >= 0; i--) {
CodeCompletion completion = completion_list.get(i); CodeCompletion completion = completionData.get(i);
if (CodeCompletion.isValid(completion)) { if (CodeCompletion.isValid(completion)) {
jlist.setSelectedIndex(i); jlist.setSelectedIndex(i);
jlist.ensureIndexIsVisible(i); jlist.ensureIndexIsVisible(i);
@ -271,11 +274,11 @@ public class CodeCompletionWindow extends JDialog {
*/ */
public void selectNext() { public void selectNext() {
if (null == completion_list) { if (null == completionData) {
return; return;
} }
for (int i = jlist.getSelectedIndex() + 1; i < completion_list.size(); i++) { for (int i = jlist.getSelectedIndex() + 1; i < completionData.size(); i++) {
CodeCompletion completion = completion_list.get(i); CodeCompletion completion = completionData.get(i);
if (CodeCompletion.isValid(completion)) { if (CodeCompletion.isValid(completion)) {
jlist.setSelectedIndex(i); jlist.setSelectedIndex(i);
jlist.ensureIndexIsVisible(i); jlist.ensureIndexIsVisible(i);
@ -296,18 +299,18 @@ public class CodeCompletionWindow extends JDialog {
if (-1 == i) { if (-1 == i) {
return null; return null;
} }
return completion_list.get(i); return completionData.get(i);
} }
} }
/** /**
* Code completion ListModel. * Code completion ListModel.
*/ */
class CodeCompletionListModel implements ListModel { class CodeCompletionListModel implements ListModel<CodeCompletion> {
List<CodeCompletion> completion_list; List<CodeCompletion> completionData;
public CodeCompletionListModel(List<CodeCompletion> completion_list) { public CodeCompletionListModel(List<CodeCompletion> completion_list) {
this.completion_list = completion_list; this.completionData = completion_list;
} }
@Override @Override
@ -321,22 +324,22 @@ class CodeCompletionListModel implements ListModel {
} }
@Override @Override
public Object getElementAt(int index) { public CodeCompletion getElementAt(int index) {
if ((null == completion_list) || completion_list.isEmpty()) { if ((null == completionData) || completionData.isEmpty()) {
if (0 == index) { if (0 == index) {
return new CodeCompletion("(no completions available)", null, null); return new CodeCompletion("(no completions available)", null, null);
} }
return null; return null;
} }
return completion_list.get(index); return completionData.get(index);
} }
@Override @Override
public int getSize() { public int getSize() {
if ((null == completion_list) || completion_list.isEmpty()) { if ((null == completionData) || completionData.isEmpty()) {
return 1; return 1;
} }
return completion_list.size(); return completionData.size();
} }
} }
@ -405,12 +408,8 @@ class CodeCompletionListCellRenderer extends GListCellRenderer<CodeCompletion> {
@Override @Override
public Component getListCellRendererComponent(JList<? extends CodeCompletion> list, public Component getListCellRendererComponent(JList<? extends CodeCompletion> list,
CodeCompletion codeCompletion, int index, boolean isSelected, boolean cellHasFocus) { CodeCompletion codeCompletion, int index, boolean isSelected, boolean cellHasFocus) {
if (codeCompletion.getComponent() == null) { JLabel component = (JLabel) super.getListCellRendererComponent(list, codeCompletion, index,
return super.getListCellRendererComponent(list, codeCompletion, index, isSelected, isSelected, cellHasFocus);
cellHasFocus);
}
JComponent component = codeCompletion.getComponent();
// if it's selected, make sure it shows up that way // if it's selected, make sure it shows up that way
component.setOpaque(true); component.setOpaque(true);

View File

@ -28,8 +28,7 @@ import javax.swing.text.*;
import docking.DockingUtils; import docking.DockingUtils;
import docking.actions.KeyBindingUtils; import docking.actions.KeyBindingUtils;
import generic.theme.GColor; import generic.theme.*;
import generic.theme.Gui;
import generic.util.WindowUtilities; import generic.util.WindowUtilities;
import ghidra.app.plugin.core.console.CodeCompletion; import ghidra.app.plugin.core.console.CodeCompletion;
import ghidra.framework.options.OptionsChangeListener; 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. " + "This is the font that will be used in the Console. " +
"Double-click the font example to change it."; "Double-click the font example to change it.";
private static final Color NORMAL_COLOR = new GColor("color.fg.interpreterconsole"); private static final GColor NORMAL_COLOR = new GColor("color.fg.interpreterconsole");
private static final Color ERROR_COLOR = new GColor("color.fg.interpreterconsole.error"); private static final GColor ERROR_COLOR = new GColor("color.fg.interpreterconsole.error");
private static final Color BG_COLOR = new GColor("color.bg.interpreterconsole"); private static final GColor BG_COLOR = new GColor("color.bg.interpreterconsole");
public enum TextType { public enum TextType {
STDOUT, STDERR, STDIN; STDOUT, STDERR, STDIN;
@ -84,16 +83,6 @@ public class InterpreterPanel extends JPanel implements OptionsChangeListener {
private boolean caretGuard = true; private boolean caretGuard = true;
private PluginTool tool; 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) { public InterpreterPanel(PluginTool tool, InterpreterConnection interpreter) {
this.tool = tool; this.tool = tool;
this.interpreter = interpreter; this.interpreter = interpreter;
@ -373,9 +362,11 @@ public class InterpreterPanel extends JPanel implements OptionsChangeListener {
private void updateFontAttributes(Font font) { private void updateFontAttributes(Font font) {
Font boldFont = font.deriveFont(Font.BOLD); Font boldFont = font.deriveFont(Font.BOLD);
STDOUT_SET = createAttributes(font, NORMAL_COLOR);
STDERR_SET = createAttributes(font, ERROR_COLOR); STDOUT_SET = new GAttributes(font, NORMAL_COLOR);
STDIN_SET = createAttributes(boldFont, 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(inputTextPane, boldFont);
setTextPaneFont(promptTextPane, font); setTextPaneFont(promptTextPane, font);
@ -389,8 +380,7 @@ public class InterpreterPanel extends JPanel implements OptionsChangeListener {
HelpLocation help = new HelpLocation(getName(), "ConsolePlugin"); HelpLocation help = new HelpLocation(getName(), "ConsolePlugin");
options.setOptionsHelpLocation(help); options.setOptionsHelpLocation(help);
options.registerThemeFontBinding(FONT_OPTION_LABEL, FONT_ID, help, options.registerThemeFontBinding(FONT_OPTION_LABEL, FONT_ID, help, FONT_DESCRIPTION);
FONT_DESCRIPTION);
options.registerOption(COMPLETION_WINDOW_TRIGGER_LABEL, CompletionWindowTrigger.TAB, help, options.registerOption(COMPLETION_WINDOW_TRIGGER_LABEL, CompletionWindowTrigger.TAB, help,
COMPLETION_WINDOW_TRIGGER_DESCRIPTION); COMPLETION_WINDOW_TRIGGER_DESCRIPTION);
@ -490,8 +480,8 @@ public class InterpreterPanel extends JPanel implements OptionsChangeListener {
completionInsertionPosition = inputTextPane.getCaretPosition(); completionInsertionPosition = inputTextPane.getCaretPosition();
String text = getInputTextPaneText(); String text = getInputTextPaneText();
List<CodeCompletion> completions = InterpreterPanel.this.interpreter.getCompletions( List<CodeCompletion> completions =
text, completionInsertionPosition); InterpreterPanel.this.interpreter.getCompletions(text, completionInsertionPosition);
completionWindow.updateCompletionList(completions); completionWindow.updateCompletionList(completions);
}); });
} }

View File

@ -67,7 +67,7 @@ class MemoryMapProvider extends ComponentProviderAdapter {
private DockingAction deleteAction; private DockingAction deleteAction;
private DockingAction setBaseAction; private DockingAction setBaseAction;
private MemoryMapPlugin plugin = null; private MemoryMapPlugin plugin;
private Program program; private Program program;
private MemoryMapManager memManager; private MemoryMapManager memManager;
@ -135,8 +135,12 @@ class MemoryMapProvider extends ComponentProviderAdapter {
table.installNavigation(tool); table.installNavigation(tool);
table.setAutoCreateColumnsFromModel(false); table.setAutoCreateColumnsFromModel(false);
GTableCellRenderer monoRenderer = new GTableCellRenderer(); GTableCellRenderer monoRenderer = new GTableCellRenderer() {
monoRenderer.setFont(monoRenderer.getFixedWidthFont()); @Override
protected Font getDefaultFont() {
return fixedWidthFont;
}
};
TableColumn column = table.getColumn(MemoryMapModel.START_COL); TableColumn column = table.getColumn(MemoryMapModel.START_COL);
column.setCellRenderer(monoRenderer); column.setCellRenderer(monoRenderer);

View File

@ -1019,8 +1019,6 @@ public class EditReferencesProvider extends ComponentProviderAdapter
private class RefCellTextRenderer extends GTableCellRenderer { private class RefCellTextRenderer extends GTableCellRenderer {
RefCellTextRenderer() { RefCellTextRenderer() {
defaultFont = getFont();
boldFont = defaultFont.deriveFont(defaultFont.getStyle() | Font.BOLD);
setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 0)); setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 0));
} }

View File

@ -28,7 +28,6 @@ import docking.widgets.OptionDialog;
import docking.widgets.table.*; import docking.widgets.table.*;
import generic.theme.GColor; import generic.theme.GColor;
import generic.theme.GThemeDefaults.Colors.Palette; import generic.theme.GThemeDefaults.Colors.Palette;
import generic.theme.Gui;
import ghidra.app.cmd.register.SetRegisterCmd; import ghidra.app.cmd.register.SetRegisterCmd;
import ghidra.app.events.ProgramSelectionPluginEvent; import ghidra.app.events.ProgramSelectionPluginEvent;
import ghidra.app.services.MarkerService; import ghidra.app.services.MarkerService;
@ -498,7 +497,11 @@ class RegisterValueRenderer extends GTableCellRenderer {
RegisterValueRenderer(JTable table) { RegisterValueRenderer(JTable table) {
setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));
Gui.registerFont(this, "font.monospaced"); }
@Override
protected Font getDefaultFont() {
return fixedWidthFont;
} }
@Override @Override

View File

@ -28,6 +28,7 @@ import javax.swing.event.ChangeListener;
import docking.DialogComponentProvider; import docking.DialogComponentProvider;
import docking.widgets.combobox.GComboBox; import docking.widgets.combobox.GComboBox;
import docking.widgets.label.GLabel; import docking.widgets.label.GLabel;
import generic.theme.GThemeDefaults.Ids.Fonts;
import generic.theme.Gui; import generic.theme.Gui;
import ghidra.app.util.bean.FixedBitSizeValueField; import ghidra.app.util.bean.FixedBitSizeValueField;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
@ -77,8 +78,6 @@ public class SetRegisterValueDialog extends DialogComponentProvider {
private JComponent buildWorkPanel(Register[] registers) { private JComponent buildWorkPanel(Register[] registers) {
registerComboBox = new GComboBox<>(wrapRegisters(registers)); registerComboBox = new GComboBox<>(wrapRegisters(registers));
Font f = registerComboBox.getFont().deriveFont(13f);
registerComboBox.setFont(f);
registerValueField = new FixedBitSizeValueField(32, true, false); registerValueField = new FixedBitSizeValueField(32, true, false);
registerValueField.addChangeListener(new ChangeListener() { registerValueField.addChangeListener(new ChangeListener() {
@Override @Override
@ -93,11 +92,11 @@ public class SetRegisterValueDialog extends DialogComponentProvider {
registerChanged(); registerChanged();
} }
}); });
f = Gui.getFont("font.monospaced");
addressRangeList = new JList(); addressRangeList = new JList();
addressRangeList.setEnabled(false); addressRangeList.setEnabled(false);
addressRangeList.setFont(f); Gui.registerFont(addressRangeList, Fonts.MONOSPACED);
JScrollPane scrollPane = new JScrollPane(addressRangeList); JScrollPane scrollPane = new JScrollPane(addressRangeList);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
Dimension d = scrollPane.getPreferredSize(); Dimension d = scrollPane.getPreferredSize();

View File

@ -16,11 +16,12 @@
package ghidra.app.plugin.core.scalartable; package ghidra.app.plugin.core.scalartable;
import java.awt.Component; import java.awt.Component;
import java.awt.Font;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.Comparator; import java.util.Comparator;
import javax.swing.*; import javax.swing.JLabel;
import javax.swing.table.TableModel; import javax.swing.SwingConstants;
import docking.widgets.table.*; import docking.widgets.table.*;
import ghidra.docking.settings.Settings; import ghidra.docking.settings.Settings;
@ -321,7 +322,7 @@ public class ScalarSearchModel extends AddressBasedTableModel<ScalarRowObject> {
//================================================================================================== //==================================================================================================
// Columns & Column helpers // Columns & Column helpers
//================================================================================================== //==================================================================================================
private class ScalarComparator implements Comparator<Scalar> { private class ScalarComparator implements Comparator<Scalar> {
@ -339,8 +340,7 @@ public class ScalarSearchModel extends AddressBasedTableModel<ScalarRowObject> {
return (o1.isSigned() ? 1 : -1); return (o1.isSigned() ? 1 : -1);
} }
return o1.isSigned() return o1.isSigned() ? Long.compare(o1.getSignedValue(), o2.getSignedValue())
? Long.compare(o1.getSignedValue(), o2.getSignedValue())
: Long.compareUnsigned(o1.getUnsignedValue(), o2.getUnsignedValue()); : Long.compareUnsigned(o1.getUnsignedValue(), o2.getUnsignedValue());
} }
} }
@ -410,15 +410,14 @@ public class ScalarSearchModel extends AddressBasedTableModel<ScalarRowObject> {
} }
@Override @Override
protected void configureFont(JTable table, TableModel model, int column) { protected Font getDefaultFont() {
setFont(fixedWidthFont); return fixedWidthFont;
} }
@Override @Override
public ColumnConstraintFilterMode getColumnConstraintFilterMode() { public ColumnConstraintFilterMode getColumnConstraintFilterMode() {
return ColumnConstraintFilterMode.ALLOW_ALL_FILTERS; return ColumnConstraintFilterMode.ALLOW_ALL_FILTERS;
} }
}; };
@Override @Override
@ -440,10 +439,7 @@ public class ScalarSearchModel extends AddressBasedTableModel<ScalarRowObject> {
public Scalar getValue(ScalarRowObject rowObject, Settings settings, Program p, public Scalar getValue(ScalarRowObject rowObject, Settings settings, Program p,
ServiceProvider provider) throws IllegalArgumentException { ServiceProvider provider) throws IllegalArgumentException {
Scalar scalar = rowObject.getScalar(); Scalar scalar = rowObject.getScalar();
return new Scalar(scalar.bitLength(), scalar.getUnsignedValue(), false);
Scalar unsigned = new Scalar(scalar.bitLength(), scalar.getUnsignedValue(), false);
return unsigned;
} }
} }

View File

@ -38,7 +38,7 @@ import docking.widgets.spinner.IntegerSpinner;
import docking.widgets.table.threaded.ThreadedTableModelListener; import docking.widgets.table.threaded.ThreadedTableModelListener;
import generic.jar.ResourceFile; import generic.jar.ResourceFile;
import generic.theme.GThemeDefaults; import generic.theme.GThemeDefaults;
import ghidra.app.services.GoToService; import generic.theme.Gui;
import ghidra.app.services.StringTranslationService; import ghidra.app.services.StringTranslationService;
import ghidra.app.services.StringTranslationService.TranslateOptions; import ghidra.app.services.StringTranslationService.TranslateOptions;
import ghidra.docking.settings.Settings; import ghidra.docking.settings.Settings;
@ -72,6 +72,8 @@ public class EncodedStringsDialog extends DialogComponentProvider {
Map.entry(CharsetInfo.UTF16, UnicodeDataType.dataType), Map.entry(CharsetInfo.UTF16, UnicodeDataType.dataType),
Map.entry(CharsetInfo.UTF32, Unicode32DataType.dataType)); Map.entry(CharsetInfo.UTF32, Unicode32DataType.dataType));
private static final String BUTTON_FONT_ID = "font.plugin.strings.buttons";
private final PluginTool tool; private final PluginTool tool;
private final EncodedStringsPlugin plugin; private final EncodedStringsPlugin plugin;
private final Program program; private final Program program;
@ -148,7 +150,7 @@ public class EncodedStringsDialog extends DialogComponentProvider {
/** /**
* For test/screen shot use * For test/screen shot use
* *
* @param charsetName set the charset * @param charsetName set the charset
*/ */
public void setSelectedCharset(String charsetName) { public void setSelectedCharset(String charsetName) {
@ -157,7 +159,7 @@ public class EncodedStringsDialog extends DialogComponentProvider {
/** /**
* For test/screen shot use * For test/screen shot use
* *
* @param b boolean * @param b boolean
*/ */
public void setRequireValidStringOption(boolean b) { public void setRequireValidStringOption(boolean b) {
@ -167,7 +169,7 @@ public class EncodedStringsDialog extends DialogComponentProvider {
/** /**
* For test/screen shot use * For test/screen shot use
* *
* @param b boolean * @param b boolean
*/ */
public void setAllowLatinScriptOption(boolean b) { public void setAllowLatinScriptOption(boolean b) {
@ -178,7 +180,7 @@ public class EncodedStringsDialog extends DialogComponentProvider {
/** /**
* For test/screen shot use * For test/screen shot use
* *
* @param b boolean * @param b boolean
*/ */
public void setAllowCommonScriptOption(boolean b) { public void setAllowCommonScriptOption(boolean b) {
@ -189,7 +191,7 @@ public class EncodedStringsDialog extends DialogComponentProvider {
/** /**
* For test/screen shot use * For test/screen shot use
* *
* @param b boolean * @param b boolean
*/ */
public void setAllowAnyScriptOption(boolean b) { public void setAllowAnyScriptOption(boolean b) {
@ -200,7 +202,7 @@ public class EncodedStringsDialog extends DialogComponentProvider {
/** /**
* For test/screen shot use * For test/screen shot use
* *
* @param requiredScript unicode script * @param requiredScript unicode script
*/ */
public void setRequiredScript(UnicodeScript requiredScript) { public void setRequiredScript(UnicodeScript requiredScript) {
@ -210,7 +212,7 @@ public class EncodedStringsDialog extends DialogComponentProvider {
/** /**
* For test/screen shot use * For test/screen shot use
* *
* @param b boolean * @param b boolean
*/ */
public void setShowAdvancedOptions(boolean b) { public void setShowAdvancedOptions(boolean b) {
@ -221,7 +223,7 @@ public class EncodedStringsDialog extends DialogComponentProvider {
/** /**
* For test/screen shot use * For test/screen shot use
* *
* @param b boolean * @param b boolean
*/ */
public void setShowScriptOptions(boolean b) { public void setShowScriptOptions(boolean b) {
@ -232,7 +234,7 @@ public class EncodedStringsDialog extends DialogComponentProvider {
/** /**
* For test/screen shot use * For test/screen shot use
* *
* @param b boolean * @param b boolean
*/ */
public void setExcludeCodecErrors(boolean b) { public void setExcludeCodecErrors(boolean b) {
@ -243,7 +245,7 @@ public class EncodedStringsDialog extends DialogComponentProvider {
/** /**
* For test/screen shot use * For test/screen shot use
* *
* @param b boolean * @param b boolean
*/ */
public void setExcludeNonStdCtrlChars(boolean b) { public void setExcludeNonStdCtrlChars(boolean b) {
@ -254,7 +256,7 @@ public class EncodedStringsDialog extends DialogComponentProvider {
/** /**
* For test/screen shot use * For test/screen shot use
* *
* @return table model * @return table model
*/ */
public EncodedStringsTableModel getStringModel() { public EncodedStringsTableModel getStringModel() {
@ -263,7 +265,7 @@ public class EncodedStringsDialog extends DialogComponentProvider {
/** /**
* For test/screen shot use * For test/screen shot use
* *
* @return button * @return button
*/ */
public JButton getCreateButton() { public JButton getCreateButton() {
@ -423,8 +425,7 @@ public class EncodedStringsDialog extends DialogComponentProvider {
table.setPreferredScrollableViewportSize(new Dimension(350, 150)); table.setPreferredScrollableViewportSize(new Dimension(350, 150));
table.getSelectionModel().addListSelectionListener(e -> selectedRowChange()); table.getSelectionModel().addListSelectionListener(e -> selectedRowChange());
GoToService goToService = tool.getService(GoToService.class); table.installNavigation(tool);
table.installNavigation(goToService, goToService.getDefaultNavigatable());
filterPanel = new GhidraTableFilterPanel<>(table, tableModel); filterPanel = new GhidraTableFilterPanel<>(table, tableModel);
} }
@ -454,7 +455,7 @@ public class EncodedStringsDialog extends DialogComponentProvider {
public void keyPressed(KeyEvent e) { public void keyPressed(KeyEvent e) {
// Note: we override the [ENTER] key handling to allow the user to invoke the // 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 // 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') { if (e.getKeyChar() == '\n') {
e.consume(); e.consume();
if (charsetComboBox.isPopupVisible()) { if (charsetComboBox.isPopupVisible()) {
@ -604,10 +605,10 @@ public class EncodedStringsDialog extends DialogComponentProvider {
scriptFailedCountLabel scriptFailedCountLabel
.setToolTipText("Number of strings excluded due to failing script requirements."); .setToolTipText("Number of strings excluded due to failing script requirements.");
Font font = new JPanel().getFont().deriveFont(10.0f);
allowLatinScriptButton = new JToggleButton("A-Z"); allowLatinScriptButton = new JToggleButton("A-Z");
allowLatinScriptButton.setName("ALLOW_LATIN_SCRIPT"); allowLatinScriptButton.setName("ALLOW_LATIN_SCRIPT");
allowLatinScriptButton.setFont(font); Gui.registerFont(allowLatinScriptButton, BUTTON_FONT_ID);
allowLatinScriptButton.setToolTipText( allowLatinScriptButton.setToolTipText(
"Allow Latin characters (e.g. A-Z, etc) to also be present in the string."); "Allow Latin characters (e.g. A-Z, etc) to also be present in the string.");
allowLatinScriptButton.setSelected(true); allowLatinScriptButton.setSelected(true);
@ -620,7 +621,7 @@ public class EncodedStringsDialog extends DialogComponentProvider {
allowCommonScriptButton = new JToggleButton("0-9,!?"); allowCommonScriptButton = new JToggleButton("0-9,!?");
allowCommonScriptButton.setName("ALLOW_COMMON_SCRIPT"); allowCommonScriptButton.setName("ALLOW_COMMON_SCRIPT");
allowCommonScriptButton.setFont(font); Gui.registerFont(allowCommonScriptButton, BUTTON_FONT_ID);
allowCommonScriptButton.setToolTipText( allowCommonScriptButton.setToolTipText(
"Allow common characters (e.g. 0-9, space, punctuation, etc) to also be present in the string."); "Allow common characters (e.g. 0-9, space, punctuation, etc) to also be present in the string.");
allowCommonScriptButton.setSelected(true); allowCommonScriptButton.setSelected(true);
@ -633,7 +634,7 @@ public class EncodedStringsDialog extends DialogComponentProvider {
allowAnyScriptButton = new JToggleButton("Any"); allowAnyScriptButton = new JToggleButton("Any");
allowAnyScriptButton.setName("ALLOW_ANY_SCRIPT"); allowAnyScriptButton.setName("ALLOW_ANY_SCRIPT");
allowAnyScriptButton.setFont(font); Gui.registerFont(allowAnyScriptButton, BUTTON_FONT_ID);
allowAnyScriptButton.setToolTipText( allowAnyScriptButton.setToolTipText(
"Allow all other character scripts to also be present in the string."); "Allow all other character scripts to also be present in the string.");
allowAnyScriptButton.setSelected(true); allowAnyScriptButton.setSelected(true);
@ -747,13 +748,12 @@ public class EncodedStringsDialog extends DialogComponentProvider {
executeMonitoredRunnable("Creating Strings", true, true, 100, this::createStringsAndClose); executeMonitoredRunnable("Creating Strings", true, true, 100, this::createStringsAndClose);
} }
private void setActionItemEnablement(boolean b) { private void setActionItemEnablement(boolean enabled) {
createButton.setEnabled(b); createButton.setEnabled(enabled);
cancelButton.setEnabled(b); cancelButton.setEnabled(enabled);
table.removeNavigation(); table.removeNavigation();
if (b) { if (enabled) {
GoToService goToService = tool.getService(GoToService.class); table.installNavigation(tool);
table.installNavigation(goToService, goToService.getDefaultNavigatable());
} }
} }
@ -834,11 +834,10 @@ public class EncodedStringsDialog extends DialogComponentProvider {
createButton.setEnabled(false); createButton.setEnabled(false);
return; return;
} }
String createMessage = isSingleStringMode() String createMessage = isSingleStringMode() ? "Create"
? "Create" : "Create %s"
: "Create %s".formatted(rowCount == selectedRowCount || selectedRowCount == 0 .formatted(rowCount == selectedRowCount || selectedRowCount == 0 ? "All"
? "All" : "Selected (%d)".formatted(selectedRowCount));
: "Selected (%d)".formatted(selectedRowCount));
createButton.setEnabled(true); createButton.setEnabled(true);
createButton.setText(createMessage); createButton.setText(createMessage);
@ -954,8 +953,7 @@ public class EncodedStringsDialog extends DialogComponentProvider {
return null; return null;
} }
File f = new File(filename); File f = new File(filename);
ResourceFile rf = f.isAbsolute() && f.isFile() ResourceFile rf = f.isAbsolute() && f.isFile() ? new ResourceFile(f)
? new ResourceFile(f)
: Application.findDataFileInAnyModule(filename); : Application.findDataFileInAnyModule(filename);
if (rf == null) { if (rf == null) {
Msg.error(this, "Unable to find string model file: %s".formatted(filename)); 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) { private StringTranslationService getSelectedStringTranslationService(boolean ifEnabled) {
boolean enabled = showTranslateOptionsButton.isSelected(); boolean enabled = showTranslateOptionsButton.isSelected();
return ifEnabled && !enabled return ifEnabled && !enabled ? null
? null
: (StringTranslationService) translateComboBox.getSelectedItem(); : (StringTranslationService) translateComboBox.getSelectedItem();
} }
@ -1081,7 +1078,7 @@ public class EncodedStringsDialog extends DialogComponentProvider {
* Execute a non-modal task that has progress and can be cancelled. * Execute a non-modal task that has progress and can be cancelled.
* <p> * <p>
* See {@link #executeProgressTask(Task, int)}. * See {@link #executeProgressTask(Task, int)}.
* *
* @param taskTitle String title of task * @param taskTitle String title of task
* @param canCancel boolean flag, if true task can be canceled by the user * @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 * @param hasProgress boolean flag, if true the task has a progress meter

View File

@ -15,7 +15,6 @@
*/ */
package ghidra.app.plugin.debug; package ghidra.app.plugin.debug;
import java.awt.Font;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -59,22 +58,11 @@ public class DomainEventComponentProvider extends ComponentProviderAdapter {
return scrollPane; return scrollPane;
} }
/**
* @see docking.ComponentProvider#componentHidden()
*/
@Override @Override
public void componentHidden() { public void componentHidden() {
clear(); clear();
} }
public Font getFont() {
return textArea.getFont();
}
public void setFont(Font font) {
textArea.setFont(font);
}
private void createAction() { private void createAction() {
clearAction = new DockingAction("Clear Display", getName()) { clearAction = new DockingAction("Clear Display", getName()) {
@Override @Override

View File

@ -15,7 +15,6 @@
*/ */
package ghidra.app.plugin.debug; package ghidra.app.plugin.debug;
import java.awt.Font;
import java.util.Date; import java.util.Date;
import ghidra.app.DeveloperPluginPackage; import ghidra.app.DeveloperPluginPackage;
@ -47,28 +46,18 @@ public class DomainEventDisplayPlugin extends Plugin implements DomainObjectList
private Program currentProgram; private Program currentProgram;
private DomainEventComponentProvider provider; private DomainEventComponentProvider provider;
private String padString;
/**
* Constructor
*/
public DomainEventDisplayPlugin(PluginTool tool) { public DomainEventDisplayPlugin(PluginTool tool) {
super(tool); super(tool);
String dateStr = new Date() + ": ";
padString = dateStr.replaceAll(".", " ");
provider = new DomainEventComponentProvider(tool, getName()); 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 helpService = Help.getHelpService();
helpService.excludeFromHelp(provider); helpService.excludeFromHelp(provider);
} }
/**
* Put event processing code here.
*/
@Override @Override
public void processEvent(PluginEvent event) { public void processEvent(PluginEvent event) {
if (event instanceof ProgramActivatedPluginEvent) { 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 @Override
public void dispose() { public void dispose() {
if (currentProgram != null) { if (currentProgram != null) {
@ -94,9 +79,6 @@ public class DomainEventDisplayPlugin extends Plugin implements DomainObjectList
} }
} }
/**
* This is the callback method for DomainObjectChangedEvents.
*/
@Override @Override
public void domainObjectChanged(DomainObjectChangedEvent ev) { public void domainObjectChanged(DomainObjectChangedEvent ev) {
if (tool != null && provider.isVisible()) { 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. * Display the change event.
*/ */

View File

@ -27,6 +27,7 @@ import javax.swing.*;
import docking.ComponentProvider; import docking.ComponentProvider;
import docking.Tool; import docking.Tool;
import generic.theme.GColor; import generic.theme.GColor;
import generic.theme.Gui;
import generic.util.WindowUtilities; import generic.util.WindowUtilities;
import generic.util.image.ImageUtils; import generic.util.image.ImageUtils;
import ghidra.app.DeveloperPluginPackage; import ghidra.app.DeveloperPluginPackage;
@ -110,6 +111,8 @@ public class WindowLocationPlugin extends Plugin {
private class WindowLocationPanel extends JPanel { private class WindowLocationPanel extends JPanel {
private static final String FONT_ID = "font.plugin.window.location";
private MouseListener mousy = new MouseListener(); private MouseListener mousy = new MouseListener();
WindowLocationPanel() { WindowLocationPanel() {
@ -188,9 +191,8 @@ public class WindowLocationPlugin extends Plugin {
} }
private void paintWindows(Graphics2D g2d, AffineTransform xform) { private void paintWindows(Graphics2D g2d, AffineTransform xform) {
Font f = g2d.getFont(); Font f = Gui.getFont(FONT_ID);
Font biggerFont = f.deriveFont(40f); g2d.setFont(f);
g2d.setFont(biggerFont);
g2d.setColor(FG_COLOR_WINDOW_TEXT); g2d.setColor(FG_COLOR_WINDOW_TEXT);
Window[] windows = Window.getWindows(); Window[] windows = Window.getWindows();
@ -423,10 +425,7 @@ public class WindowLocationPlugin extends Plugin {
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; return Objects.hash(window);
int result = 1;
result = prime * result + ((window == null) ? 0 : window.hashCode());
return result;
} }
@Override @Override

View File

@ -65,10 +65,12 @@ public abstract class AbstractVariableFieldFactory extends FieldFactory {
* @param fieldOptions the Options for field specific properties. * @param fieldOptions the Options for field specific properties.
*/ */
protected AbstractVariableFieldFactory(String name, FieldFormatModel model, protected AbstractVariableFieldFactory(String name, FieldFormatModel model,
ListingHighlightProvider highlightProvider, Options displayOptions, Options fieldOptions) { ListingHighlightProvider highlightProvider, Options displayOptions,
Options fieldOptions) {
super(name, model, highlightProvider, displayOptions, fieldOptions); super(name, model, highlightProvider, displayOptions, fieldOptions);
} }
@Override
protected void initDisplayOptions(Options displayOptions) { protected void initDisplayOptions(Options displayOptions) {
// display options for local variables handled by FieldFactory base class // 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); super.displayOptionsChanged(options, optionName, oldValue, newValue);
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation") // ignore getFontMetrics() deprecation warning
// we know
private void setMetrics(Font newFont, ParameterFieldOptions paramFieldOptions) { private void setMetrics(Font newFont, ParameterFieldOptions paramFieldOptions) {
paramFieldOptions.defaultMetrics = Toolkit.getDefaultToolkit().getFontMetrics(newFont); paramFieldOptions.defaultMetrics = Toolkit.getDefaultToolkit().getFontMetrics(newFont);
for (int i = 0; i < paramFieldOptions.fontMetrics.length; i++) { for (int i = 0; i < paramFieldOptions.fontMetrics.length; i++) {

View File

@ -29,7 +29,6 @@ import ghidra.framework.options.ToolOptions;
import ghidra.program.model.listing.Data; import ghidra.program.model.listing.Data;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
import ghidra.util.HelpLocation; import ghidra.util.HelpLocation;
import ghidra.util.SystemUtilities;
import ghidra.util.classfinder.ExtensionPoint; import ghidra.util.classfinder.ExtensionPoint;
/** /**
@ -66,8 +65,8 @@ public abstract class FieldFactory implements ExtensionPoint {
* @param fieldOptions the Options for field specific properties. * @param fieldOptions the Options for field specific properties.
*/ */
protected FieldFactory(String name, FieldFormatModel model, protected FieldFactory(String name, FieldFormatModel model,
ListingHighlightProvider highlightProvider, ListingHighlightProvider highlightProvider, Options displayOptions,
Options displayOptions, Options fieldOptions) { Options fieldOptions) {
this.name = name; this.name = name;
this.model = model; this.model = model;
this.hlProvider = highlightProvider; this.hlProvider = highlightProvider;
@ -135,7 +134,7 @@ public abstract class FieldFactory implements ExtensionPoint {
public void displayOptionsChanged(Options options, String optionName, Object oldValue, public void displayOptionsChanged(Options options, String optionName, Object oldValue,
Object newValue) { Object newValue) {
if (optionName.equals(FONT_OPTION_NAME)) { if (optionName.equals(FONT_OPTION_NAME)) {
baseFont = SystemUtilities.adjustForFontSizeOverride((Font) newValue); baseFont = (Font) newValue;
setMetrics(baseFont); setMetrics(baseFont);
} }
else if (optionName.equals(styleOptionName)) { 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 * Returns true if this given field represents the given location
* @param listingField the field * @param listingField the field
* @param location the location * @param location the location
* @return true if this given field represents the given location * @return true if this given field represents the given location
*/ */
public boolean supportsLocation(ListingField listingField, ProgramLocation location) { public boolean supportsLocation(ListingField listingField, ProgramLocation location) {

View File

@ -40,7 +40,6 @@ import generic.theme.GThemeDefaults.Colors.Palette;
import ghidra.GhidraOptions; import ghidra.GhidraOptions;
import ghidra.app.util.viewer.field.ListingColors; import ghidra.app.util.viewer.field.ListingColors;
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. * Class for displaying and manipulating field colors and fonts.
@ -133,13 +132,13 @@ public class OptionsGui extends JPanel {
/** /**
* Constructor * Constructor
* *
* @param font the base font for the fields. * @param font the base font for the fields.
* @param listener the listener to be notified when options change. * @param listener the listener to be notified when options change.
*/ */
public OptionsGui(Font font, PropertyChangeListener listener) { public OptionsGui(Font font, PropertyChangeListener listener) {
propertyChangeListener = listener; propertyChangeListener = listener;
setBaseFont(SystemUtilities.adjustForFontSizeOverride(font)); setBaseFont(font);
genLayouts(); genLayouts();
buildPanel(); buildPanel();
fieldPanel.setBackgroundColor(BACKGROUND.getColor()); fieldPanel.setBackgroundColor(BACKGROUND.getColor());
@ -217,7 +216,7 @@ public class OptionsGui extends JPanel {
/** /**
* callback for when the selected display field changes. * callback for when the selected display field changes.
* *
* @param index the index in the JList of the selected field. * @param index the index in the JList of the selected field.
*/ */
private void setSelectedIndex(int index) { 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. * This listener will be notified when changes are made that need to be applied.
* *
* @param listener The listener to be notified. * @param listener The listener to be notified.
*/ */
void setOptionsPropertyChangeListener(PropertyChangeListener listener) { void setOptionsPropertyChangeListener(PropertyChangeListener listener) {
@ -774,9 +773,9 @@ public class OptionsGui extends JPanel {
setSelectedIndex(selectedIndex); setSelectedIndex(selectedIndex);
} }
//================================================================================================== //==================================================================================================
// Inner Classes // Inner Classes
//================================================================================================== //==================================================================================================
/** /**
* Simple layoutModel to be used for the preview panel. * Simple layoutModel to be used for the preview panel.
@ -850,7 +849,7 @@ public class OptionsGui extends JPanel {
/** /**
* Constructor * Constructor
* *
* @param size the number of fields in the layout * @param size the number of fields in the layout
*/ */
LayoutBuilder(int size) { LayoutBuilder(int size) {

View File

@ -21,9 +21,8 @@ import java.util.LinkedList;
import javax.swing.JTextPane; import javax.swing.JTextPane;
import javax.swing.text.*; import javax.swing.text.*;
import generic.theme.GColor; import generic.theme.*;
import generic.theme.GThemeDefaults.Ids.Fonts; import generic.theme.GThemeDefaults.Ids.Fonts;
import generic.theme.Gui;
import ghidra.framework.options.*; import ghidra.framework.options.*;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
import ghidra.util.Msg; import ghidra.util.Msg;
@ -31,9 +30,9 @@ import ghidra.util.SystemUtilities;
import ghidra.util.exception.AssertException; import ghidra.util.exception.AssertException;
import ghidra.util.task.SwingUpdateManager; import ghidra.util.task.SwingUpdateManager;
/** /**
* A generic text pane that is used as a console to which text can be written. * 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. * There is not test for this class, but it is indirectly tested by FrontEndGuiTest.
*/ */
public class ConsoleTextPane extends JTextPane implements OptionsChangeListener { 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 */ /** % of characters to delete when truncation is necessary */
private static double DEFAULT_TRUNCATION_FACTOR = .10; private static double DEFAULT_TRUNCATION_FACTOR = .10;
private static SimpleAttributeSet outputAttributeSet; private static SimpleAttributeSet outputAttributes;
private static SimpleAttributeSet errorAttributeSet; private static SimpleAttributeSet errorAttributes;
// don't update more than once per second if lots of messages are being written // don't update more than once per second if lots of messages are being written
private SwingUpdateManager updateManager = new SwingUpdateManager(100, 1000, () -> doUpdate()); private SwingUpdateManager updateManager = new SwingUpdateManager(100, 1000, () -> doUpdate());
@ -99,7 +98,7 @@ public class ConsoleTextPane extends JTextPane implements OptionsChangeListener
} }
//================================================================================================== //==================================================================================================
// Non-interface Methods // Non-interface Methods
//================================================================================================== //==================================================================================================
private void initOptions(Options options) { private void initOptions(Options options) {
options.registerOption(MAXIMUM_CHARACTERS_OPTION_NAME, DEFAULT_MAXIMUM_CHARS, null, 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) { private AttributeSet getAttributeSetByName(String attributeSetName) {
if (OUTPUT_ATTRIBUTE_VALUE.equals(attributeSetName)) { if (OUTPUT_ATTRIBUTE_VALUE.equals(attributeSetName)) {
return outputAttributeSet; return outputAttributes;
} }
else if (ERROR_ATTRIBUTE_VALUE.equals(attributeSetName)) { else if (ERROR_ATTRIBUTE_VALUE.equals(attributeSetName)) {
return errorAttributeSet; return errorAttributes;
} }
else { else {
// we found an attribute type that we do not know about // 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) { 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(); outputAttributes = new GAttributes(font, new GColor("color.fg.consoletextpane"));
errorAttributeSet.addAttribute(CUSTOM_ATTRIBUTE_KEY, ERROR_ATTRIBUTE_VALUE); outputAttributes.addAttribute(CUSTOM_ATTRIBUTE_KEY, OUTPUT_ATTRIBUTE_VALUE);
errorAttributeSet.addAttribute(StyleConstants.FontFamily, font.getFamily());
errorAttributeSet.addAttribute(StyleConstants.FontSize, font.getSize()); errorAttributes = new GAttributes(font, new GColor("color.fg.error.consoletextpane"));
errorAttributeSet.addAttribute(StyleConstants.Italic, font.isItalic()); errorAttributes.addAttribute(CUSTOM_ATTRIBUTE_KEY, ERROR_ATTRIBUTE_VALUE);
errorAttributeSet.addAttribute(StyleConstants.Bold, font.isBold());
errorAttributeSet.addAttribute(StyleConstants.Foreground,
new GColor("color.fg.error.consoletextpane"));
} }
private void doUpdate() { private void doUpdate() {
@ -316,7 +304,7 @@ public class ConsoleTextPane extends JTextPane implements OptionsChangeListener
} }
AttributeSet getAttributes() { AttributeSet getAttributes() {
return outputAttributeSet; return outputAttributes;
} }
} }
@ -327,7 +315,7 @@ public class ConsoleTextPane extends JTextPane implements OptionsChangeListener
@Override @Override
AttributeSet getAttributes() { AttributeSet getAttributes() {
return errorAttributeSet; return errorAttributes;
} }
} }

View File

@ -29,6 +29,7 @@ import docking.widgets.*;
import docking.widgets.label.*; import docking.widgets.label.*;
import generic.theme.GColor; import generic.theme.GColor;
import generic.theme.GThemeDefaults.Colors.Palette; import generic.theme.GThemeDefaults.Colors.Palette;
import generic.theme.Gui;
import generic.util.WindowUtilities; import generic.util.WindowUtilities;
import ghidra.framework.Application; import ghidra.framework.Application;
import ghidra.framework.ApplicationProperties; import ghidra.framework.ApplicationProperties;
@ -44,16 +45,19 @@ class InfoPanel extends JPanel {
private final static int MARGIN = 10; 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 version;
private String marking; private String marking;
private String distributionInfo; private String distributionInfo;
private Color bgColor; // background color for all panels private Color bgColor; // background color for all panels
private int imageWidth; 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() { InfoPanel() {
getAboutInfo(); getAboutInfo();
@ -170,9 +174,7 @@ class InfoPanel extends JPanel {
private Component buildVersionLabel() { private Component buildVersionLabel() {
MultiLineLabel versionLabel = new MultiLineLabel(version, 0, 3, MultiLineLabel.CENTER); MultiLineLabel versionLabel = new MultiLineLabel(version, 0, 3, MultiLineLabel.CENTER);
Font font = versionLabel.getFont(); Gui.registerFont(versionLabel, FONT_ID);
font = font.deriveFont(14f).deriveFont(Font.BOLD);
versionLabel.setFont(font);
versionLabel.setForeground(new GColor("color.fg.infopanel.version")); versionLabel.setForeground(new GColor("color.fg.infopanel.version"));
return versionLabel; return versionLabel;
} }

View File

@ -38,6 +38,7 @@ import docking.widgets.dialogs.MultiLineMessageDialog;
import docking.widgets.label.GLabel; import docking.widgets.label.GLabel;
import docking.widgets.list.GListCellRenderer; import docking.widgets.list.GListCellRenderer;
import generic.theme.GIcon; import generic.theme.GIcon;
import generic.theme.Gui;
import ghidra.app.services.ProgramManager; import ghidra.app.services.ProgramManager;
import ghidra.app.util.*; import ghidra.app.util.*;
import ghidra.app.util.bin.ByteProvider; import ghidra.app.util.bin.ByteProvider;
@ -240,8 +241,7 @@ public class ImporterDialog extends DialogComponentProvider {
validateFormInput(); validateFormInput();
}); });
Font font = languageButton.getFont(); Gui.registerFont(languageButton, Font.BOLD);
languageButton.setFont(font.deriveFont(Font.BOLD));
JPanel panel = new JPanel(new BorderLayout()); JPanel panel = new JPanel(new BorderLayout());
panel.add(languageTextField, BorderLayout.CENTER); panel.add(languageTextField, BorderLayout.CENTER);

View File

@ -26,6 +26,7 @@ import javax.swing.border.Border;
import docking.widgets.checkbox.GCheckBox; import docking.widgets.checkbox.GCheckBox;
import docking.widgets.label.GDLabel; import docking.widgets.label.GDLabel;
import generic.theme.GThemeDefaults.Colors.Messages; import generic.theme.GThemeDefaults.Colors.Messages;
import generic.theme.Gui;
import ghidra.program.model.lang.*; import ghidra.program.model.lang.*;
import ghidra.program.util.DefaultLanguageService; import ghidra.program.util.DefaultLanguageService;
import ghidra.util.table.*; import ghidra.util.table.*;
@ -67,7 +68,7 @@ public class NewLanguagePanel extends JPanel {
tableFilterPanel = new GhidraTableFilterPanel<>(table, tableModel); tableFilterPanel = new GhidraTableFilterPanel<>(table, tableModel);
descriptionLabel = new GDLabel(DEFAULT_DESCRIPTION_TEXT); 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 = new GCheckBox("Show Only Recommended Language/Compiler Specs");
recommendedCheckbox.addItemListener(e -> { recommendedCheckbox.addItemListener(e -> {
@ -211,7 +212,6 @@ public class NewLanguagePanel extends JPanel {
LanguageCompilerSpecPair selectedLcsPair = getSelectedLcsPair(); LanguageCompilerSpecPair selectedLcsPair = getSelectedLcsPair();
if (selectedLcsPair == null) { if (selectedLcsPair == null) {
descriptionLabel.setText(DEFAULT_DESCRIPTION_TEXT); descriptionLabel.setText(DEFAULT_DESCRIPTION_TEXT);
descriptionLabel.setFont(descriptionLabel.getFont().deriveFont(Font.ITALIC));
} }
else { else {
try { try {
@ -220,7 +220,6 @@ public class NewLanguagePanel extends JPanel {
catch (LanguageNotFoundException e) { catch (LanguageNotFoundException e) {
descriptionLabel.setText("<LanguageNotFound>"); descriptionLabel.setText("<LanguageNotFound>");
} }
descriptionLabel.setFont(descriptionLabel.getFont().deriveFont(Font.PLAIN));
} }
// notifyListenersOfValidityChanged(); // notifyListenersOfValidityChanged();
if (!listeners.isEmpty()) { if (!listeners.isEmpty()) {

View File

@ -109,7 +109,7 @@ public class ProgramDiffDetails {
// FUTURE : Add checks to make sure programs are comparable. // FUTURE : Add checks to make sure programs are comparable.
// Throw exception if not comparable. // Throw exception if not comparable.
initDetails(); initDetails();
initAttributes(); textAttrSet = new SimpleAttributeSet();
} }
private static String getIndentString(int indentCount) { private static String getIndentString(int indentCount) {
@ -121,11 +121,6 @@ public class ProgramDiffDetails {
return buf.toString(); 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 * 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. * address. The string contains information from each program where there are differences.

View File

@ -15,8 +15,7 @@
*/ */
package ghidra.util.table.field; package ghidra.util.table.field;
import javax.swing.JTable; import java.awt.Font;
import javax.swing.table.TableModel;
import ghidra.app.plugin.core.disassembler.AddressTable; import ghidra.app.plugin.core.disassembler.AddressTable;
import ghidra.docking.settings.Settings; import ghidra.docking.settings.Settings;
@ -34,9 +33,10 @@ public class AddressTableDataTableColumn
private final GColumnRenderer<String> monospacedRenderer = private final GColumnRenderer<String> monospacedRenderer =
new AbstractGColumnRenderer<String>() { new AbstractGColumnRenderer<String>() {
@Override @Override
protected void configureFont(JTable table, TableModel model, int column) { protected Font getDefaultFont() {
setFont(getFixedWidthFont()); return fixedWidthFont;
} }
@Override @Override

View File

@ -16,10 +16,9 @@
package ghidra.util.table.field; package ghidra.util.table.field;
import java.awt.Component; import java.awt.Component;
import java.awt.Font;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.TableModel;
import docking.widgets.table.GTableCellRenderingData; import docking.widgets.table.GTableCellRenderingData;
import ghidra.docking.settings.FormatSettingsDefinition; import ghidra.docking.settings.FormatSettingsDefinition;
@ -29,14 +28,15 @@ import ghidra.util.StringFormat;
import ghidra.util.table.column.AbstractGColumnRenderer; import ghidra.util.table.column.AbstractGColumnRenderer;
public class MonospacedByteRenderer extends AbstractGColumnRenderer<Byte[]> { public class MonospacedByteRenderer extends AbstractGColumnRenderer<Byte[]> {
@Override @Override
protected void configureFont(JTable table, TableModel model, int column) { protected Font getDefaultFont() {
setFont(getFixedWidthFont()); return fixedWidthFont;
} }
private String formatBytes(Byte[] bytes, Settings settings) { private String formatBytes(Byte[] bytes, Settings settings) {
boolean bigEndian = (EndianSettingsDefinition.DEF boolean bigEndian =
.getChoice(settings) != EndianSettingsDefinition.LITTLE); (EndianSettingsDefinition.DEF.getChoice(settings) != EndianSettingsDefinition.LITTLE);
int startIx = 0; int startIx = 0;
int endIx = bytes.length; int endIx = bytes.length;

View File

@ -34,7 +34,8 @@ import ghidra.app.util.viewer.listingpanel.AddressSetDisplayListener;
import ghidra.framework.options.*; import ghidra.framework.options.*;
import ghidra.framework.plugintool.ComponentProviderAdapter; import ghidra.framework.plugintool.ComponentProviderAdapter;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
import ghidra.util.*; import ghidra.util.HelpLocation;
import ghidra.util.Msg;
import ghidra.util.classfinder.ClassSearcher; import ghidra.util.classfinder.ClassSearcher;
import ghidra.util.task.SwingUpdateManager; import ghidra.util.task.SwingUpdateManager;
@ -60,13 +61,13 @@ public abstract class ByteViewerComponentProvider extends ComponentProviderAdapt
//@formatter:off //@formatter:off
static final String FG = "byteviewer.color.fg"; static final String FG = "byteviewer.color.fg";
static final String CURSOR = "byteviewer.color.cursor"; 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 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_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_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 CURSOR_NOT_FOCUSED_COLOR = new GColor("color.cursor.byteviewer.unfocused");
static final GColor CURRENT_LINE_COLOR = GhidraOptions.DEFAULT_CURSOR_LINE_COLOR; static final GColor CURRENT_LINE_COLOR = GhidraOptions.DEFAULT_CURSOR_LINE_COLOR;
//@formatter:on //@formatter:on
@ -162,7 +163,7 @@ public abstract class ByteViewerComponentProvider extends ComponentProviderAdapt
/** /**
* Notification that an option changed. * Notification that an option changed.
* *
* @param options options object containing the property that changed * @param options options object containing the property that changed
* @param optionName name of option that changed * @param optionName name of option that changed
* @param oldValue old value of the option * @param oldValue old value of the option
@ -173,7 +174,7 @@ public abstract class ByteViewerComponentProvider extends ComponentProviderAdapt
Object newValue) { Object newValue) {
if (options.getName().equals("ByteViewer")) { if (options.getName().equals("ByteViewer")) {
if (optionName.equals(OPTION_FONT)) { if (optionName.equals(OPTION_FONT)) {
setFont(SystemUtilities.adjustForFontSizeOverride((Font) newValue)); setFont((Font) newValue);
} }
} }
else if (options.getName().equals(CATEGORY_BROWSER_FIELDS)) { 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. * Set the status info on the tool.
* *
* @param message non-html text to display * @param message non-html text to display
*/ */
void setStatusMessage(String message) { void setStatusMessage(String message) {
@ -505,7 +506,7 @@ public abstract class ByteViewerComponentProvider extends ComponentProviderAdapt
/** /**
* Add the {@link AddressSetDisplayListener} to the byte viewer panel * Add the {@link AddressSetDisplayListener} to the byte viewer panel
* *
* @param listener the listener to add * @param listener the listener to add
*/ */
public void addDisplayListener(AddressSetDisplayListener listener) { public void addDisplayListener(AddressSetDisplayListener listener) {
@ -514,7 +515,7 @@ public abstract class ByteViewerComponentProvider extends ComponentProviderAdapt
/** /**
* Remove the {@link AddressSetDisplayListener} from the byte viewer panel * Remove the {@link AddressSetDisplayListener} from the byte viewer panel
* *
* @param listener the listener to remove * @param listener the listener to remove
*/ */
public void removeDisplayListener(AddressSetDisplayListener listener) { public void removeDisplayListener(AddressSetDisplayListener listener) {

View File

@ -39,8 +39,7 @@ import docking.widgets.fieldpanel.Layout;
import docking.widgets.fieldpanel.field.Field; import docking.widgets.fieldpanel.field.Field;
import docking.widgets.fieldpanel.support.BackgroundColorModel; import docking.widgets.fieldpanel.support.BackgroundColorModel;
import docking.widgets.label.GDLabel; import docking.widgets.label.GDLabel;
import generic.theme.GColor; import generic.theme.*;
import generic.theme.GIcon;
import generic.theme.GThemeDefaults.Colors; import generic.theme.GThemeDefaults.Colors;
import generic.theme.GThemeDefaults.Colors.Tooltips; import generic.theme.GThemeDefaults.Colors.Tooltips;
import ghidra.app.plugin.core.codebrowser.MarkerServiceBackgroundColorModel; import ghidra.app.plugin.core.codebrowser.MarkerServiceBackgroundColorModel;
@ -245,8 +244,7 @@ public class ListingGraphComponentPanel extends AbstractGraphComponentPanel {
tooltipTitleLabel.setHorizontalAlignment(SwingConstants.LEADING); tooltipTitleLabel.setHorizontalAlignment(SwingConstants.LEADING);
tooltipTitleLabel.setBackground(Tooltips.BACKGROUND); tooltipTitleLabel.setBackground(Tooltips.BACKGROUND);
tooltipTitleLabel.setOpaque(true); tooltipTitleLabel.setOpaque(true);
Font labelFont = tooltipTitleLabel.getFont(); Gui.registerFont(tooltipTitleLabel, Font.BOLD);
tooltipTitleLabel.setFont(labelFont.deriveFont(Font.BOLD));
JPanel headerPanel = new JPanel(new BorderLayout()); JPanel headerPanel = new JPanel(new BorderLayout());
headerPanel.add(tooltipTitleLabel); headerPanel.add(tooltipTitleLabel);

View File

@ -15,11 +15,12 @@
*/ */
package ghidra.feature.fid.debug; package ghidra.feature.fid.debug;
import java.awt.BorderLayout; import java.awt.*;
import java.awt.Dimension;
import java.awt.event.*; import java.awt.event.*;
import java.io.IOException; 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.*;
import javax.swing.table.TableColumn; import javax.swing.table.TableColumn;
@ -63,8 +64,13 @@ public class FidSearchResultFrame extends JFrame implements FidQueryCloseListene
} }
private void buildFrame() { private void buildFrame() {
GTableCellRenderer renderer = new GTableCellRenderer(); GTableCellRenderer renderer = new GTableCellRenderer() {
renderer.setFont(renderer.getFixedWidthFont()); @Override
protected Font getDefaultFont() {
return fixedWidthFont;
}
};
int columnCount = table.getColumnCount(); int columnCount = table.getColumnCount();
for (int ii = 0; ii < columnCount; ++ii) { for (int ii = 0; ii < columnCount; ++ii) {
Class<?> columnClass = table.getColumnClass(ii); Class<?> columnClass = table.getColumnClass(ii);
@ -314,7 +320,7 @@ public class FidSearchResultFrame extends JFrame implements FidQueryCloseListene
} }
@Override @Override
public void fidQueryClosed(FidQueryService service) { public void fidQueryClosed(FidQueryService fqs) {
dispose(); dispose();
} }
} }

View File

@ -133,10 +133,18 @@ icon.task.progress.hourglass.11 = hourglass24_11.png
// Fonts // Fonts
font.splash.header.default = Serif-BOLD-35 font.splash.header.default = serif-bold-35
font.splash.status = Serif-BOLD-12 font.splash.status = serif-bold-12
font.table.header.number = arial-BOLD-12
font.input.hint = monospaced-PLAIN-10 // 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] [Dark Defaults]
color.fg.filterfield = color.palette.darkslategray color.fg.filterfield = color.palette.darkslategray
color.bg.highlight = #703401 // orangish color.bg.highlight = #703401 // orangish

View File

@ -59,9 +59,9 @@
<tocdef id="Root" sortgroup="a" text="Welcome to Help"> <tocdef id="Root" sortgroup="a" text="Welcome to Help">
<tocdef id="Theming" text="Theming" sortgroup="t" target="help/topics/Theming/ThemingOverview.html"> <tocdef id="Theming" text="Theming" sortgroup="t" target="help/topics/Theming/ThemingOverview.html">
<tocdef id="Overview" sortgroup="1" text="Overview" target="help/topics/Theming/ThemingOverview.html"/> <tocdef id="Overview" sortgroup="1" text="Overview" target="help/topics/Theming/ThemingOverview.html"/>
<tocdef id="Editing Themes" sortgroup="2" text="Editing Themes" target="help/topics/Theming/ThemingUserDocs.html"/> <tocdef id="Editing Themes" sortgroup="2" text="User's Guide" target="help/topics/Theming/ThemingUserDocs.html"/>
<tocdef id="Architecture" sortgroup="3" text="Architecture" target="help/topics/Theming/ThemingInternals.html"/> <tocdef id="Developer Documentation" sortgroup="3" text="Developer's Guide" target="help/topics/Theming/ThemingDeveloperDocs.html"/>
<tocdef id="Developer Documentation" sortgroup="4" text="Developer's Guide" target="help/topics/Theming/ThemingDeveloperDocs.html"/> <tocdef id="Architecture" sortgroup="4" text="Architecture" target="help/topics/Theming/ThemingInternals.html"/>
</tocdef> </tocdef>
</tocdef> </tocdef>
</tocroot> </tocroot>

View File

@ -13,6 +13,14 @@
plugins, actions, scripts, etc., that use colors, fonts, or icons. By following these guidelines, plugins, actions, scripts, etc., that use colors, fonts, or icons. By following these guidelines,
developers can easily make use of Ghidra's theming capabilities.</P> developers can easily make use of Ghidra's theming capabilities.</P>
<BLOCKQUOTE>
<BLOCKQUOTE>
<P><IMG border="0" src="help/shared/tip.png" alt="Tip">Most classes referenced in this document
live in the <CODE>generic.theme</CODE> package.
</P>
</BLOCKQUOTE>
</BLOCKQUOTE>
<H2>Theme Resource Types</H2> <H2>Theme Resource Types</H2>
<P>When developing application code for Ghidra such as plugins, actions, etc., developers often <P>When developing application code for Ghidra such as plugins, actions, etc., developers often
@ -122,8 +130,58 @@
<BLOCKQUOTE> <BLOCKQUOTE>
<CODE>Gui.registerFont(myLabel, "font.xyz");</CODE> <CODE>Gui.registerFont(myLabel, "font.xyz");</CODE>
</BLOCKQUOTE>
<H3>Font Usage in Tables, Lists and Custom Painting</H3>
<P>
Ghidra makes great use of tables and to a lesser extent, lists. Both tables and lists
use renderers to paint cell values.
</P>
<UL>
<LI>
Java - By default, Java will use the font of the table/list as the font used during rendering.
</LI>
<LI>
Ghidra Tables - Ghidra does <U>not</U> use the table's font for rendering by default. Instead,
the renderer is initialized with the fonts used by <CODE>JLabel</CODE>, with additional
fonts for bold and monospaced text.
</LI>
<LI>
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.
</LI>
</UL>
<P>
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
<BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
<CODE>
table.setFont(newFont);
</CODE>
</PRE>
</BLOCKQUOTE> </BLOCKQUOTE>
</BLOCKQUOTE> </BLOCKQUOTE>
<P>
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.
</P>
<P>
The fonts used for any painting operations, including table and list cell rendering, as well
as any code that overrides <CODE>paint</CODE> 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 <CODE>Gui</CODE> 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.
</P>
</BLOCKQUOTE>
</BLOCKQUOTE> </BLOCKQUOTE>

View File

@ -26,7 +26,9 @@ import docking.action.DockingActionIf;
import docking.action.KeyBindingData; import docking.action.KeyBindingData;
import docking.tool.ToolConstants; import docking.tool.ToolConstants;
import docking.widgets.label.GIconLabel; import docking.widgets.label.GIconLabel;
import generic.theme.GAttributes;
import generic.theme.GThemeDefaults.Colors.Messages; import generic.theme.GThemeDefaults.Colors.Messages;
import generic.theme.Gui;
import ghidra.util.HelpLocation; import ghidra.util.HelpLocation;
import resources.Icons; import resources.Icons;
@ -43,7 +45,8 @@ public class KeyEntryDialog extends DialogComponentProvider {
private KeyEntryTextField keyEntryField; private KeyEntryTextField keyEntryField;
private JTextPane collisionPane; private JTextPane collisionPane;
private StyledDocument doc; private StyledDocument doc;
private SimpleAttributeSet textAttrSet;
private SimpleAttributeSet textAttrs;
private Color bgColor; private Color bgColor;
public KeyEntryDialog(Tool tool, DockingActionIf action) { public KeyEntryDialog(Tool tool, DockingActionIf action) {
@ -172,10 +175,8 @@ public class KeyEntryDialog extends DialogComponentProvider {
} }
private void setUpAttributes() { private void setUpAttributes() {
textAttrSet = new SimpleAttributeSet(); Font font = Gui.getFont("font.standard");
textAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); textAttrs = new GAttributes(font, Messages.NORMAL);
textAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11));
textAttrSet.addAttribute(StyleConstants.Foreground, Messages.NORMAL);
} }
private void updateCollisionPane(KeyStroke ks) { private void updateCollisionPane(KeyStroke ks) {
@ -194,7 +195,7 @@ public class KeyEntryDialog extends DialogComponentProvider {
String ksName = KeyBindingUtils.parseKeyStroke(ks); String ksName = KeyBindingUtils.parseKeyStroke(ks);
String text = keyBindings.getActionsForKeyStrokeText(ksName); String text = keyBindings.getActionsForKeyStrokeText(ksName);
try { try {
doc.insertString(0, text, textAttrSet); doc.insertString(0, text, textAttrs);
collisionPane.setCaretPosition(0); collisionPane.setCaretPosition(0);
} }
catch (BadLocationException e) { catch (BadLocationException e) {

View File

@ -26,6 +26,7 @@ import javax.swing.*;
import docking.widgets.combobox.GComboBox; import docking.widgets.combobox.GComboBox;
import docking.widgets.label.GDLabel; import docking.widgets.label.GDLabel;
import generic.theme.Gui;
import ghidra.util.Swing; import ghidra.util.Swing;
/** /**
@ -133,7 +134,7 @@ public class FontPropertyEditor extends PropertyEditorSupport {
JPanel panel = new JPanel(new GridLayout(2, 1)); JPanel panel = new JPanel(new GridLayout(2, 1));
GDLabel styleLabel = new GDLabel("Styles"); GDLabel styleLabel = new GDLabel("Styles");
styleLabel.setFont(getFont().deriveFont(1)); Gui.registerFont(styleLabel, Font.BOLD);
styleLabel.setHorizontalAlignment(SwingConstants.CENTER); styleLabel.setHorizontalAlignment(SwingConstants.CENTER);
panel.add(styleLabel); panel.add(styleLabel);
@ -150,7 +151,7 @@ public class FontPropertyEditor extends PropertyEditorSupport {
JPanel panel = new JPanel(new GridLayout(2, 1)); JPanel panel = new JPanel(new GridLayout(2, 1));
GDLabel sizeLabel = new GDLabel("Sizes"); GDLabel sizeLabel = new GDLabel("Sizes");
sizeLabel.setFont(getFont().deriveFont(1)); Gui.registerFont(sizeLabel, Font.BOLD);
sizeLabel.setHorizontalAlignment(SwingConstants.CENTER); sizeLabel.setHorizontalAlignment(SwingConstants.CENTER);
panel.add(sizeLabel); panel.add(sizeLabel);
@ -168,7 +169,7 @@ public class FontPropertyEditor extends PropertyEditorSupport {
JPanel panel = new JPanel(new GridLayout(2, 1)); JPanel panel = new JPanel(new GridLayout(2, 1));
GDLabel fontLabel = new GDLabel("Fonts"); GDLabel fontLabel = new GDLabel("Fonts");
fontLabel.setFont(getFont().deriveFont(1)); Gui.registerFont(fontLabel, Font.BOLD);
fontLabel.setHorizontalAlignment(SwingConstants.CENTER); fontLabel.setHorizontalAlignment(SwingConstants.CENTER);
panel.add(fontLabel); panel.add(fontLabel);

View File

@ -25,22 +25,32 @@ import javax.swing.plaf.basic.BasicHTML;
import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableCellRenderer;
import docking.widgets.label.GDHtmlLabel; import docking.widgets.label.GDHtmlLabel;
import generic.theme.GColor; import generic.theme.*;
import generic.theme.GColorUIResource;
import generic.theme.GThemeDefaults.Colors.Palette; import generic.theme.GThemeDefaults.Colors.Palette;
import generic.theme.GThemeDefaults.Colors.Tables; 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. * A common base class for list and table renderer objects, unifying the Ghidra look and feel.
* <p> * <p>
* It allows (but default-disables) HTML content, automatically paints alternating row * It allows (but default-disables) HTML content, automatically paints alternating row background
* background colors, and highlights the drop target in a drag-n-drop operation. * colors, and highlights the drop target in a drag-n-drop operation.
* * <p>
* 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 { public abstract class AbstractGCellRenderer extends GDHtmlLabel {
private static final Color BACKGROUND_COLOR = new GColor("color.bg.table.row"); 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 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 */ /** Allows the user to disable alternating row colors on JLists and JTables */
private static final String DISABLE_ALTERNATING_ROW_COLORS_PROPERTY = private static final String DISABLE_ALTERNATING_ROW_COLORS_PROPERTY =
"disable.alternating.row.colors"; "disable.alternating.row.colors";
@ -61,6 +71,9 @@ public abstract class AbstractGCellRenderer extends GDHtmlLabel {
private boolean instanceAlternateRowColors = true; private boolean instanceAlternateRowColors = true;
public AbstractGCellRenderer() { public AbstractGCellRenderer() {
setBaseFontId(BASE_FONT_ID);
noFocusBorder = BorderFactory.createEmptyBorder(0, 5, 0, 5); noFocusBorder = BorderFactory.createEmptyBorder(0, 5, 0, 5);
Border innerBorder = BorderFactory.createEmptyBorder(0, 4, 0, 4); Border innerBorder = BorderFactory.createEmptyBorder(0, 4, 0, 4);
Border outerBorder = BorderFactory.createLineBorder(Palette.YELLOW, 1); Border outerBorder = BorderFactory.createLineBorder(Palette.YELLOW, 1);
@ -114,34 +127,48 @@ public abstract class AbstractGCellRenderer extends GDHtmlLabel {
return getBackgroundColorForRow(row); 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 @Override
public void setFont(Font f) { public void setFont(Font f) {
super.setFont(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 String caller =
// getTableCellRenderer() is called, as it resets the font to the default font on each pass ReflectionUtilities.getClassNameOlderThan(getClass().getName(), "generic.theme");
protected void setBold() { Msg.debug(this, "Calling setFont() on the renderer is discouraged. " +
super.setFont(boldFont); "To change the font, call setBaseFontId(). Called from " + caller);
}
} }
/** /**
* Sets the row where DnD would perform drop operation. * Sets the font of this renderer to be bold until the next time that getTableCellRenderer() is
* @param dropRow the drop row * called, as it resets the font to the default font on each pass.
* @see #getDefaultFont()
*/ */
public void setDropRow(int dropRow) { protected void setBold() {
this.dropRow = dropRow; super.setFont(boldFont);
}
protected Border getNoFocusBorder() {
return noFocusBorder;
} }
protected Font getDefaultFont() { protected Font getDefaultFont() {
@ -156,6 +183,18 @@ public abstract class AbstractGCellRenderer extends GDHtmlLabel {
return boldFont; 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() { protected Color getDefaultBackgroundColor() {
return BACKGROUND_COLOR; return BACKGROUND_COLOR;
} }

View File

@ -72,7 +72,8 @@ public class DropDownTextField<T> extends JTextField implements GComponent {
new DropDownWindowVisibilityListener<>(); new DropDownWindowVisibilityListener<>();
private GDHtmlLabel previewLabel; private GDHtmlLabel previewLabel;
protected GList<T> list = new GList<>(); protected DropDownList list = new DropDownList();
private WeakSet<DropDownSelectionChoiceListener<T>> choiceListeners = private WeakSet<DropDownSelectionChoiceListener<T>> choiceListeners =
WeakDataStructureFactory.createSingleThreadAccessWeakSet(); WeakDataStructureFactory.createSingleThreadAccessWeakSet();
private Collection<CellEditorListener> cellEditorListeners = new HashSet<>(); private Collection<CellEditorListener> cellEditorListeners = new HashSet<>();
@ -82,7 +83,6 @@ public class DropDownTextField<T> extends JTextField implements GComponent {
private WindowComponentListener parentWindowListener = new WindowComponentListener(); private WindowComponentListener parentWindowListener = new WindowComponentListener();
private T selectedValue; private T selectedValue;
private int cellHeight;
private int matchingWindowHeight = MIN_HEIGHT; private int matchingWindowHeight = MIN_HEIGHT;
private Point lastLocation; private Point lastLocation;
protected final DropDownTextFieldDataModel<T> dataModel; protected final DropDownTextFieldDataModel<T> dataModel;
@ -278,15 +278,6 @@ public class DropDownTextField<T> extends JTextField implements GComponent {
private void initDataList() { 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.setCellRenderer(dataModel.getListRenderer());
list.addKeyListener(keyListener); list.addKeyListener(keyListener);
@ -654,7 +645,7 @@ public class DropDownTextField<T> extends JTextField implements GComponent {
* signalling to use the clicked item. When pressing Enter, they may have been typing and * 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. * 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() { private void setTextFromListOnEnterPress() {
Object selectedItem = list.getSelectedValue(); Object selectedItem = list.getSelectedValue();
if (selectedItem == null) { if (selectedItem == null) {
@ -747,6 +738,30 @@ public class DropDownTextField<T> extends JTextField implements GComponent {
// Inner Classes // Inner Classes
//================================================================================================= //=================================================================================================
protected class DropDownList extends GList<T> {
@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 { private class HideWindowFocusListener extends FocusAdapter {
@Override @Override
public void focusLost(FocusEvent event) { public void focusLost(FocusEvent event) {

View File

@ -15,7 +15,8 @@
*/ */
package docking.widgets.dialogs; package docking.widgets.dialogs;
import java.awt.*; import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.KeyAdapter; import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
@ -26,6 +27,7 @@ import docking.DockingUtils;
import docking.widgets.label.GDLabel; import docking.widgets.label.GDLabel;
import docking.widgets.label.GLabel; import docking.widgets.label.GLabel;
import generic.theme.GThemeDefaults.Colors.Messages; import generic.theme.GThemeDefaults.Colors.Messages;
import generic.theme.Gui;
import ghidra.framework.OperatingSystem; import ghidra.framework.OperatingSystem;
import ghidra.framework.Platform; import ghidra.framework.Platform;
@ -34,6 +36,8 @@ public class MultiLineInputDialog extends DialogComponentProvider {
private static final KeyStroke SUBMIT_KEYSTROKE = private static final KeyStroke SUBMIT_KEYSTROKE =
KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, DockingUtils.CONTROL_KEY_MODIFIER_MASK); KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, DockingUtils.CONTROL_KEY_MODIFIER_MASK);
private static final String FONT_ID = "font.input.hint";
private boolean isCanceled; private boolean isCanceled;
private JTextArea inputTextArea; private JTextArea inputTextArea;
@ -84,10 +88,7 @@ public class MultiLineInputDialog extends DialogComponentProvider {
} }
JLabel hintLabel = new GLabel("(" + metaKeyText + "-Enter to accept)"); JLabel hintLabel = new GLabel("(" + metaKeyText + "-Enter to accept)");
hintLabel.setHorizontalAlignment(SwingConstants.CENTER); hintLabel.setHorizontalAlignment(SwingConstants.CENTER);
Font font = hintLabel.getFont(); Gui.registerFont(hintLabel, FONT_ID);
Font smallerFont = font.deriveFont(12F);
Font smallItalicFont = smallerFont.deriveFont(Font.ITALIC);
hintLabel.setFont(smallItalicFont);
hintLabel.setForeground(Messages.HINT); hintLabel.setForeground(Messages.HINT);
dataPanel.add(messageLabel, BorderLayout.NORTH); dataPanel.add(messageLabel, BorderLayout.NORTH);

View File

@ -49,39 +49,54 @@ class DirectoryList extends GList<File> implements GhidraFileChooserDirectoryMod
/** /**
* Create a new DirectoryList instance. * Create a new DirectoryList instance.
* *
* @param chooser the {@link GhidraFileChooser} this instance is nested in * @param chooser the {@link GhidraFileChooser} this instance is nested in
* @param model the {@link DirectoryListModel} * @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); super(model);
this.chooser = chooser; this.chooser = chooser;
this.model = model; 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); setLayoutOrientation(JList.VERTICAL_WRAP);
FileListCellRenderer cellRenderer = new FileListCellRenderer(chooser); FileListCellRenderer cellRenderer = new FileListCellRenderer(chooser);
setCellRenderer(cellRenderer); setCellRenderer(cellRenderer);
// Enable the list to calculate the width of the cells on its own, but manually updateCellDimensions(getFont());
// 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);
addMouseListener(new GMouseListenerAdapter() { addMouseListener(new GMouseListenerAdapter() {
@Override @Override

View File

@ -558,7 +558,7 @@ public class GhidraFileChooser extends ReusableDialogComponentProvider implement
private JScrollPane buildDirectoryList() { private JScrollPane buildDirectoryList() {
directoryListModel = new DirectoryListModel(); directoryListModel = new DirectoryListModel();
directoryList = new DirectoryList(this, directoryListModel, rootPanel.getFont()); directoryList = new DirectoryList(this, directoryListModel);
directoryList.setName("LIST"); directoryList.setName("LIST");
directoryList.setBackground(BACKGROUND_COLOR); directoryList.setBackground(BACKGROUND_COLOR);

View File

@ -51,18 +51,17 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe
private static final Color BG_DRAG = new GColor("color.bg.table.row.drag"); 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. * manipulation are thread safe.
*/ */
private static Map<Integer, ThreadLocal<DecimalFormat>> decimalFormatCache = private static Map<Integer, ThreadLocal<DecimalFormat>> decimalFormatCache = new HashMap<>();
new HashMap<>();
static { static {
int n = FloatingPointPrecisionSettingsDefinition.MAX_PRECISION; int n = FloatingPointPrecisionSettingsDefinition.MAX_PRECISION;
for (int i = 0; i <= n; i++) { for (int i = 0; i <= n; i++) {
int precision = i; int precision = i;
ThreadLocal<DecimalFormat> localFormatter = ThreadLocal.withInitial( ThreadLocal<DecimalFormat> localFormatter =
() -> new DecimalFormat(createDecimalFormat(precision))); ThreadLocal.withInitial(() -> new DecimalFormat(createDecimalFormat(precision)));
decimalFormatCache.put(precision, localFormatter); decimalFormatCache.put(precision, localFormatter);
} }
} }
@ -84,7 +83,7 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe
/** /**
* Constructs a new GTableCellRenderer using the specified font. * Constructs a new GTableCellRenderer using the specified font.
* *
* @param f the font to use when rendering text in the table cells * @param f the font to use when rendering text in the table cells
*/ */
public GTableCellRenderer(Font f) { public GTableCellRenderer(Font f) {
@ -94,7 +93,7 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe
/** /**
* Return the cell renderer text * Return the cell renderer text
* *
* @param value Cell object value * @param value Cell object value
* @return A string interpretation of value; generated by calling value.toString() * @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, * 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 * 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. * passed through the {@link docking.widgets.table.GTableCellRenderingData} object.
* *
* @param data Context data used in the rendering of a data cell. * @param data Context data used in the rendering of a data cell.
* @return The component used for drawing the table 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(); Object value = data.getValue();
JTable table = data.getTable(); JTable table = data.getTable();
int row = data.getRowViewIndex(); int row = data.getRowViewIndex();
int column = data.getColumnViewIndex();
boolean isSelected = data.isSelected(); boolean isSelected = data.isSelected();
boolean hasFocus = data.hasFocus(); boolean hasFocus = data.hasFocus();
Settings settings = data.getColumnSettings(); Settings settings = data.getColumnSettings();
@ -173,7 +171,7 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe
} }
TableModel model = table.getModel(); TableModel model = table.getModel();
configureFont(table, model, column); setFont(getDefaultFont());
if (isSelected) { if (isSelected) {
setForeground(table.getSelectionForeground()); setForeground(table.getSelectionForeground());
@ -199,8 +197,14 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe
setForeground(table.getForeground()); 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) { protected int getRadix(Settings settings) {
@ -217,7 +221,7 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe
/** /**
* Format a Number per the Settings parameters. * Format a Number per the Settings parameters.
* *
* @param value the number to format * @param value the number to format
* @param settings settings controlling the display of the Number parameter * @param settings settings controlling the display of the Number parameter
* @return a formatted representation of the Number value * @return a formatted representation of the Number value

View File

@ -67,7 +67,7 @@ public class HintTextField extends JTextField {
/** /**
* Constructor * Constructor
* *
* @param hint the hint text * @param hint the hint text
* @param required true, if the field should be marked as required * @param required true, if the field should be marked as required
* @param verifier input verifier, or null if none needed * @param verifier input verifier, or null if none needed
@ -78,7 +78,6 @@ public class HintTextField extends JTextField {
this.verifier = verifier; this.verifier = verifier;
addListeners(); addListeners();
setFont(getFont().deriveFont(Font.PLAIN));
validateField(); validateField();
} }
@ -143,7 +142,7 @@ public class HintTextField extends JTextField {
/** /**
* Sets whether the field is required or not. If so, it will be rendered * Sets whether the field is required or not. If so, it will be rendered
* differently to indicate that to the user. * differently to indicate that to the user.
* *
* @param required true if required, false otherwise * @param required true if required, false otherwise
*/ */
public void setRequired(boolean required) { public void setRequired(boolean required) {
@ -161,7 +160,7 @@ public class HintTextField extends JTextField {
/** /**
* Returns true if the field contains valid input. * Returns true if the field contains valid input.
* *
* @return true if valid, false otherwise * @return true if valid, false otherwise
*/ */
public boolean isFieldValid() { 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. * field attributes.
*/ */
private void validateField() { private void validateField() {

View File

@ -28,6 +28,7 @@ import docking.ReusableDialogComponentProvider;
import docking.widgets.EmptyBorderButton; import docking.widgets.EmptyBorderButton;
import docking.widgets.label.GDLabel; import docking.widgets.label.GDLabel;
import generic.theme.GThemeDefaults.Colors.Messages; import generic.theme.GThemeDefaults.Colors.Messages;
import generic.theme.Gui;
import ghidra.util.*; import ghidra.util.*;
import help.Help; import help.Help;
import help.HelpService; import help.HelpService;
@ -47,6 +48,8 @@ public class WizardManager extends ReusableDialogComponentProvider implements Wi
private final static String INIT_TITLE = "<< untitled >>"; private final static String INIT_TITLE = "<< untitled >>";
private static final String FONT_ID = "font.wizard.border.title";
private PanelManager panelMgr; private PanelManager panelMgr;
private WizardPanel currWizPanel; private WizardPanel currWizPanel;
private JButton backButton; private JButton backButton;
@ -91,7 +94,7 @@ public class WizardManager extends ReusableDialogComponentProvider implements Wi
} }
/** /**
* *
* @see docking.wizard.WizardPanelListener#validityChanged() * @see docking.wizard.WizardPanelListener#validityChanged()
*/ */
@Override @Override
@ -108,7 +111,7 @@ public class WizardManager extends ReusableDialogComponentProvider implements Wi
return getStatusText(); return getStatusText();
} }
/** /**
* @see docking.wizard.WizardPanelListener#setStatusMessage(String) * @see docking.wizard.WizardPanelListener#setStatusMessage(String)
*/ */
@Override @Override
@ -220,8 +223,7 @@ public class WizardManager extends ReusableDialogComponentProvider implements Wi
titleLabel = (wizardIcon == null ? new GDLabel(INIT_TITLE) titleLabel = (wizardIcon == null ? new GDLabel(INIT_TITLE)
: new GDLabel(INIT_TITLE, wizardIcon, SwingConstants.TRAILING)); : new GDLabel(INIT_TITLE, wizardIcon, SwingConstants.TRAILING));
EmptyBorderButton helpButton = EmptyBorderButton helpButton = new EmptyBorderButton(Icons.INFO_ICON);
new EmptyBorderButton(Icons.INFO_ICON);
helpButton.setToolTipText("Help (F1)"); helpButton.setToolTipText("Help (F1)");
helpButton.addActionListener( helpButton.addActionListener(
e -> DockingWindowManager.getHelpService().showHelp(rootPanel, false, rootPanel)); e -> DockingWindowManager.getHelpService().showHelp(rootPanel, false, rootPanel));
@ -438,7 +440,7 @@ if (!visitedMap.containsKey(currWizPanel)) {
return; // nothing to do 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 // case
defaultFocusComponent.requestFocusInWindow(); defaultFocusComponent.requestFocusInWindow();
} }
@ -465,14 +467,12 @@ if (!visitedMap.containsKey(currWizPanel)) {
if (scrollPane.getVerticalScrollBar().isShowing()) { if (scrollPane.getVerticalScrollBar().isShowing()) {
TitledBorder titledBorder = TitledBorder titledBorder =
new TitledBorder(BorderFactory.createEmptyBorder(), "(scroll for more options)"); new TitledBorder(BorderFactory.createEmptyBorder(), "(scroll for more options)");
Gui.addThemeListener(e -> {
Font font = titledBorder.getTitleFont(); if (e.isFontChanged(FONT_ID)) {
if (font == null) { titledBorder.setTitleFont(Gui.getFont(FONT_ID));
// workaround for bug on Java 7 }
font = titleLabel.getFont(); });
} titledBorder.setTitleFont(Gui.getFont(FONT_ID));
titledBorder.setTitleFont(font.deriveFont(10f));
titledBorder.setTitleColor(Messages.NORMAL); titledBorder.setTitleColor(Messages.NORMAL);
titledBorder.setTitlePosition(TitledBorder.BOTTOM); titledBorder.setTitlePosition(TitledBorder.BOTTOM);
titledBorder.setTitleJustification(TitledBorder.TRAILING); titledBorder.setTitleJustification(TitledBorder.TRAILING);

View File

@ -15,20 +15,14 @@
*/ */
package ghidra.docking.util; package ghidra.docking.util;
import java.awt.Font;
import java.awt.Taskbar; 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 javax.swing.plaf.ComponentUI;
import docking.framework.ApplicationInformationDisplayFactory; import docking.framework.ApplicationInformationDisplayFactory;
import generic.theme.LafType; import generic.theme.LafType;
import generic.theme.ThemeManager; import generic.theme.ThemeManager;
import ghidra.framework.preferences.Preferences;
import ghidra.util.SystemUtilities;
/** /**
* A utility class to manage LookAndFeel (LaF) settings. * 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() { 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<Entry<Object, Object>> set = defaults.entrySet();
Iterator<Entry<Object, Object>> iterator = set.iterator();
while (iterator.hasNext()) {
Entry<Object, Object> 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() { public static void performPlatformSpecificFixups() {

View File

@ -28,6 +28,7 @@ import org.apache.commons.lang3.StringUtils;
import docking.widgets.EmptyBorderButton; import docking.widgets.EmptyBorderButton;
import docking.widgets.OptionDialog; import docking.widgets.OptionDialog;
import docking.widgets.label.GDHtmlLabel; import docking.widgets.label.GDHtmlLabel;
import generic.theme.Gui;
import ghidra.util.Swing; import ghidra.util.Swing;
import ghidra.util.datastruct.WeakDataStructureFactory; import ghidra.util.datastruct.WeakDataStructureFactory;
import ghidra.util.datastruct.WeakSet; import ghidra.util.datastruct.WeakSet;
@ -43,6 +44,8 @@ import resources.Icons;
*/ */
public class TaskMonitorComponent extends JPanel implements TaskMonitor { public class TaskMonitorComponent extends JPanel implements TaskMonitor {
private static final String MESSAGE_FONT_ID = "font.task.monitor.label.message";
private WeakSet<CancelledListener> listeners = private WeakSet<CancelledListener> listeners =
WeakDataStructureFactory.createCopyOnReadWeakSet(); WeakDataStructureFactory.createCopyOnReadWeakSet();
@ -458,7 +461,7 @@ public class TaskMonitorComponent extends JPanel implements TaskMonitor {
// don't care // don't care
} }
}; };
messageLabel.setFont(messageLabel.getFont().deriveFont((float) 10.0)); Gui.registerFont(messageLabel, MESSAGE_FONT_ID);
Dimension d = messageLabel.getPreferredSize(); Dimension d = messageLabel.getPreferredSize();
d.width = 180; d.width = 180;
messageLabel.setPreferredSize(d); messageLabel.setPreferredSize(d);

View File

@ -35,7 +35,7 @@ public class ReflectionUtilitiesTest {
@Test @Test
public void testGetClassNameAfter_NoClasses() { public void testGetClassNameAfter_NoClasses() {
String caller = ReflectionUtilities.getClassNameOlderThan(); String caller = ReflectionUtilities.getClassNameOlderThan(new String[0]);
assertThat(caller, is(equalTo(ReflectionUtilitiesTest.class.getName()))); assertThat(caller, is(equalTo(ReflectionUtilitiesTest.class.getName())));
} }

View File

@ -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.selected = color.palette.lime
color.visualgraph.view.satellite.edge.hovered = color.palette.lime color.visualgraph.view.satellite.edge.hovered = color.palette.lime
color.graphdisplay.vertex.default = color.palette.green color.graphdisplay.vertex.default = color.palette.green
color.graphdisplay.edge.default = color.palette.green color.graphdisplay.edge.default = color.palette.green
color.graphdisplay.vertex.selected = color.palette.blue color.graphdisplay.vertex.selected = color.palette.blue
color.graphdisplay.edge.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 = network-wireless-16.png
icon.graph.satellite.large = network-wireless.png icon.graph.satellite.large = network-wireless.png
icon.graph.layout.default = color_swatch.png icon.graph.layout.default = color_swatch.png

View File

@ -27,6 +27,7 @@ import docking.widgets.label.GDLabel;
import edu.uci.ics.jung.visualization.RenderContext; import edu.uci.ics.jung.visualization.RenderContext;
import edu.uci.ics.jung.visualization.VisualizationViewer; import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.ScalingControl; import edu.uci.ics.jung.visualization.control.ScalingControl;
import generic.theme.Gui;
import ghidra.graph.VisualGraph; import ghidra.graph.VisualGraph;
import ghidra.graph.viewer.event.mouse.VertexTooltipProvider; import ghidra.graph.viewer.event.mouse.VertexTooltipProvider;
import ghidra.graph.viewer.event.mouse.VisualGraphMousePlugin; 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. * 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. * This class will contain all UI widgets need to display and interact with a graph.
* *
* <p><b><u>Implementation Note:</u></b> * <p><b><u>Implementation Note:</u></b>
* <ol> * <ol>
* <li>The graph of this component can be null, changing to non-null values over the * <li>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 * lifetime of this view. This allows this view to be installed in a UI component, with the
* contents changing as needed. * contents changing as needed.
* </li> * </li>
* <li> * <li>
* When the graph is {@link #setGraph(VisualGraph) set}, the view portion of the class is * When the graph is {@link #setGraph(VisualGraph) set}, the view portion of the class is
* recreated. * recreated.
* </li> * </li>
* <li> * <li>
* 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 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. * This state is atypical and makes this class a bit harder to understand.
* </li> * </li>
@ -60,14 +61,16 @@ import ghidra.graph.viewer.vertex.VertexFocusListener;
* @param <G> the graph type * @param <G> the graph type
*/ */
//@formatter:off //@formatter:off
public class VisualGraphView<V extends VisualVertex, public class VisualGraphView<V extends VisualVertex,
E extends VisualEdge<V>, E extends VisualEdge<V>,
G extends VisualGraph<V, E>> { G extends VisualGraph<V, E>> {
//@formatter:on //@formatter:on
private static final float ZOOM_OUT_AMOUNT = .9f; private static final float ZOOM_OUT_AMOUNT = .9f;
private static final float ZOOM_IN_AMOUNT = 1.1f; 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 viewPanel;
private JPanel viewContentPanel; private JPanel viewContentPanel;
@ -76,7 +79,7 @@ public class VisualGraphView<V extends VisualVertex,
* As graph data is updated, we set and clear the contents of this panel as needed. This * As graph data is updated, we set and clear the contents of this panel as needed. This
* allows the client to initialize the satellite window once, with updates controlled by * allows the client to initialize the satellite window once, with updates controlled by
* this class. * this class.
* *
* Note: this panel will be empty when docked and when the viewer is not yet built * Note: this panel will be empty when docked and when the viewer is not yet built
*/ */
private JPanel undockedSatelliteContentPanel; private JPanel undockedSatelliteContentPanel;
@ -99,7 +102,7 @@ public class VisualGraphView<V extends VisualVertex,
private Optional<GraphSatelliteListener> clientSatelliteListener = Optional.empty(); private Optional<GraphSatelliteListener> 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 // graph component, as well as how we notify the client listener
private GraphSatelliteListener internalSatelliteListener = (docked, visible) -> { private GraphSatelliteListener internalSatelliteListener = (docked, visible) -> {
@ -190,10 +193,10 @@ public class VisualGraphView<V extends VisualVertex,
} }
/** /**
* Sets a listener that allows clients to be notified of vertex double-clicks. Normal * Sets a listener that allows clients to be notified of vertex double-clicks. Normal
* mouse processing is handled by the {@link VisualGraphMousePlugin} class. This is a * mouse processing is handled by the {@link VisualGraphMousePlugin} class. This is a
* convenience method so that clients do not have to deal with the mouse plugin. * convenience method so that clients do not have to deal with the mouse plugin.
* *
* @param l the listener * @param l the listener
*/ */
public void setVertexClickListener(VertexClickListener<V, E> l) { public void setVertexClickListener(VertexClickListener<V, E> l) {
@ -290,9 +293,9 @@ public class VisualGraphView<V extends VisualVertex,
} }
/** /**
* Returns the primary viewer of the graph (as opposed to the satellite viewer). The * Returns the primary viewer of the graph (as opposed to the satellite viewer). The
* viewer returned is responsible for maintaining view information for a given graph. * viewer returned is responsible for maintaining view information for a given graph.
* *
* @return the primary viewer * @return the primary viewer
*/ */
public GraphViewer<V, E> getPrimaryGraphViewer() { public GraphViewer<V, E> getPrimaryGraphViewer() {
@ -308,7 +311,7 @@ public class VisualGraphView<V extends VisualVertex,
/** /**
* Sets the perspective for this view * Sets the perspective for this view
* *
* @param newPerspective the new perspective * @param newPerspective the new perspective
*/ */
public void setGraphPerspective(GraphPerspectiveInfo<V, E> newPerspective) { public void setGraphPerspective(GraphPerspectiveInfo<V, E> newPerspective) {
@ -350,8 +353,7 @@ public class VisualGraphView<V extends VisualVertex,
viewContentPanel.removeAll(); viewContentPanel.removeAll();
viewContentPanel.paintImmediately(viewContentPanel.getBounds()); viewContentPanel.paintImmediately(viewContentPanel.getBounds());
JLabel messageLabel = new GDLabel(errorMessage); JLabel messageLabel = new GDLabel(errorMessage);
Font font = messageLabel.getFont(); Gui.registerFont(messageLabel, MESSAGE_FONT_ID);
messageLabel.setFont(font.deriveFont(22f)); // make a bit bigger for readability
messageLabel.setHorizontalAlignment(SwingConstants.CENTER); messageLabel.setHorizontalAlignment(SwingConstants.CENTER);
messageLabel.setFocusable(true); // we have to have something focusable in our provider messageLabel.setFocusable(true); // we have to have something focusable in our provider
viewContentPanel.add(messageLabel, BorderLayout.NORTH); viewContentPanel.add(messageLabel, BorderLayout.NORTH);
@ -362,8 +364,8 @@ public class VisualGraphView<V extends VisualVertex,
/** /**
* Sets a message to be painted on the viewer. This is useful to show a text message to the * Sets a message to be painted on the viewer. This is useful to show a text message to the
* user. Passing null will clear the message. * user. Passing null will clear the message.
* *
* @param message the status message * @param message the status message
*/ */
public void setStatusMessage(String message) { public void setStatusMessage(String message) {
if (graphComponent != null) { if (graphComponent != null) {
@ -377,10 +379,10 @@ public class VisualGraphView<V extends VisualVertex,
/** /**
* Returns whether the satellite intended to be visible. If this component is built, then * Returns whether the satellite intended to be visible. If this component is built, then
* a result of true means that the satellite is showing. If the component is not yet * a result of true means that the satellite is showing. If the component is not yet
* built, then a result of true means that the satellite will be made visible when the * built, then a result of true means that the satellite will be made visible when the
* component is built. * component is built.
* *
* @return true if visible * @return true if visible
*/ */
public boolean isSatelliteVisible() { public boolean isSatelliteVisible() {
@ -421,10 +423,10 @@ public class VisualGraphView<V extends VisualVertex,
/** /**
* Returns whether the satellite intended to be docked. If this component is built, then * Returns whether the satellite intended to be docked. If this component is built, then
* a result of true means that the satellite is docked. If the component is not yet * a result of true means that the satellite is docked. If the component is not yet
* built, then a result of true means that the satellite will be made docked when the * built, then a result of true means that the satellite will be made docked when the
* component is built. * component is built.
* *
* @return true if visible * @return true if visible
*/ */
public boolean isSatelliteDocked() { public boolean isSatelliteDocked() {
@ -517,8 +519,8 @@ public class VisualGraphView<V extends VisualVertex,
} }
public Point translatePointFromVertexToViewSpace(V v, Point p) { public Point translatePointFromVertexToViewSpace(V v, Point p) {
return GraphViewerUtils.translatePointFromVertexRelativeSpaceToViewSpace( return GraphViewerUtils
getPrimaryGraphViewer(), v, p); .translatePointFromVertexRelativeSpaceToViewSpace(getPrimaryGraphViewer(), v, p);
} }
public Rectangle translateRectangleFromVertexToViewSpace(V v, Rectangle r) { public Rectangle translateRectangleFromVertexToViewSpace(V v, Rectangle r) {
@ -577,7 +579,7 @@ public class VisualGraphView<V extends VisualVertex,
} }
/** /**
* Effectively clears this display. This method is not called dispose, as that implies * Effectively clears this display. This method is not called dispose, as that implies
* the end of an object's lifecycle. This object can be re-used after this method is * the end of an object's lifecycle. This object can be re-used after this method is
* called. * called.
*/ */

View File

@ -34,7 +34,8 @@ color.fg.tree.selected = [color]system.color.fg.selected.view
// Fonts // Fonts
font.standard = [font]system.font.control font.standard = [font]system.font.control
font.monospaced = monospaced-PLAIN-12 font.standard.bold = font.standard[bold]
font.monospaced = monospaced-plain-12
// //

View File

@ -298,6 +298,11 @@ public class ApplicationThemeManager extends ThemeManager {
lookAndFeelManager.registerFont(component, fontId); lookAndFeelManager.registerFont(component, fontId);
} }
@Override
public void registerFont(Component component, String fontId, int fontStyle) {
lookAndFeelManager.registerFont(component, fontId, fontStyle);
}
private void installFlatLookAndFeels() { private void installFlatLookAndFeels() {
UIManager.installLookAndFeel(LafType.FLAT_LIGHT.getName(), FlatLightLaf.class.getName()); UIManager.installLookAndFeel(LafType.FLAT_LIGHT.getName(), FlatLightLaf.class.getName());
UIManager.installLookAndFeel(LafType.FLAT_DARK.getName(), FlatDarkLaf.class.getName()); UIManager.installLookAndFeel(LafType.FLAT_DARK.getName(), FlatDarkLaf.class.getName());

View File

@ -68,7 +68,7 @@ public class FontModifier {
} }
/** /**
* Sets the font stle modifier. This can be called multiple times to bold and italicize. * Sets the font style modifier. This can be called multiple times to bold and italicize.
* @param newStyle the style to use for the font. * @param newStyle the style to use for the font.
*/ */
public void addStyleModifier(int newStyle) { public void addStyleModifier(int newStyle) {

View File

@ -0,0 +1,57 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package generic.theme;
import java.awt.Font;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import ghidra.util.HTMLUtilities;
/**
* A drop-in replacement for clients using {@link SimpleAttributeSet}s. This class will apply a
* default set of font attributes based on the given font and optional color.
*/
public class GAttributes extends SimpleAttributeSet {
public GAttributes(Font f) {
this(f, null);
}
public GAttributes(Font f, GColor c) {
addAttribute(StyleConstants.FontFamily, f.getFamily());
addAttribute(StyleConstants.FontSize, f.getSize());
addAttribute(StyleConstants.Bold, f.isBold());
addAttribute(StyleConstants.Italic, f.isItalic());
if (c != null) {
addAttribute(StyleConstants.Foreground, c);
}
}
/**
* A convenience method to style the given text in HTML using the font and color attributes
* defined in this attribute set. The text will be HTML escaped.
*
* @param content the content
* @return the styled content
* @see HTMLUtilities#styleText(SimpleAttributeSet, String)
*/
public String toStyledHtml(String content) {
return HTMLUtilities.styleText(this, content);
}
}

View File

@ -17,8 +17,9 @@ package generic.theme;
import java.awt.*; import java.awt.*;
import javax.swing.Icon; import javax.swing.*;
import javax.swing.LookAndFeel;
import ghidra.util.Msg;
/** /**
* Provides a static set of methods for globally managing application themes and their values. * Provides a static set of methods for globally managing application themes and their values.
@ -36,6 +37,8 @@ import javax.swing.LookAndFeel;
* *
*/ */
public class Gui { public class Gui {
private static final String FONT_SUFFIX = ".font";
// Start with an StubThemeManager so that simple tests can operate without having // Start with an StubThemeManager so that simple tests can operate without having
// to initialize the theme system. Applications and integration tests will // to initialize the theme system. Applications and integration tests will
// called ThemeManager.initialize() which will replace this with a fully initialized version. // called ThemeManager.initialize() which will replace this with a fully initialized version.
@ -146,6 +149,9 @@ public class Gui {
/** /**
* Binds the component to the font identified by the given font id. Whenever the font for * 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. * the font id changes, the component will updated with the new font.
* <p>
* Calling this method will trigger a call to {@link JComponent#setFont(Font)}.
*
* @param component the component to set/update the font * @param component the component to set/update the font
* @param fontId the id of the font to register with the given component * @param fontId the id of the font to register with the given component
*/ */
@ -153,6 +159,37 @@ public class Gui {
themeManager.registerFont(component, fontId); 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.
* <P>
* Most clients should <b>not</b> be using this method. Instead, use
* {@link #registerFont(JComponent, int)}.
* <P>
* 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 * Returns true if the active theme is using dark defaults
* @return true if the active theme is using dark defaults * @return true if the active theme is using dark defaults

View File

@ -575,6 +575,21 @@ public abstract class ThemeManager {
// do nothing // 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.
* <p>
* 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. * Returns true if the current theme use dark default values.
* @return true if the current theme use dark default values. * @return true if the current theme use dark default values.

View File

@ -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. * for the font id, this class will update the component's font to the new value.
*/ */
public class ComponentFontRegistry { public class ComponentFontRegistry {
private WeakSet<Component> components = WeakDataStructureFactory.createCopyOnReadWeakSet(); private WeakSet<StyledComponent> components =
WeakDataStructureFactory.createCopyOnReadWeakSet();
private String fontId; private String fontId;
/** /**
@ -45,8 +46,18 @@ public class ComponentFontRegistry {
* @param component the component to add * @param component the component to add
*/ */
public void addComponent(Component component) { public void addComponent(Component component) {
component.setFont(Gui.getFont(fontId)); addComponent(component, Font.PLAIN);
components.add(component); }
/**
* 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() { public void updateComponentFonts() {
Font font = Gui.getFont(fontId); 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(); Font existingFont = component.getFont();
if (!Objects.equals(existingFont, font)) { Font styledFont = font;
component.setFont(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);
} }
} }
} }

View File

@ -30,6 +30,7 @@ import generic.theme.*;
import generic.util.action.*; import generic.util.action.*;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.SystemUtilities; import ghidra.util.SystemUtilities;
import utilities.util.reflection.ReflectionUtilities;
/** /**
* Manages installing and updating a {@link LookAndFeel} * Manages installing and updating a {@link LookAndFeel}
@ -38,6 +39,7 @@ public abstract class LookAndFeelManager {
private LafType laf; private LafType laf;
private Map<String, ComponentFontRegistry> fontRegistryMap = new HashMap<>(); private Map<String, ComponentFontRegistry> fontRegistryMap = new HashMap<>();
private Map<Component, String> componentToIdMap = new WeakHashMap<>();
protected ApplicationThemeManager themeManager; protected ApplicationThemeManager themeManager;
protected Map<String, String> normalizedIdToLafIdMap; protected Map<String, String> normalizedIdToLafIdMap;
@ -158,7 +160,7 @@ public abstract class LookAndFeelManager {
* Called when one or more fonts have changed. * Called when one or more fonts have changed.
* <p> * <p>
* This will update the Java {@link UIManager} and trigger a reload of the UIs. * 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 * @param changedFontIds the set of Java Font ids that are affected by this change; these are
* the normalized ids * the normalized ids
*/ */
@ -202,12 +204,49 @@ public abstract class LookAndFeelManager {
* @param fontId the id of the font to register with the given component * @param fontId the id of the font to register with the given component
*/ */
public void registerFont(Component component, String fontId) { public void registerFont(Component component, String fontId) {
checkForAlreadyRegistered(component, fontId);
componentToIdMap.put(component, fontId);
ComponentFontRegistry register = ComponentFontRegistry register =
fontRegistryMap.computeIfAbsent(fontId, id -> new ComponentFontRegistry(id)); fontRegistryMap.computeIfAbsent(fontId, id -> new ComponentFontRegistry(id));
register.addComponent(component); 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.
* <p>
* 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) { private Font toUiResource(Font font) {
if (!(font instanceof UIResource)) { if (!(font instanceof UIResource)) {
return new FontUIResource(font); return new FontUIResource(font);
@ -292,8 +331,7 @@ public abstract class LookAndFeelManager {
return false; return false;
} }
protected void setKeyBinding(String existingKsText, String newKsText, protected void setKeyBinding(String existingKsText, String newKsText, String[] prefixValues) {
String[] prefixValues) {
KeyStroke existingKs = KeyStroke.getKeyStroke(existingKsText); KeyStroke existingKs = KeyStroke.getKeyStroke(existingKsText);
KeyStroke newKs = KeyStroke.getKeyStroke(newKsText); KeyStroke newKs = KeyStroke.getKeyStroke(newKsText);

View File

@ -153,8 +153,8 @@ public class UiDefaultsMapper {
* the user changeable values for affecting the Java LookAndFeel colors, fonts, and icons. * the user changeable values for affecting the Java LookAndFeel colors, fonts, and icons.
* <p> * <p>
* The keys in the returned map have been normalized and all start with 'laf.' * 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 * @return a map of changeable values that affect java LookAndFeel values
*/ */
public GThemeValueMap getNormalizedJavaDefaults() { 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 * 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 * 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. * the UiDefaults so that the LookAndFeel will pick up and use the changes.
* *
* @return a mapping of normalized LaF ids to original LaF ids. * @return a mapping of normalized LaF ids to original LaF ids.
*/ */
public Map<String, String> getNormalizedIdToLafIdMap() { public Map<String, String> getNormalizedIdToLafIdMap() {
@ -281,7 +281,7 @@ public class UiDefaultsMapper {
/** /**
* This allows clients to hard-code a chosen color for a group * This allows clients to hard-code a chosen color for a group
* *
* @param group the system color id to assign the given color * @param group the system color id to assign the given color
* @param color the color to be assigned to the system color id * @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 * This allows clients to hard-code a chosen font for a group
* *
* @param group the system font id to assign the given font * @param group the system font id to assign the given font
* @param font the font to be assigned to the system font id * @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 * 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 * value (Color or Font). This grouper allows us to specify the precedence to use when
* searching for the best group. * searching for the best group.
* *
* @param <T> The theme value type (Color or Font) * @param <T> The theme value type (Color or Font)
*/ */
private abstract class ValueGrouper<T> { private abstract class ValueGrouper<T> {

View File

@ -22,9 +22,10 @@ import java.util.regex.Pattern;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.plaf.basic.BasicHTML; import javax.swing.plaf.basic.BasicHTML;
import javax.swing.text.View; import javax.swing.text.*;
import generic.text.TextLayoutGraphics; import generic.text.TextLayoutGraphics;
import generic.theme.GAttributes;
import ghidra.util.html.HtmlLineSplitter; import ghidra.util.html.HtmlLineSplitter;
import utilities.util.reflection.ReflectionUtilities; import utilities.util.reflection.ReflectionUtilities;
@ -343,6 +344,67 @@ public class HTMLUtilities {
return buffy.toString(); 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:
*
* <UL>
* <LI>{@link StyleConstants#Foreground} - {@link Color} object</LI>
* <LI>{@link StyleConstants#FontFamily} - font name</LI>
* <LI>{@link StyleConstants#FontSize} - size in pixels</LI>
* <LI>{@link StyleConstants#Italic} - true if italic</LI>
* <LI>{@link StyleConstants#Bold} - true if bold</LI>
* </UL>
* <P>
* 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 """
<SPAN STYLE=\"%s font-family: '%s'; font-size: %spx; font-style: %s; font-weight: %s;\">\
%s\
</SPAN>
""".formatted(color, family, size, style, weight, escaped);
//@formatter:on
}
/** /**
* Returns the given text wrapped in {@link #LINK_PLACEHOLDER_OPEN} and close tags. * Returns the given text wrapped in {@link #LINK_PLACEHOLDER_OPEN} and close tags.
* If <code>foo</code> is passed for the HTML text, with a content value of <code>123456</code>, then * If <code>foo</code> is passed for the HTML text, with a content value of <code>123456</code>, then
@ -510,7 +572,7 @@ public class HTMLUtilities {
/** /**
* See {@link #friendlyEncodeHTML(String)} * See {@link #friendlyEncodeHTML(String)}
* *
* @param text string to be encoded * @param text string to be encoded
* @param skipLeadingWhitespace true signals to ignore any leading whitespace characters. * @param skipLeadingWhitespace true signals to ignore any leading whitespace characters.
* This is useful when line wrapping to force wrapped lines to the left * 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. * Calling this twice will result in text being double-escaped, which will not display correctly.
* <p> * <p>
* See also <code>StringEscapeUtils#escapeHtml3(String)</code> if you need quote-safe html encoding. * See also <code>StringEscapeUtils#escapeHtml3(String)</code> if you need quote-safe html encoding.
* <p> *
*
* @param text plain-text that might have some characters that should NOT be interpreted as HTML * @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} * @param makeSpacesNonBreaking true to convert spaces into {@value #HTML_SPACE}
* @return string with any html characters replaced with equivalents * @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. * 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 * @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 * @return string with any html characters replaced with equivalents
* @see #escapeHTML(String, boolean) * @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 * 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 * being added to a HTML document because it is non-printable or a non-standard control
* character * character
* *
* @param codePoint character to test * @param codePoint character to test
* @return boolean true if character should be escaped * @return boolean true if character should be escaped
*/ */

View File

@ -84,8 +84,12 @@ icon.plugin.manager.default = plasma.png
font.help.about = font.monospaced font.help.about = font.monospaced
font.keybindings.status = sansserif-plain-11 font.keybindings.status = sansserif-plain-11
font.task.viewer = sansserif-bold-36 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

View File

@ -15,7 +15,8 @@
*/ */
package ghidra.framework.main; package ghidra.framework.main;
import java.awt.*; import java.awt.BorderLayout;
import java.awt.Insets;
import java.io.InputStream; import java.io.InputStream;
import javax.swing.*; import javax.swing.*;
@ -57,11 +58,10 @@ public class UserAgreementDialog extends DialogComponentProvider {
} }
private JComponent buildWorkPanel() { private JComponent buildWorkPanel() {
Font font = Gui.getFont(FONT_ID);
JPanel panel = new JPanel(new BorderLayout()); JPanel panel = new JPanel(new BorderLayout());
JLabel label = new GDLabel("Ghidra User Agreement", SwingConstants.CENTER); JLabel label = new GDLabel("Ghidra User Agreement", SwingConstants.CENTER);
label.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0)); 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.add(label, BorderLayout.NORTH);
panel.setBorder(BorderFactory.createEmptyBorder(10, 40, 40, 40)); panel.setBorder(BorderFactory.createEmptyBorder(10, 40, 40, 40));
JEditorPane editorPane = new JEditorPane(); JEditorPane editorPane = new JEditorPane();

View File

@ -23,6 +23,7 @@ import java.util.List;
import javax.swing.*; import javax.swing.*;
import docking.widgets.label.GDLabel; import docking.widgets.label.GDLabel;
import generic.theme.Gui;
import ghidra.framework.client.RepositoryAdapter; import ghidra.framework.client.RepositoryAdapter;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.remote.User; import ghidra.framework.remote.User;
@ -33,9 +34,9 @@ import ghidra.framework.remote.User;
*/ */
public class ViewProjectAccessPanel extends ProjectAccessPanel { public class ViewProjectAccessPanel extends ProjectAccessPanel {
/** /**
* Construct a new panel. * Construct a new panel.
* *
* @param repository handle to the repository adapter * @param repository handle to the repository adapter
* @param tool the plugin tool * @param tool the plugin tool
* @throws IOException if there's an error processing repository information * @throws IOException if there's an error processing repository information
@ -47,13 +48,13 @@ public class ViewProjectAccessPanel extends ProjectAccessPanel {
/** /**
* Constructs a new panel. * Constructs a new panel.
* *
* @param knownUsers names of the users that are known to the remote server * @param knownUsers names of the users that are known to the remote server
* @param currentUser the current user * @param currentUser the current user
* @param allUsers all users known to the repository * @param allUsers all users known to the repository
* @param repositoryName the name of the repository * @param repositoryName the name of the repository
* @param anonymousServerAccessAllowed true if the server allows anonymous access * @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) * (ignored if anonymousServerAccessAllowed is false)
* @param tool the current tool * @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. * panels.
*/ */
@Override @Override
@ -82,9 +83,7 @@ public class ViewProjectAccessPanel extends ProjectAccessPanel {
if (anonymousServerAccessAllowed && origAnonymousAccessEnabled) { if (anonymousServerAccessAllowed && origAnonymousAccessEnabled) {
JLabel anonymousAccessLabel = new GDLabel("Anonymous Read-Only Access Enabled"); JLabel anonymousAccessLabel = new GDLabel("Anonymous Read-Only Access Enabled");
anonymousAccessLabel.setBorder(BorderFactory.createEmptyBorder(5, 2, 0, 0)); anonymousAccessLabel.setBorder(BorderFactory.createEmptyBorder(5, 2, 0, 0));
Font f = anonymousAccessLabel.getFont().deriveFont(Font.ITALIC); Gui.registerFont(anonymousAccessLabel, Font.ITALIC);
anonymousAccessLabel.setFont(f);
mainPanel.add(anonymousAccessLabel, BorderLayout.SOUTH); mainPanel.add(anonymousAccessLabel, BorderLayout.SOUTH);
} }

View File

@ -17,79 +17,57 @@ package ghidra.framework.plugintool.dialog;
import static ghidra.util.HTMLUtilities.*; import static ghidra.util.HTMLUtilities.*;
import java.awt.*; import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.*; import javax.swing.*;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import docking.widgets.label.GDHtmlLabel; import docking.widgets.label.GDHtmlLabel;
import generic.theme.GColor; import generic.theme.*;
import ghidra.util.HTMLUtilities;
/** /**
* Abstract class that defines a panel for displaying name/value pairs with html-formatting. * Abstract class that defines a panel for displaying name/value pairs with html-formatting.
*/ */
public abstract class AbstractDetailsPanel extends JPanel { 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; private static final int MIN_WIDTH = 700;
protected static final int LEFT_COLUMN_WIDTH = 150; protected static final int LEFT_COLUMN_WIDTH = 150;
protected static final int RIGHT_MARGIN = 30; protected static final int RIGHT_MARGIN = 30;
// Font attributes for the title of each row. // Font attributes for the title of each row.
protected static SimpleAttributeSet titleAttrSet; protected static GAttributes titleAttrs;
protected JLabel textLabel; protected JLabel textLabel;
protected JScrollPane sp; 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. * panel.
*/ */
protected abstract void createFieldAttributes(); protected abstract void createFieldAttributes();
/** protected abstract void refresh();
* 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:
* <ul>
* <li>FontFamily: "Tahoma"</li>
* <li>FontSize: 11</li>
* <li>Bold: True</li>
* </ul>
*
* @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;
}
/** /**
* Clears the text in the details pane. * 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 * 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. * for inserting the name of each row in the description text.
* *
* @param buffer the string buffer to add to * @param buffer the string buffer to add to
* @param rowName the name of the row to add * @param rowName the name of the row to add
*/ */
protected void insertRowTitle(StringBuilder buffer, String rowName) { protected void insertRowTitle(StringBuilder buffer, String rowName) {
buffer.append("<TR>"); buffer.append("<TR>");
buffer.append("<TD VALIGN=\"TOP\">"); buffer.append("<TD VALIGN=\"TOP\">");
insertHTMLLine(buffer, rowName + ":", titleAttrSet); insertHTMLLine(buffer, rowName + ":", titleAttrs);
buffer.append("</TD>"); buffer.append("</TD>");
} }
/** /**
* Inserts an html-formatted string into the given buffer. This is meant to be used * 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. * for inserting the value of each row in the description text.
* *
* @param buffer the string buffer to add to * @param buffer the string buffer to add to
* @param value the text to add * @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, protected void insertRowValue(StringBuilder buffer, String value, GAttributes attributes) {
SimpleAttributeSet attributes) {
buffer.append("<TD VALIGN=\"TOP\" WIDTH=\"80%\">"); buffer.append("<TD VALIGN=\"TOP\" WIDTH=\"80%\">");
insertHTMLLine(buffer, value, attributes); insertHTMLLine(buffer, value, attributes);
buffer.append("</TD>"); buffer.append("</TD>");
@ -161,33 +138,13 @@ public abstract class AbstractDetailsPanel extends JPanel {
* @param string the string to add * @param string the string to add
* @param attributes the formatting instructions * @param attributes the formatting instructions
*/ */
protected void insertHTMLString(StringBuilder buffer, String string, protected void insertHTMLString(StringBuilder buffer, String string, GAttributes attributes) {
SimpleAttributeSet attributes) {
if (string == null) { if (string == null) {
return; return;
} }
buffer.append("<FONT COLOR=\""); buffer.append(attributes.toStyledHtml(string));
Color foregroundColor = (Color) attributes.getAttribute(StyleConstants.Foreground);
buffer.append(HTMLUtilities.toHexString(foregroundColor));
buffer.append("\" FACE=\"");
buffer.append(attributes.getAttribute(StyleConstants.FontFamily).toString());
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("</FONT>");
} }
/** /**
@ -196,8 +153,7 @@ public abstract class AbstractDetailsPanel extends JPanel {
* @param string the string to insert * @param string the string to insert
* @param attributes the attributes to apply * @param attributes the attributes to apply
*/ */
protected void insertHTMLLine(StringBuilder buffer, String string, protected void insertHTMLLine(StringBuilder buffer, String string, GAttributes attributes) {
SimpleAttributeSet attributes) {
if (string == null) { if (string == null) {
return; return;
} }

View File

@ -15,17 +15,16 @@
*/ */
package ghidra.framework.plugintool.dialog; package ghidra.framework.plugintool.dialog;
import java.awt.Font;
import java.awt.Point; import java.awt.Point;
import java.util.*; import java.util.*;
import javax.swing.KeyStroke; import javax.swing.KeyStroke;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import docking.action.DockingActionIf; import docking.action.DockingActionIf;
import docking.action.MenuData; import docking.action.MenuData;
import docking.actions.KeyBindingUtils; import docking.actions.KeyBindingUtils;
import generic.theme.GColor; import generic.theme.*;
import ghidra.framework.plugintool.PluginConfigurationModel; import ghidra.framework.plugintool.PluginConfigurationModel;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.PluginDescription; import ghidra.framework.plugintool.util.PluginDescription;
@ -37,29 +36,52 @@ import ghidra.util.HTMLUtilities;
*/ */
class PluginDetailsPanel extends AbstractDetailsPanel { class PluginDetailsPanel extends AbstractDetailsPanel {
private SimpleAttributeSet nameAttrSet; private static final GColor NO_VALUE_COLOR = new GColor("color.fg.pluginpanel.details.novalue");
private SimpleAttributeSet depNameAttrSet; private static final GColor DEPENDENCY_COLOR =
private SimpleAttributeSet descrAttrSet; new GColor("color.fg.pluginpanel.details.dependency");
private SimpleAttributeSet categoriesAttrSet; private static final GColor LOCATION_COLOR = new GColor("color.fg.pluginpanel.details.loc");
private SimpleAttributeSet classAttrSet; private static final GColor DEVELOPER_COLOR =
private SimpleAttributeSet locAttrSet; new GColor("color.fg.pluginpanel.details.developer");
private SimpleAttributeSet developerAttrSet; private static final GColor CLASS_COLOR = new GColor("color.fg.pluginpanel.details.class");
private SimpleAttributeSet dependencyAttrSet; private static final GColor CATEGORIES_COLOR =
private SimpleAttributeSet noValueAttrSet; 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 final PluginConfigurationModel model;
private PluginTool tool; private PluginTool tool;
private PluginDescription currentDescriptor;
PluginDetailsPanel(PluginTool tool, PluginConfigurationModel model) { PluginDetailsPanel(PluginTool tool, PluginConfigurationModel model) {
super();
this.tool = tool; this.tool = tool;
this.model = model; this.model = model;
createFieldAttributes(); createFieldAttributes();
createMainPanel(); createMainPanel();
} }
@Override
protected void refresh() {
setPluginDescription(currentDescriptor);
}
void setPluginDescription(PluginDescription descriptor) { void setPluginDescription(PluginDescription descriptor) {
this.currentDescriptor = descriptor;
textLabel.setText(""); textLabel.setText("");
if (descriptor == null) { if (descriptor == null) {
return; return;
@ -74,43 +96,43 @@ class PluginDetailsPanel extends AbstractDetailsPanel {
insertRowTitle(buffer, "Name"); insertRowTitle(buffer, "Name");
insertRowValue(buffer, descriptor.getName(), insertRowValue(buffer, descriptor.getName(),
!dependencies.isEmpty() ? depNameAttrSet : nameAttrSet); !dependencies.isEmpty() ? dependenciesNameAttrs : nameAttrs);
insertRowTitle(buffer, "Description"); insertRowTitle(buffer, "Description");
insertRowValue(buffer, descriptor.getDescription(), descrAttrSet); insertRowValue(buffer, descriptor.getDescription(), descriptionAttrs);
insertRowTitle(buffer, "Status"); insertRowTitle(buffer, "Status");
insertRowValue(buffer, descriptor.getStatus().getDescription(), insertRowValue(buffer, descriptor.getStatus().getDescription(),
(descriptor.getStatus() == PluginStatus.RELEASED) ? titleAttrSet : developerAttrSet); (descriptor.getStatus() == PluginStatus.RELEASED) ? titleAttrs : developerAttrs);
insertRowTitle(buffer, "Package"); insertRowTitle(buffer, "Package");
insertRowValue(buffer, descriptor.getPluginPackage().getName(), categoriesAttrSet); insertRowValue(buffer, descriptor.getPluginPackage().getName(), categoriesAttrs);
insertRowTitle(buffer, "Category"); insertRowTitle(buffer, "Category");
insertRowValue(buffer, descriptor.getCategory(), categoriesAttrSet); insertRowValue(buffer, descriptor.getCategory(), categoriesAttrs);
insertRowTitle(buffer, "Plugin Class"); insertRowTitle(buffer, "Plugin Class");
insertRowValue(buffer, descriptor.getPluginClass().getName(), classAttrSet); insertRowValue(buffer, descriptor.getPluginClass().getName(), classAttrs);
insertRowTitle(buffer, "Class Location"); insertRowTitle(buffer, "Class Location");
insertRowValue(buffer, descriptor.getSourceLocation(), locAttrSet); insertRowValue(buffer, descriptor.getSourceLocation(), locationAttrs);
insertRowTitle(buffer, "Used By"); insertRowTitle(buffer, "Used By");
buffer.append("<TD VALIGN=\"TOP\">"); buffer.append("<TD VALIGN=\"TOP\">");
if (dependencies.isEmpty()) { if (dependencies.isEmpty()) {
insertHTMLLine(buffer, "None", noValueAttrSet); insertHTMLLine(buffer, "None", noValueAttrs);
} }
else { else {
for (int i = 0; i < dependencies.size(); i++) { for (int i = 0; i < dependencies.size(); i++) {
insertHTMLString(buffer, dependencies.get(i).getPluginClass().getName(), insertHTMLString(buffer, dependencies.get(i).getPluginClass().getName(),
dependencyAttrSet); dependencyAttrs);
if (i < dependencies.size() - 1) { if (i < dependencies.size() - 1) {
buffer.append(HTMLUtilities.BR); buffer.append(HTMLUtilities.BR);
} }
} }
insertHTMLLine(buffer, "", titleAttrSet); // add a newline insertHTMLLine(buffer, "", titleAttrs); // add a newline
} }
buffer.append("</TD>"); buffer.append("</TD>");
buffer.append("</TR>"); buffer.append("</TR>");
@ -121,16 +143,16 @@ class PluginDetailsPanel extends AbstractDetailsPanel {
List<Class<?>> servicesRequired = descriptor.getServicesRequired(); List<Class<?>> servicesRequired = descriptor.getServicesRequired();
if (servicesRequired.isEmpty()) { if (servicesRequired.isEmpty()) {
insertHTMLLine(buffer, "None", noValueAttrSet); insertHTMLLine(buffer, "None", noValueAttrs);
} }
else { else {
for (int i = 0; i < servicesRequired.size(); i++) { 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) { if (i < servicesRequired.size() - 1) {
buffer.append(HTMLUtilities.BR); buffer.append(HTMLUtilities.BR);
} }
} }
insertHTMLLine(buffer, "", titleAttrSet); // add a newline insertHTMLLine(buffer, "", titleAttrs); // add a newline
} }
buffer.append("</TD>"); buffer.append("</TD>");
buffer.append("</TR>"); buffer.append("</TR>");
@ -158,7 +180,7 @@ class PluginDetailsPanel extends AbstractDetailsPanel {
buffer.append("<TR>"); buffer.append("<TR>");
buffer.append("<TD VALIGN=\"TOP\">"); buffer.append("<TD VALIGN=\"TOP\">");
insertHTMLLine(buffer, "Loaded Actions:", titleAttrSet); insertHTMLLine(buffer, "Loaded Actions:", titleAttrs);
buffer.append("</TD>"); buffer.append("</TD>");
Set<DockingActionIf> actions = Collections.emptySet(); Set<DockingActionIf> actions = Collections.emptySet();
@ -169,7 +191,7 @@ class PluginDetailsPanel extends AbstractDetailsPanel {
if (actions.isEmpty()) { if (actions.isEmpty()) {
buffer.append("<TD VALIGN=\"TOP\">"); buffer.append("<TD VALIGN=\"TOP\">");
insertHTMLLine(buffer, "No actions for plugin", noValueAttrSet); insertHTMLLine(buffer, "No actions for plugin", noValueAttrs);
buffer.append("</TD>"); buffer.append("</TD>");
buffer.append("</TR>"); buffer.append("</TR>");
return; return;
@ -182,7 +204,7 @@ class PluginDetailsPanel extends AbstractDetailsPanel {
for (DockingActionIf dockableAction : actions) { for (DockingActionIf dockableAction : actions) {
buffer.append("<TR><TD WIDTH=\"200\">"); buffer.append("<TR><TD WIDTH=\"200\">");
insertHTMLString(buffer, dockableAction.getName(), locAttrSet); insertHTMLString(buffer, dockableAction.getName(), locationAttrs);
buffer.append("</TD>"); buffer.append("</TD>");
buffer.append("<TD WIDTH=\"300\">"); buffer.append("<TD WIDTH=\"300\">");
@ -190,17 +212,17 @@ class PluginDetailsPanel extends AbstractDetailsPanel {
String[] menuPath = menuBarData == null ? null : menuBarData.getMenuPath(); String[] menuPath = menuBarData == null ? null : menuBarData.getMenuPath();
String menuPathString = createStringForMenuPath(menuPath); String menuPathString = createStringForMenuPath(menuPath);
if (menuPathString != null) { if (menuPathString != null) {
insertHTMLString(buffer, menuPathString, locAttrSet); insertHTMLString(buffer, menuPathString, locationAttrs);
} }
else { else {
MenuData popupMenuData = dockableAction.getPopupMenuData(); MenuData popupMenuData = dockableAction.getPopupMenuData();
String[] popupPath = popupMenuData == null ? null : popupMenuData.getMenuPath(); String[] popupPath = popupMenuData == null ? null : popupMenuData.getMenuPath();
if (popupPath != null) { if (popupPath != null) {
insertHTMLString(buffer, "(in a context popup menu)", noValueAttrSet); insertHTMLString(buffer, "(in a context popup menu)", noValueAttrs);
} }
else { 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(); KeyStroke keyBinding = dockableAction.getKeyBinding();
if (keyBinding != null) { if (keyBinding != null) {
String keyStrokeString = KeyBindingUtils.parseKeyStroke(keyBinding); String keyStrokeString = KeyBindingUtils.parseKeyStroke(keyBinding);
insertHTMLString(buffer, keyStrokeString, locAttrSet); insertHTMLString(buffer, keyStrokeString, locationAttrs);
} }
else { else {
insertHTMLString(buffer, "No keybinding", noValueAttrSet); insertHTMLString(buffer, "No keybinding", noValueAttrs);
} }
buffer.append("</TD></TR>"); buffer.append("</TD></TR>");
@ -242,74 +264,19 @@ class PluginDetailsPanel extends AbstractDetailsPanel {
@Override @Override
protected void createFieldAttributes() { protected void createFieldAttributes() {
titleAttrSet = new SimpleAttributeSet(); Font font = Gui.getFont(FONT_DEFAULT);
titleAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); titleAttrs = new GAttributes(font, TITLE_COLOR);
titleAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11)); nameAttrs = new GAttributes(font, NAME_NO_DEPENDENTS_COLOR);
titleAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE); dependenciesNameAttrs = new GAttributes(font, NAME_DEPENDENTS_COLOR);
titleAttrSet.addAttribute(StyleConstants.Foreground, descriptionAttrs = new GAttributes(font, DESCRIPTION_COLOR);
new GColor("color.fg.pluginpanel.details.title")); categoriesAttrs = new GAttributes(font, CATEGORIES_COLOR);
locationAttrs = new GAttributes(font, LOCATION_COLOR);
developerAttrs = new GAttributes(font, DEVELOPER_COLOR);
nameAttrSet = new SimpleAttributeSet(); Font fontMonospaced = Gui.getFont(FONT_MONOSPACED);
nameAttrSet.addAttribute(StyleConstants.FontFamily, "Tahoma"); classAttrs = new GAttributes(fontMonospaced, CLASS_COLOR);
nameAttrSet.addAttribute(StyleConstants.FontSize, Integer.valueOf(11)); dependencyAttrs = new GAttributes(fontMonospaced, DEPENDENCY_COLOR);
nameAttrSet.addAttribute(StyleConstants.Bold, Boolean.TRUE);
nameAttrSet.addAttribute(StyleConstants.Foreground,
new GColor("color.fg.pluginpanel.details.name.no.dependents"));
depNameAttrSet = new SimpleAttributeSet(); noValueAttrs = new GAttributes(font, NO_VALUE_COLOR);
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"));
} }
} }

View File

@ -15,11 +15,14 @@
*/ */
package ghidra.framework.plugintool.dialog; package ghidra.framework.plugintool.dialog;
import static ghidra.framework.plugintool.dialog.PluginInstallerTableModel.*;
import java.awt.*; import java.awt.*;
import java.util.List; import java.util.List;
import javax.swing.*; import javax.swing.*;
import javax.swing.table.TableColumn; import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import docking.DialogComponentProvider; import docking.DialogComponentProvider;
import docking.widgets.table.*; import docking.widgets.table.*;
@ -149,30 +152,23 @@ public class PluginInstallerDialog extends DialogComponentProvider {
tableFilterPanel = new GTableFilterPanel<>(table, tableModel); tableFilterPanel = new GTableFilterPanel<>(table, tableModel);
JScrollPane sp = new JScrollPane(table); JScrollPane sp = new JScrollPane(table);
pluginTablePanel.add(sp, BorderLayout.CENTER); pluginTablePanel.add(sp, BorderLayout.CENTER);
pluginTablePanel.add(tableFilterPanel, BorderLayout.SOUTH); pluginTablePanel.add(tableFilterPanel, BorderLayout.SOUTH);
// Restrict the size of the first couple columns - the default size is // 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 too large. This is annoying but our table column classes don't have a nice
// way to restrict column width. // way to restrict column width.
TableColumn inst_col = TableColumnModel columnModel = table.getColumnModel();
table.getColumnModel().getColumn(PluginInstallerTableModel.INSTALLED_COL); TableColumn installedColumn = columnModel.getColumn(INSTALLED_COL);
inst_col.setMaxWidth(30); installedColumn.setMaxWidth(30);
TableColumn status_col = TableColumn statusColumn = columnModel.getColumn(STATUS_COL);
table.getColumnModel().getColumn(PluginInstallerTableModel.STATUS_COL); statusColumn.setMaxWidth(24);
status_col.setMaxWidth(24);
tableModel.setTableSortState( tableModel.setTableSortState(TableSortState.createDefaultSortState(NAME_COL));
TableSortState.createDefaultSortState(PluginInstallerTableModel.NAME_COL));
tableModel.refresh(); tableModel.refresh();
table.getColumnModel() columnModel.getColumn(NAME_COL).setCellRenderer(new NameCellRenderer());
.getColumn(PluginInstallerTableModel.NAME_COL) columnModel.getColumn(STATUS_COL).setCellRenderer(new StatusCellRenderer());
.setCellRenderer(new NameCellRenderer());
table.getColumnModel()
.getColumn(PluginInstallerTableModel.STATUS_COL)
.setCellRenderer(new StatusCellRenderer());
HelpService help = Help.getHelpService(); HelpService help = Help.getHelpService();
help.registerHelp(table, new HelpLocation(GenericHelpTopics.TOOL, "PluginDialog")); 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); renderer.setIcon((value instanceof Icon) ? (Icon) value : null);
String toolTipText = ""; String toolTipText = "";
if (value == PluginInstallerTableModel.EXPERIMENTAL_ICON) { if (value == EXPERIMENTAL_ICON) {
toolTipText = "This plugin is usable, but not fully tested or documented"; toolTipText = "This plugin is usable, but not fully tested or documented";
} }
else if (value == PluginInstallerTableModel.DEV_ICON) { else if (value == DEV_ICON) {
toolTipText = toolTipText =
"This plugin is under development and not intended for general use.\n" + "This plugin is under development and not intended for general use.\n" +
"It could cause Ghidra to become unstable!"; "It could cause Ghidra to become unstable!";

View File

@ -176,7 +176,7 @@ public class PluginManagerComponent extends JPanel implements Scrollable {
labelPanel.setBackground(BG); labelPanel.setBackground(BG);
GLabel nameLabel = new GLabel(pluginPackage.getName()); 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")); nameLabel.setForeground(new GColor("color.fg.pluginpanel.name"));
labelPanel.add(nameLabel); labelPanel.add(nameLabel);

View File

@ -15,13 +15,11 @@
*/ */
package ghidra.framework.project.extensions; package ghidra.framework.project.extensions;
import java.awt.Color; import java.awt.Font;
import java.awt.Point; import java.awt.Point;
import javax.swing.text.SimpleAttributeSet;
import docking.widgets.table.threaded.ThreadedTableModelListener; import docking.widgets.table.threaded.ThreadedTableModelListener;
import generic.theme.GColor; import generic.theme.*;
import ghidra.framework.plugintool.dialog.AbstractDetailsPanel; import ghidra.framework.plugintool.dialog.AbstractDetailsPanel;
import ghidra.util.extensions.ExtensionDetails; import ghidra.util.extensions.ExtensionDetails;
@ -33,27 +31,28 @@ import ghidra.util.extensions.ExtensionDetails;
*/ */
class ExtensionDetailsPanel extends AbstractDetailsPanel { 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"); new GColor("color.fg.extensionpanel.details.author");
private static final Color FG_COLOR_DATE = new GColor("color.fg.extensionpanel.details.date"); private static final GColor FG_COLOR_DATE = new GColor("color.fg.extensionpanel.details.date");
private static final Color FG_COLOR_DESCRIPTION = private static final GColor FG_COLOR_DESCRIPTION =
new GColor("color.fg.extensionpanel.details.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 GColor 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 GColor 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 GColor FG_COLOR_TITLE =
private static final Color FG_COLOR_VERSION = new GColor("color.fg.extensionpanel.details.title");
private static final GColor FG_COLOR_VERSION =
new GColor("color.fg.extensionpanel.details.version"); new GColor("color.fg.extensionpanel.details.version");
/** Attribute sets define the visual characteristics for each field */ /** Attribute sets define the visual characteristics for each field */
private SimpleAttributeSet nameAttrSet; private GAttributes nameAttrSet;
private SimpleAttributeSet descrAttrSet; private GAttributes descrAttrSet;
private SimpleAttributeSet authorAttrSet; private GAttributes authorAttrSet;
private SimpleAttributeSet createdOnAttrSet; private GAttributes createdOnAttrSet;
private SimpleAttributeSet versionAttrSet; private GAttributes versionAttrSet;
private SimpleAttributeSet pathAttrSet; private GAttributes pathAttrSet;
private ExtensionDetails currentDetails;
ExtensionDetailsPanel(ExtensionTablePanel tablePanel) { ExtensionDetailsPanel(ExtensionTablePanel tablePanel) {
super();
createFieldAttributes(); createFieldAttributes();
createMainPanel(); createMainPanel();
@ -82,13 +81,19 @@ class ExtensionDetailsPanel extends AbstractDetailsPanel {
}); });
} }
@Override
protected void refresh() {
setDescription(currentDetails);
}
/** /**
* Updates this panel with the given extension. * Updates this panel with the given extension.
* *
* @param details the extension to display * @param details the extension to display
*/ */
public void setDescription(ExtensionDetails details) { public void setDescription(ExtensionDetails details) {
this.currentDetails = details;
clear(); clear();
if (details == null) { if (details == null) {
return; return;
@ -134,12 +139,14 @@ class ExtensionDetailsPanel extends AbstractDetailsPanel {
@Override @Override
protected void createFieldAttributes() { protected void createFieldAttributes() {
titleAttrSet = createAttributeSet(FG_COLOR_TITLE);
nameAttrSet = createAttributeSet(FG_COLOR_NAME); Font font = Gui.getFont(FONT_DEFAULT);
descrAttrSet = createAttributeSet(FG_COLOR_DESCRIPTION); titleAttrs = new GAttributes(font, FG_COLOR_TITLE);
authorAttrSet = createAttributeSet(FG_COLOR_AUTHOR); nameAttrSet = new GAttributes(font, FG_COLOR_NAME);
createdOnAttrSet = createAttributeSet(FG_COLOR_DATE); descrAttrSet = new GAttributes(font, FG_COLOR_DESCRIPTION);
versionAttrSet = createAttributeSet(FG_COLOR_VERSION); authorAttrSet = new GAttributes(font, FG_COLOR_AUTHOR);
pathAttrSet = createAttributeSet(FG_COLOR_PATH); createdOnAttrSet = new GAttributes(font, FG_COLOR_DATE);
versionAttrSet = new GAttributes(font, FG_COLOR_VERSION);
pathAttrSet = new GAttributes(font, FG_COLOR_PATH);
} }
} }

View File

@ -25,6 +25,7 @@ import docking.util.AnimatedIcon;
import docking.widgets.EmptyBorderButton; import docking.widgets.EmptyBorderButton;
import docking.widgets.label.GDHtmlLabel; import docking.widgets.label.GDHtmlLabel;
import docking.widgets.label.GIconLabel; import docking.widgets.label.GIconLabel;
import generic.theme.Gui;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.SystemUtilities; import ghidra.util.SystemUtilities;
import ghidra.util.layout.VerticalLayout; import ghidra.util.layout.VerticalLayout;
@ -36,6 +37,8 @@ import resources.ResourceManager;
public class GProgressBar extends JPanel { public class GProgressBar extends JPanel {
private static final NumberFormat PERCENT_FORMAT = NumberFormat.getPercentInstance(); 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 lastProgress = -1;
private volatile long progress; private volatile long progress;
private volatile long scaleFactor = 1; private volatile long scaleFactor = 1;
@ -47,7 +50,6 @@ public class GProgressBar extends JPanel {
private volatile boolean paintProgressValue = true; private volatile boolean paintProgressValue = true;
private boolean showingIcon = true; private boolean showingIcon = true;
private final float fontSize;
private JProgressBar progressBar; private JProgressBar progressBar;
private JLabel messageLabel; private JLabel messageLabel;
private JLabel imageLabel; private JLabel imageLabel;
@ -61,10 +63,9 @@ public class GProgressBar extends JPanel {
private CancelledListener cancelledListener; private CancelledListener cancelledListener;
public GProgressBar(CancelledListener cancelledListener, boolean includeTextField, public GProgressBar(CancelledListener cancelledListener, boolean includeTextField,
boolean includeCancelButton, boolean includeAnimatedIcon, float fontSize) { boolean includeCancelButton, boolean includeAnimatedIcon) {
super(new BorderLayout(5, 1)); super(new BorderLayout(5, 1));
this.cancelledListener = cancelledListener; this.cancelledListener = cancelledListener;
this.fontSize = fontSize;
buildProgressPanel(includeTextField, includeCancelButton, includeAnimatedIcon); buildProgressPanel(includeTextField, includeCancelButton, includeAnimatedIcon);
@ -217,7 +218,7 @@ public class GProgressBar extends JPanel {
// don't care // don't care
} }
}; };
messageLabel.setFont(messageLabel.getFont().deriveFont(fontSize)); Gui.registerFont(messageLabel, MESSAGE_FONT_ID);
Dimension d = messageLabel.getPreferredSize(); Dimension d = messageLabel.getPreferredSize();
d.width = 180; d.width = 180;
messageLabel.setPreferredSize(d); messageLabel.setPreferredSize(d);

View File

@ -31,7 +31,6 @@ public class ScheduledTaskPanel extends JPanel {
private ScheduledElementLayout layout; private ScheduledElementLayout layout;
public ScheduledTaskPanel(String labelText, int indention) { public ScheduledTaskPanel(String labelText, int indention) {
super();
this.indention = indention; this.indention = indention;
setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0)); setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0));
@ -44,7 +43,7 @@ public class ScheduledTaskPanel extends JPanel {
} }
void addProgressBar() { void addProgressBar() {
progressBar = new GProgressBar(null, true, true, false, 12); progressBar = new GProgressBar(null, true, true, false);
progressBar.setBackgroundColor(Colors.BACKGROUND); progressBar.setBackgroundColor(Colors.BACKGROUND);
add(progressBar); add(progressBar);
layout.clearPreferredSize(); layout.clearPreferredSize();
@ -71,7 +70,7 @@ public class ScheduledTaskPanel extends JPanel {
//================================================================================================== //==================================================================================================
// Inner Classes // Inner Classes
//================================================================================================== //==================================================================================================
// This layout handles the scrolling based on the scrollOffset as set by the setHiddenViewAmount() // 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. // It also optionally shows the scrollbar for the task or group.

View File

@ -15,8 +15,7 @@
*/ */
package ghidra.framework.task; package ghidra.framework.task;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.*;
import static org.junit.Assert.assertTrue;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
@ -46,11 +45,11 @@ public class GProgressBarTest extends AbstractDockingTest {
cancelled = true; cancelled = true;
} }
}; };
progressBar = new GProgressBar(cancelledListener, true, true, true, 10.0f); progressBar = new GProgressBar(cancelledListener, true, true, true);
} }
@Test @Test
public void testBasicProgress() { public void testBasicProgress() {
progressBar.initialize(100); progressBar.initialize(100);
assertEquals(0, progressBar.getProgress()); assertEquals(0, progressBar.getProgress());
assertEquals(100, progressBar.getMax()); assertEquals(100, progressBar.getMax());
@ -62,7 +61,7 @@ public class GProgressBarTest extends AbstractDockingTest {
} }
@Test @Test
public void testLongValues() { public void testLongValues() {
progressBar.initialize(0x400000000L); progressBar.initialize(0x400000000L);
progressBar.setProgress(10); progressBar.setProgress(10);
assertEquals(10, progressBar.getProgress()); assertEquals(10, progressBar.getProgress());
@ -73,7 +72,7 @@ public class GProgressBarTest extends AbstractDockingTest {
} }
@Test @Test
public void testMessage() { public void testMessage() {
progressBar.initialize(100); progressBar.initialize(100);
progressBar.setMessage("Hey"); progressBar.setMessage("Hey");
assertEquals("Hey", progressBar.getMessage()); assertEquals("Hey", progressBar.getMessage());
@ -91,7 +90,7 @@ public class GProgressBarTest extends AbstractDockingTest {
} }
@Test @Test
public void testCancel() { public void testCancel() {
progressBar.initialize(100); progressBar.initialize(100);
progressBar.setProgress(50); progressBar.setProgress(50);
assertTrue(!cancelled); assertTrue(!cancelled);

View File

@ -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"). * which may be present (e.g., "MyDomain\John Doe" becomes "JohnDoe").
* @param name user name string to be cleaned-up * @param name user name string to be cleaned-up
* @return the clean user name * @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 * 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 * eliminate any spaces or leading domain name which may be present in Java's
* {@code user.name} system property (see {@link #getCleanUserName(String)}). * {@code user.name} system property (see {@link #getCleanUserName(String)}).
* @return the user name * @return the user name
*/ */
@ -173,20 +173,15 @@ public class SystemUtilities {
} }
/** /**
* Checks to see if the font size override setting is enabled and adjusts * No longer supported. Use the theming system for fonts
* the given font as necessary to match the override setting. If the setting
* is not enabled, then <code>font</code> is returned.
* *
* @param font * @param font the font
* The current font to adjust, if necessary. * @return the same font passed in
* @return a font object with the proper size. * @deprecated Use the theming system for fonts
*/ */
@Deprecated(since = "11.1", forRemoval = true)
public static Font adjustForFontSizeOverride(Font font) { public static Font adjustForFontSizeOverride(Font font) {
if (FONT_SIZE_OVERRIDE_VALUE == null) { return font;
return font;
}
return font.deriveFont((float) FONT_SIZE_OVERRIDE_VALUE.intValue());
} }
/** /**
@ -350,10 +345,10 @@ public class SystemUtilities {
} }
/** /**
* Returns a file that contains the given class. If the class is in a jar file, then * 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 * 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). * containing the package root will be returned (i.e. the "bin" directory).
* *
* @param classObject the class for which to get the location * @param classObject the class for which to get the location
* @return the containing location * @return the containing location
*/ */

View File

@ -42,12 +42,12 @@ public class ReflectionUtilities {
} }
/** /**
* Locates the field of the name <code>fieldName</code> on the given * Locates the field of the name <code>fieldName</code> on the given
* class. If the given class does not contain the field, then this * class. If the given class does not contain the field, then this
* method will recursively call up <code>containingClass</code>'s * method will recursively call up <code>containingClass</code>'s
* implementation tree looking for a parent implementation of the * implementation tree looking for a parent implementation of the
* requested field. * requested field.
* *
* @param fieldName The name of the field to locate. * @param fieldName The name of the field to locate.
* @param containingClass The class that contains the desired field. * @param containingClass The class that contains the desired field.
* @return The Field object that matches the given name, or null if not * @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 <code>fieldName</code> on the given * Locates the field of the name <code>fieldName</code> on the given
* class. If the given class does not contain the field, then this * class. If the given class does not contain the field, then this
* method will recursively call up <code>containingClass</code>'s * method will recursively call up <code>containingClass</code>'s
* implementation tree looking for a parent implementation of the * implementation tree looking for a parent implementation of the
* requested field. * requested field.
* *
* @param fieldName The name of the field to locate. * @param fieldName The name of the field to locate.
* @param containingClass The class that contains the desired field. * @param containingClass The class that contains the desired field.
* @return The Field object that matches the given name, or null if not * @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 <code>methodName</code> on the given * Locates the method of the name <code>methodName</code> on the given
* class. If the given class does not contain the method, then this * class. If the given class does not contain the method, then this
* method will recursively call up <code>containingClass</code>'s * method will recursively call up <code>containingClass</code>'s
* implementation tree looking for a parent implementation of the * implementation tree looking for a parent implementation of the
* requested method. * requested method.
* *
* @param methodName The name of the method to locate. * @param methodName The name of the method to locate.
* @param containingClass The class that contains the desired method. * @param containingClass The class that contains the desired method.
* @param parameterTypes The parameters of the desired method (may be null). * @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. * 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. * classType exists within the containingClass hierarchy.
* @param classType the class * @param classType the class
* @param containingClass the class that contains a field of the given type * @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 * 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 * given classes. This is useful for figuring out at runtime who is calling a particular
* method. * method.
* <p> * <p>
* 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. * class of disinterest.
* *
* @param classes the classes to ignore * @param classes the classes to ignore
* @return the desired class name * @return the desired class name
*/ */
public static String getClassNameOlderThan(Class<?>... classes) { public static String getClassNameOlderThan(Class<?>... classes) {
Throwable t = createThrowableWithStackOlderThan(classes); Throwable t = createThrowableWithStackOlderThan(classes);
StackTraceElement[] stackTrace = t.getStackTrace(); StackTraceElement[] stackTrace = t.getStackTrace();
return stackTrace[0].getClassName(); return stackTrace[0].getClassName();
} }
/** /**
* Creates a throwable whose stack trace is based upon the current call stack, with any * Returns the class name of the entry in the stack that comes before all references to the
* information coming before, and including, the given classes removed. * given patterns. This is useful for figuring out at runtime who is calling a particular
* <p> * method.
* This method can take multiple classes, but you really only need to pass the oldest *
* class of disinterest. * @param patterns the patterns to ignore
* * @return the desired class name
* @param classes the classes to ignore
* @return the new throwable
*/ */
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<String> 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()) { private static Throwable createThrowableWithStackOlderThan(List<String> patterns) {
// Always ignore our class. We get this for free if the client passes in any
// classes. if (patterns.isEmpty()) {
toFind.add(0, ReflectionUtilities.class.getName()); // 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(); Throwable t = new Throwable();
@ -227,7 +239,7 @@ public class ReflectionUtilities {
StackTraceElement element = trace[i]; StackTraceElement element = trace[i];
String className = element.getClassName(); String className = element.getClassName();
int nameIndex = toFind.indexOf(className); int nameIndex = patterns.indexOf(className);
if (nameIndex != -1) { if (nameIndex != -1) {
lastIgnoreIndex = i; lastIgnoreIndex = i;
} }
@ -242,13 +254,13 @@ public class ReflectionUtilities {
if (lastIgnoreIndex == -1) { if (lastIgnoreIndex == -1) {
Msg.error(ReflectionUtilities.class, Msg.error(ReflectionUtilities.class,
"Change call to ReflectionUtils. Did not find the " + "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) { if (lastIgnoreIndex == trace.length - 1) {
Msg.error(ReflectionUtilities.class, Msg.error(ReflectionUtilities.class,
"Change call to ReflectionUtils. Call stack only contains the classes to ignore: " + "Change call to ReflectionUtils. Call stack contains only ignored patterns: " +
Arrays.toString(classes)); patterns);
} }
int startIndex = lastIgnoreIndex + 1; 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.
* <p>
* 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<String> 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 * something that is not that pattern
* *
* @param trace the trace to update * @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 * {@link String#contains(CharSequence)} on each {@link StackTraceElement} line
* @return the updated trace * @return the updated trace
*/ */
@ -296,12 +324,12 @@ public class ReflectionUtilities {
} }
/** /**
* Uses the given <code>patterns</code> to remove elements from the given stack trace. * Uses the given <code>patterns</code> to remove elements from the given stack trace.
* The current implementation will simply perform a <code>toString()</code> on each element and * The current implementation will simply perform a <code>toString()</code> on each element and
* then check to see if that string contains any of the <code>patterns</code>. * then check to see if that string contains any of the <code>patterns</code>.
* *
* @param trace the trace to filter * @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} * {@link String#contains(CharSequence)} on each {@link StackTraceElement}
* line. * line.
* @return the filtered trace * @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 * 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. * 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} * {@link String#contains(CharSequence)} on each {@link StackTraceElement}
* line. * line.
* @return the new throwable * @return the new throwable
*/ */
public static Throwable createFilteredThrowable(String... patterns) { public static Throwable createFilteredThrowable(String... patterns) {
Throwable t = createThrowableWithStackOlderThan(); Throwable t = createThrowableWithStackOlderThan(new ArrayList<>());
StackTraceElement[] trace = t.getStackTrace(); StackTraceElement[] trace = t.getStackTrace();
StackTraceElement[] filtered = filterStackTrace(trace, patterns); StackTraceElement[] filtered = filterStackTrace(trace, patterns);
t.setStackTrace(filtered); t.setStackTrace(filtered);
@ -341,40 +369,39 @@ public class ReflectionUtilities {
} }
/** /**
* A convenience method to create a throwable, filtering boiler-plate Java-related * A convenience method to create a throwable, filtering boiler-plate Java-related
* lines (e.g., AWT, Swing, Security, etc). * lines (e.g., AWT, Swing, Security, etc).
* This can be useful for emitting diagnostic stack traces with reduced noise. * This can be useful for emitting diagnostic stack traces with reduced noise.
* *
* @return the new throwable * @return the new throwable
*/ */
public static Throwable createJavaFilteredThrowable() { public static Throwable createJavaFilteredThrowable() {
Throwable t = createThrowableWithStackOlderThan(List.of());
Throwable t = createThrowableWithStackOlderThan();
return filterJavaThrowable(t); return filterJavaThrowable(t);
} }
/** /**
* A convenience method to create a throwable, filtering boiler-plate Java-related * A convenience method to create a throwable, filtering boiler-plate Java-related
* lines (e.g., AWT, Swing, Security, etc). * lines (e.g., AWT, Swing, Security, etc).
* This can be useful for emitting diagnostic stack traces with reduced noise. * This can be useful for emitting diagnostic stack traces with reduced noise.
* *
* <p>This method differs from {@link #createJavaFilteredThrowable()} in that this method * <p>This method differs from {@link #createJavaFilteredThrowable()} in that this method
* returns a String, which is useful when printing log messages without having to directly * returns a String, which is useful when printing log messages without having to directly
* print the stack trace. * print the stack trace.
* *
* @return the new throwable * @return the new throwable
*/ */
public static String createJavaFilteredThrowableString() { public static String createJavaFilteredThrowableString() {
Throwable t = createThrowableWithStackOlderThan(); Throwable t = createThrowableWithStackOlderThan(List.of());
Throwable filtered = filterJavaThrowable(t); Throwable filtered = filterJavaThrowable(t);
return stackTraceToString(filtered); return stackTraceToString(filtered);
} }
/** /**
* A convenience method to take a throwable, filter boiler-plate Java-related * A convenience method to take a throwable, filter boiler-plate Java-related
* lines (e.g., AWT, Swing, Security, etc). * lines (e.g., AWT, Swing, Security, etc).
* This can be useful for emitting diagnostic stack traces with reduced noise. * This can be useful for emitting diagnostic stack traces with reduced noise.
* *
* @param t the throwable to filter * @param t the throwable to filter
* @return the throwable * @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 list.
* <p> * <p>
* 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. * classes. Further, interface hierarchies are examined before concrete parent extensions.
* <p> * <p>
* If the given items have no parents in common, then the result will be a list with * If the given items have no parents in common, then the result will be a list with
* only <code>Object.class</code>. * only <code>Object.class</code>.
* *
* @param list the items to examine * @param list the items to examine
* @return the set of items * @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. * amongst the items in the list.
* <p> * <p>
* 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. * classes. Further, interface hierarchies are examined before concrete parent extensions.
* <p> * <p>
* If the given items have no parents in common, then the result will be a list with * If the given items have no parents in common, then the result will be a list with
* only <code>Object.class</code>. * only <code>Object.class</code>.
* *
* @param list the items to examine * @param list the items to examine
* @return the set of items * @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. * {@link Throwable#printStackTrace()} method.
* *
* @param t the throwable * @param t the throwable
* @return the string * @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. * {@link Throwable#printStackTrace()} method.
* *
* @param message the preferred message to use. If null, the throwable message will be used * @param message the preferred message to use. If null, the throwable message will be used
* @param t the throwable * @param t the throwable
* @return the string * @return the string
@ -543,11 +570,11 @@ public class ReflectionUtilities {
/** /**
* Returns an order set of all interfaces implemented and classes extended for the entire * 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.
* <p> * <p>
* If <code>Object.class</code> is passed to this method, then it will be returned in the * If <code>Object.class</code> is passed to this method, then it will be returned in the
* result of this method. * result of this method.
* *
* @param c the class to introspect * @param c the class to introspect
* @return the set of parents * @return the set of parents
*/ */
@ -581,7 +608,7 @@ public class ReflectionUtilities {
/** /**
* Returns the type arguments for the given base class and extension. * Returns the type arguments for the given base class and extension.
* *
* <p>Caveat: this lookup will only work if the given child class is a concrete class that * <p>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: * has its type arguments specified. For example, these cases will work:
* <pre> * <pre>
@ -592,17 +619,17 @@ public class ReflectionUtilities {
* *
* // class definition * // class definition
* public class MyList implements List&lt;String&gt; { * public class MyList implements List&lt;String&gt; {
* </pre> * </pre>
* *
* Whereas this case will not work: * Whereas this case will not work:
* <pre> * <pre>
* // local variable with the type specified * // local variable with the type specified
* List&lt;String&gt; myList = new ArrayList&lt;String&gt;(); * List&lt;String&gt; myList = new ArrayList&lt;String&gt;();
* </pre> * </pre>
* *
* <p>Note: a null entry in the result list will exist for any type that was unrecoverable * <p>Note: a null entry in the result list will exist for any type that was unrecoverable
* *
* *
* @param <T> the type of the base and child class * @param <T> the type of the base and child class
* @param baseClass the base class * @param baseClass the base class
* @param childClass the child class * @param childClass the child class
@ -618,7 +645,7 @@ public class ReflectionUtilities {
Type baseClassAsType = Type baseClassAsType =
walkClassHierarchyAndResolveTypes(baseClass, resolvedTypesDictionary, childClass); 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); Type[] baseClassDeclaredTypeArguments = getDeclaredTypeArguments(baseClassAsType);
return resolveBaseClassTypeArguments(resolvedTypesDictionary, return resolveBaseClassTypeArguments(resolvedTypesDictionary,
baseClassDeclaredTypeArguments); baseClassDeclaredTypeArguments);

View File

@ -33,7 +33,6 @@ import resources.ResourceManager;
public class RepositoryCustomScreenShots extends GhidraScreenShotGenerator { public class RepositoryCustomScreenShots extends GhidraScreenShotGenerator {
public RepositoryCustomScreenShots() { public RepositoryCustomScreenShots() {
super();
} }
@Test @Test
@ -127,8 +126,6 @@ public class RepositoryCustomScreenShots extends GhidraScreenShotGenerator {
int y = p.y - radius; int y = p.y - radius;
g.fillOval(x, y, radius * 2, 2 * radius); g.fillOval(x, y, radius * 2, 2 * radius);
Font f = g.getFont().deriveFont(12f);
g.setFont(f);
FontMetrics metrics = g.getFontMetrics(); FontMetrics metrics = g.getFontMetrics();
int height = metrics.getHeight(); int height = metrics.getHeight();
g.setColor(Palette.BLACK); g.setColor(Palette.BLACK);
@ -154,8 +151,6 @@ public class RepositoryCustomScreenShots extends GhidraScreenShotGenerator {
BasicStroke stroke = new BasicStroke(1); BasicStroke stroke = new BasicStroke(1);
g.setStroke(stroke); g.setStroke(stroke);
Font f = g.getFont().deriveFont(12f);
g.setFont(f);
FontMetrics metrics = g.getFontMetrics(); FontMetrics metrics = g.getFontMetrics();
int margin = 5; int margin = 5;
int height = metrics.getHeight() * text.length + 2 * margin; int height = metrics.getHeight() * text.length + 2 * margin;
@ -189,8 +184,6 @@ public class RepositoryCustomScreenShots extends GhidraScreenShotGenerator {
Graphics2D g = ((BufferedImage) image).createGraphics(); Graphics2D g = ((BufferedImage) image).createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Font f = g.getFont().deriveFont(12f);
g.setFont(f);
FontMetrics metrics = g.getFontMetrics(); FontMetrics metrics = g.getFontMetrics();
// int margin = 5; // int margin = 5;
int height = metrics.getHeight() * text.length; int height = metrics.getHeight() * text.length;