diff --git a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractTraceRmiLaunchOpinion.java b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractTraceRmiLaunchOpinion.java
index def81a2db9..e889ca5348 100644
--- a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractTraceRmiLaunchOpinion.java
+++ b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractTraceRmiLaunchOpinion.java
@@ -34,7 +34,8 @@ public abstract class AbstractTraceRmiLaunchOpinion implements TraceRmiLaunchOpi
String pluginName = PluginUtils.getPluginNameFromClass(TraceRmiLauncherServicePlugin.class);
options.registerOption(TraceRmiLauncherServicePlugin.OPTION_NAME_SCRIPT_PATHS,
OptionType.STRING_TYPE, "", new HelpLocation(pluginName, "options"),
- "Paths to search for user-created debugger launchers", new ScriptPathsPropertyEditor());
+ "Paths to search for user-created debugger launchers",
+ () -> new ScriptPathsPropertyEditor());
}
@Override
diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/framework/options/AutoOptions.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/framework/options/AutoOptions.java
index 498151adfe..20569ee7c8 100644
--- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/framework/options/AutoOptions.java
+++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/framework/options/AutoOptions.java
@@ -27,6 +27,7 @@ import ghidra.framework.options.annotation.*;
import ghidra.framework.plugintool.Plugin;
import ghidra.framework.plugintool.PluginTool;
import ghidra.util.HelpLocation;
+import ghidra.util.SystemUtilities;
public interface AutoOptions {
@@ -148,7 +149,7 @@ public interface AutoOptions {
String description = annotation.description();
Class extends PropertyEditor> editorClass = annotation.editor();
final PropertyEditor editor;
- if (editorClass == PropertyEditor.class) {
+ if (editorClass == PropertyEditor.class || SystemUtilities.isInHeadlessMode()) {
editor = null;
}
else {
@@ -169,16 +170,16 @@ public interface AutoOptions {
else if ( is font option ) {
// Note: there is no font value to check against for fonts in the new Theme system.
- // If annotation fonts are needed, then they should be bound by String id. Likely,
- // annotation fonts are not needed now that have themes. We also probably no
- // longer need annotation colors either.
+ // If annotation fonts are needed, then they should be bound by String id. Likely,
+ // annotation fonts are not needed now that have themes. We also probably no
+ // longer need annotation colors either.
options.registerThemeFontBinding(description, fontId, help, description);
}
*/
else {
options.registerOption(key.name, type, defaultValue, help, description,
- editor);
+ () -> editor);
// TODO: Wish Ghidra would do this upon any option registration
options.putObject(key.name, defaultValue, type);
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ApplyDataArchiveAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ApplyDataArchiveAnalyzer.java
index d2e13ec137..72acebfe12 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ApplyDataArchiveAnalyzer.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ApplyDataArchiveAnalyzer.java
@@ -126,13 +126,13 @@ public class ApplyDataArchiveAnalyzer extends AbstractAnalyzer {
options.registerOption(OPTION_NAME_ARCHIVE_CHOOSER, OptionType.STRING_TYPE,
CHOOSER_AUTO_DETECT, null, OPTION_DESCRIPTION_ARCHIVE_CHOOSER,
- new StringWithChoicesEditor(chooserList));
+ () -> new StringWithChoicesEditor(chooserList));
options.registerOption(OPTION_NAME_GDT_FILEPATH, OptionType.FILE_TYPE, null, null,
OPTION_DESCRIPTION_GDT_FILEPATH,
- new FileChooserEditor(FileDataTypeManager.GDT_FILEFILTER));
+ () -> new FileChooserEditor(FileDataTypeManager.GDT_FILEFILTER));
options.registerOption(OPTION_NAME_PROJECT_PATH, OptionType.STRING_TYPE, null, null,
- OPTION_DESCRIPTION_PROJECT_PATH, new ProjectPathChooserEditor(
+ OPTION_DESCRIPTION_PROJECT_PATH, () -> new ProjectPathChooserEditor(
"Choose Data Type Archive", DATATYPEARCHIVE_PROJECT_FILTER));
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AutoAnalysisPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AutoAnalysisPlugin.java
index eb6d4a01fa..14b2e6b7a3 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AutoAnalysisPlugin.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AutoAnalysisPlugin.java
@@ -256,7 +256,7 @@ public class AutoAnalysisPlugin extends Plugin implements AutoAnalysisManagerLis
analysisMgr.addListener(this);
Options options = program.getOptions(Program.ANALYSIS_PROPERTIES);
- options.registerOptionsEditor(new AnalysisOptionsEditor(program));
+ options.registerOptionsEditor(() -> new AnalysisOptionsEditor(program));
options.setOptionsHelpLocation(
new HelpLocation("AutoAnalysisPlugin", "Auto_Analysis_Option"));
}
@@ -264,7 +264,8 @@ public class AutoAnalysisPlugin extends Plugin implements AutoAnalysisManagerLis
private void programActivated(Program program) {
program.getOptions(StoredAnalyzerTimes.OPTIONS_LIST)
.registerOption(StoredAnalyzerTimes.OPTION_NAME, OptionType.CUSTOM_TYPE, null, null,
- "Cumulative analysis task times", new StoredAnalyzerTimesPropertyEditor());
+ "Cumulative analysis task times",
+ () -> new StoredAnalyzerTimesPropertyEditor());
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/rust/RustDemanglerAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/rust/RustDemanglerAnalyzer.java
index 3255dd2369..534a781ff4 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/rust/RustDemanglerAnalyzer.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/rust/RustDemanglerAnalyzer.java
@@ -15,8 +15,7 @@
*/
package ghidra.app.plugin.core.analysis.rust;
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
+import java.beans.*;
import java.util.Arrays;
import docking.options.editor.BooleanEditor;
@@ -90,24 +89,14 @@ public class RustDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
options.registerOption(OPTION_NAME_DEMANGLE_USE_KNOWN_PATTERNS, demangleOnlyKnownPatterns,
help, OPTION_DESCRIPTION_USE_KNOWN_PATTERNS);
- BooleanEditor deprecatedEditor = null;
- FormatEditor formatEditor = null;
- if (!SystemUtilities.isInHeadlessMode()) {
- // Only add the custom options editor when not headless. The custom editor allows
- // the list of choices presented to the user to change depending on the state of the
- // useDeprecatedDemangler flag.
- deprecatedEditor = new BooleanEditor();
- deprecatedEditor.setValue(Boolean.valueOf(useDeprecatedDemangler));
- formatEditor = new FormatEditor(demanglerFormat, deprecatedEditor);
- deprecatedEditor.addPropertyChangeListener(formatEditor);
- }
+ RustOptionsEditor optionsEditor = new RustOptionsEditor();
options.registerOption(OPTION_NAME_USE_DEPRECATED_DEMANGLER, OptionType.BOOLEAN_TYPE,
useDeprecatedDemangler, help, OPTION_DESCRIPTION_DEPRECATED_DEMANGLER,
- deprecatedEditor);
+ () -> optionsEditor.getDeprecatedNameEditor());
options.registerOption(OPTION_NAME_DEMANGLER_FORMAT, OptionType.ENUM_TYPE, demanglerFormat,
- help, OPTION_DESCRIPTION_DEMANGLER_FORMAT, formatEditor);
+ help, OPTION_DESCRIPTION_DEMANGLER_FORMAT, () -> optionsEditor.getFormatEditor());
}
@Override
@@ -162,6 +151,45 @@ public class RustDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
super.apply(program, address, demangledVariable, options, log, monitor);
}
+//==================================================================================================
+// Inner Classes
+//==================================================================================================
+
+ // We only use the editor when not headless, since GUI code in headless will throw an exception.
+ // Further, the options below have a relationship, so we need to build them together.
+ // The format editor's list of choices presented to the user will change depending on the state
+ // of the deprecated boolean editor.
+ private class RustOptionsEditor {
+
+ private BooleanEditor deprecatedEditor;
+ private FormatEditor formatEditor;
+
+ private void lazyInit() {
+ if (SystemUtilities.isInHeadlessMode()) {
+ return; // the editor should not be requested in headless mode
+ }
+
+ if (deprecatedEditor != null) {
+ return; // already loaded
+ }
+
+ deprecatedEditor = new BooleanEditor();
+ deprecatedEditor.setValue(Boolean.valueOf(useDeprecatedDemangler));
+ formatEditor = new FormatEditor(demanglerFormat, deprecatedEditor);
+ deprecatedEditor.addPropertyChangeListener(formatEditor);
+ }
+
+ PropertyEditor getDeprecatedNameEditor() {
+ lazyInit();
+ return deprecatedEditor;
+ }
+
+ PropertyEditor getFormatEditor() {
+ lazyInit();
+ return formatEditor;
+ }
+ }
+
private static class FormatEditor extends EnumEditor implements PropertyChangeListener {
private final FormatSelector selector;
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/blockmodel/BlockModelServicePlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/blockmodel/BlockModelServicePlugin.java
index bbf155d607..4293db67b9 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/blockmodel/BlockModelServicePlugin.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/blockmodel/BlockModelServicePlugin.java
@@ -37,11 +37,11 @@ import ghidra.util.datastruct.WeakDataStructureFactory;
import ghidra.util.datastruct.WeakSet;
import ghidra.util.exception.NotFoundException;
-/**
+/**
* Provides a service for tracking the selected basic/subroutine block models for a tool.
* Methods are provided for obtaining an instance of the active or arbitrary block model.
- * A new model instance is always provided since the internal cache will quickly become
- * stale based upon program changes. The current model implementations do not handle
+ * A new model instance is always provided since the internal cache will quickly become
+ * stale based upon program changes. The current model implementations do not handle
* program changes which would invalidate the cached blocks stored within the model.
*
* A single basic/sub model list is maintained since it is possible that some uses
@@ -111,9 +111,12 @@ public class BlockModelServicePlugin extends ProgramPlugin
// Install model selection option in Tool panel
options = tool.getOptions(ToolConstants.TOOL_OPTIONS);
- editor = new StringWithChoicesEditor(availableModelNames);
options.registerOption(SUB_OPTION, OptionType.STRING_TYPE, selectedSubroutineModelName,
- null, "The default subroutine model used when creating call graphs.", editor);
+ null, "The default subroutine model used when creating call graphs.",
+ () -> {
+ editor = new StringWithChoicesEditor(availableModelNames);
+ return editor;
+ });
setPreferedModel(options);
updateModelOptions();
options.addOptionsChangeListener(this);
@@ -168,7 +171,9 @@ public class BlockModelServicePlugin extends ProgramPlugin
modelUpdateInProgress = true;
try {
- editor.setChoices(availableModelNames);
+ if (editor != null) {
+ editor.setChoices(availableModelNames);
+ }
options.setString(SUB_OPTION, selectedSubroutineModelName);
}
finally {
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/AbstractCodeBrowserPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/AbstractCodeBrowserPlugin.java
index 38945157ff..d8fd98c53e 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/AbstractCodeBrowserPlugin.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/AbstractCodeBrowserPlugin.java
@@ -98,7 +98,7 @@ public abstract class AbstractCodeBrowserPlugin
ex
ToolOptions displayOptions = tool.getOptions(GhidraOptions.CATEGORY_BROWSER_DISPLAY);
ToolOptions fieldOptions = tool.getOptions(GhidraOptions.CATEGORY_BROWSER_FIELDS);
- displayOptions.registerOptionsEditor(new ListingDisplayOptionsEditor(displayOptions));
+ displayOptions.registerOptionsEditor(() -> new ListingDisplayOptionsEditor(displayOptions));
displayOptions.setOptionsHelpLocation(
new HelpLocation(getName(), GhidraOptions.CATEGORY_BROWSER_DISPLAY));
fieldOptions.setOptionsHelpLocation(
@@ -616,7 +616,7 @@ public abstract class AbstractCodeBrowserPlugin
ex
options.registerOption(ManualViewerCommandWrappedOption.MANUAL_VIEWER_OPTIONS,
OptionType.CUSTOM_TYPE,
ManualViewerCommandWrappedOption.getDefaultBrowserLoaderOptions(), helpLocation,
- "Options for running manual viewer", new ManualViewerCommandEditor());
+ "Options for running manual viewer", () -> new ManualViewerCommandEditor());
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramManagerPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramManagerPlugin.java
index a34139999a..8605ac8e9b 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramManagerPlugin.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramManagerPlugin.java
@@ -606,7 +606,7 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager, Opti
PropertyEditor editor = options.getPropertyEditor(filePropertyName);
if (editor == null && options.getType(filePropertyName) == OptionType.STRING_TYPE) {
options.registerOption(filePropertyName, OptionType.STRING_TYPE, null, null, null,
- new StringBasedFileEditor());
+ () -> new StringBasedFileEditor());
}
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AddressFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AddressFieldFactory.java
index 89b1d31480..9d29e56038 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AddressFieldFactory.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AddressFieldFactory.java
@@ -15,7 +15,6 @@
*/
package ghidra.app.util.viewer.field;
-import java.beans.PropertyEditor;
import java.math.BigInteger;
import docking.widgets.fieldpanel.field.*;
@@ -47,7 +46,6 @@ public class AddressFieldFactory extends FieldFactory {
private boolean padZeros;
private int minHexDigits;
private boolean rightJustify;
- private PropertyEditor addressFieldOptionsEditor = new AddressFieldOptionsPropertyEditor();
/**
* Default Constructor
@@ -74,7 +72,7 @@ public class AddressFieldFactory extends FieldFactory {
fieldOptions.registerOption(ADDRESS_DISPLAY_OPTIONS_NAME, OptionType.CUSTOM_TYPE,
new AddressFieldOptionsWrappedOption(), helpLoc, "Adjusts the Address Field display",
- addressFieldOptionsEditor);
+ () -> new AddressFieldOptionsPropertyEditor());
CustomOption customOption =
fieldOptions.getCustomOption(ADDRESS_DISPLAY_OPTIONS_NAME, null);
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/ArrayValuesFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/ArrayValuesFieldFactory.java
index 3f83282ad9..a467b26514 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/ArrayValuesFieldFactory.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/ArrayValuesFieldFactory.java
@@ -15,7 +15,6 @@
*/
package ghidra.app.util.viewer.field;
-import java.beans.PropertyEditor;
import java.math.BigInteger;
import docking.widgets.fieldpanel.field.*;
@@ -35,7 +34,6 @@ import ghidra.util.exception.AssertException;
public class ArrayValuesFieldFactory extends FieldFactory {
public static final String FIELD_NAME = "Array Values";
private int valuesPerLine;
- private PropertyEditor arrayOptionsEditor = new ArrayElementPropertyEditor();
public ArrayValuesFieldFactory() {
super(FIELD_NAME);
@@ -66,7 +64,7 @@ public class ArrayValuesFieldFactory extends FieldFactory {
// we need to install a custom editor that allows us to edit a group of related options
fieldOptions.registerOption(FormatManager.ARRAY_DISPLAY_OPTIONS, OptionType.CUSTOM_TYPE,
new ArrayElementWrappedOption(), null, FormatManager.ARRAY_DISPLAY_DESCRIPTION,
- arrayOptionsEditor);
+ () -> new ArrayElementPropertyEditor());
CustomOption wrappedOption = fieldOptions.getCustomOption(
FormatManager.ARRAY_DISPLAY_OPTIONS, new ArrayElementWrappedOption());
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/BrowserCodeUnitFormatOptions.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/BrowserCodeUnitFormatOptions.java
index 9b0993ece7..83e302d438 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/BrowserCodeUnitFormatOptions.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/BrowserCodeUnitFormatOptions.java
@@ -58,8 +58,8 @@ public class BrowserCodeUnitFormatOptions extends CodeUnitFormatOptions
GhidraOptions.OPERAND_GROUP_TITLE + Options.DELIMITER + "Always Show Primary Reference";
/**
- * Option for whether to follow referenced pointers, for read or indirect reference types,
- * to show pointer's referenced symbol instead of symbol at pointer. When applied the
+ * Option for whether to follow referenced pointers, for read or indirect reference types,
+ * to show pointer's referenced symbol instead of symbol at pointer. When applied the
* resulting label will be preceded by ->.
*/
private final static String FOLLOW_POINTER_REFERENCE_MARKUP_OPTION =
@@ -98,7 +98,7 @@ public class BrowserCodeUnitFormatOptions extends CodeUnitFormatOptions
* This constructor must be used by the field factory since an OptionsService may
* not obtainable at the time they are constructed.
* @param fieldOptions field options
- * @param autoUpdate if true format will auto update if associated options are changed, in
+ * @param autoUpdate if true format will auto update if associated options are changed, in
* addition any listeners will be notified when this format is updated.
*/
BrowserCodeUnitFormatOptions(ToolOptions fieldOptions, boolean autoUpdate) {
@@ -110,7 +110,7 @@ public class BrowserCodeUnitFormatOptions extends CodeUnitFormatOptions
if (!exists) {
fieldOptions.registerOption(NAMESPACE_OPTIONS, OptionType.CUSTOM_TYPE,
new NamespaceWrappedOption(), null, NAMESPACE_OPTIONS_DESCRIPTIONS,
- new NamespacePropertyEditor());
+ () -> new NamespacePropertyEditor());
HelpLocation hl = new HelpLocation("CodeBrowserPlugin", "Operands_Field");
fieldOptions.getOptions(GhidraOptions.OPERAND_GROUP_TITLE).setOptionsHelpLocation(hl);
@@ -165,7 +165,7 @@ public class BrowserCodeUnitFormatOptions extends CodeUnitFormatOptions
private void updateFormat() {
fieldOptions.registerOption(NAMESPACE_OPTIONS, OptionType.CUSTOM_TYPE,
new NamespaceWrappedOption(), null, NAMESPACE_OPTIONS_DESCRIPTIONS,
- new NamespacePropertyEditor());
+ () -> new NamespacePropertyEditor());
CustomOption customOption =
fieldOptions.getCustomOption(NAMESPACE_OPTIONS, new NamespaceWrappedOption());
if (!(customOption instanceof NamespaceWrappedOption)) {
@@ -240,9 +240,9 @@ public class BrowserCodeUnitFormatOptions extends CodeUnitFormatOptions
}
/**
- * Get current state of the Follow Referenced Pointers option.
- * @return true if operand pointer read of indirect references will be followed and
- * non-dynamic pointer referenced symbol will be rendered in place of pointer label.
+ * Get current state of the Follow Referenced Pointers option.
+ * @return true if operand pointer read of indirect references will be followed and
+ * non-dynamic pointer referenced symbol will be rendered in place of pointer label.
*/
public boolean followReferencedPointers() {
return followReferencedPointers;
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/EolCommentFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/EolCommentFieldFactory.java
index b457ea1841..884f8a6c45 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/EolCommentFieldFactory.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/EolCommentFieldFactory.java
@@ -16,7 +16,6 @@
package ghidra.app.util.viewer.field;
import java.awt.Color;
-import java.beans.PropertyEditor;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
@@ -67,7 +66,6 @@ public class EolCommentFieldFactory extends FieldFactory {
private int refRepeatableCommentStyle;
private EolExtraCommentsOption extraCommentsOption = new EolExtraCommentsOption();
- private PropertyEditor extraCommmentsEditor = new EolExtraCommentsPropertyEditor();
// The codeUnitFormatOptions is used to monitor "follow pointer..." option to avoid duplication
// of data within auto-comment. We don't bother adding a listener to kick the model since this
@@ -126,7 +124,7 @@ public class EolCommentFieldFactory extends FieldFactory {
private void setupAutoCommentOptions(Options fieldOptions, HelpLocation hl) {
fieldOptions.registerOption(EXTRA_COMMENT_KEY, OptionType.CUSTOM_TYPE,
new EolExtraCommentsOption(), hl, "The group of auto comment options",
- extraCommmentsEditor);
+ () -> new EolExtraCommentsPropertyEditor());
CustomOption customOption = fieldOptions.getCustomOption(EXTRA_COMMENT_KEY, null);
if (!(customOption instanceof EolExtraCommentsOption)) {
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/FileOffsetFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/FileOffsetFieldFactory.java
index 07a2c376dd..5a7280f49b 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/FileOffsetFieldFactory.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/FileOffsetFieldFactory.java
@@ -15,7 +15,6 @@
*/
package ghidra.app.util.viewer.field;
-import java.beans.PropertyEditor;
import java.math.BigInteger;
import docking.widgets.fieldpanel.field.*;
@@ -49,8 +48,6 @@ public class FileOffsetFieldFactory extends FieldFactory {
private boolean showFilename;
private boolean useHex;
- private PropertyEditor fileOffsetFieldOptionsEditor =
- new FileOffsetFieldOptionsPropertyEditor();
/**
* Default Constructor
@@ -77,7 +74,8 @@ public class FileOffsetFieldFactory extends FieldFactory {
fieldOptions.registerOption(FILE_OFFSET_DISPLAY_OPTIONS_NAME, OptionType.CUSTOM_TYPE,
new FileOffsetFieldOptionsWrappedOption(), helpLoc,
- "Adjusts the File Offset Field display", fileOffsetFieldOptionsEditor);
+ "Adjusts the File Offset Field display",
+ () -> new FileOffsetFieldOptionsPropertyEditor());
CustomOption customOption =
fieldOptions.getCustomOption(FILE_OFFSET_DISPLAY_OPTIONS_NAME, null);
@@ -97,7 +95,8 @@ public class FileOffsetFieldFactory extends FieldFactory {
@Override
public FieldFactory newInstance(FieldFormatModel formatModel,
- ListingHighlightProvider highlightProvider, ToolOptions options, ToolOptions fieldOptions) {
+ ListingHighlightProvider highlightProvider, ToolOptions options,
+ ToolOptions fieldOptions) {
return new FileOffsetFieldFactory(formatModel, highlightProvider, options, fieldOptions);
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/LabelFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/LabelFieldFactory.java
index 03a0155cd1..cd5d7b0ee3 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/LabelFieldFactory.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/LabelFieldFactory.java
@@ -15,7 +15,6 @@
*/
package ghidra.app.util.viewer.field;
-import java.beans.PropertyEditor;
import java.math.BigInteger;
import java.util.*;
@@ -60,8 +59,6 @@ public class LabelFieldFactory extends FieldFactory {
private Icon ANCHOR_ICON =
new MultiIcon(EMPTY_ICON, new GIcon("icon.base.util.viewer.fieldfactory.label"));
- private PropertyEditor namespaceOptionsEditor = new NamespacePropertyEditor();
-
private boolean displayFunctionLabel;
private boolean displayLocalNamespace;
private boolean displayNonLocalNamespace;
@@ -107,7 +104,7 @@ public class LabelFieldFactory extends FieldFactory {
// we need to install a custom editor that allows us to edit a group of related options
fieldOptions.registerOption(NAMESPACE_OPTIONS, OptionType.CUSTOM_TYPE,
new NamespaceWrappedOption(), null, "Adjusts the Label Field namespace display",
- namespaceOptionsEditor);
+ () -> new NamespacePropertyEditor());
CustomOption wrappedOption =
fieldOptions.getCustomOption(NAMESPACE_OPTIONS, new NamespaceWrappedOption());
if (!(wrappedOption instanceof NamespaceWrappedOption)) {
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/XRefFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/XRefFieldFactory.java
index a7b127977c..06260f24ad 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/XRefFieldFactory.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/XRefFieldFactory.java
@@ -17,7 +17,6 @@ package ghidra.app.util.viewer.field;
import java.awt.Color;
import java.awt.FontMetrics;
-import java.beans.PropertyEditor;
import java.math.BigInteger;
import java.util.*;
import java.util.Map.Entry;
@@ -75,8 +74,6 @@ public class XRefFieldFactory extends FieldFactory {
static final String GROUP_BY_FUNCTION_KEY =
GROUP_TITLE + Options.DELIMITER + "Group by Function";
- private PropertyEditor namespaceOptionsEditor = new NamespacePropertyEditor();
-
protected String delim = DELIMITER;
protected boolean displayBlockName;
protected boolean groupByFunction;
@@ -168,7 +165,7 @@ public class XRefFieldFactory extends FieldFactory {
// we need to install a custom editor that allows us to edit a group of related options
fieldOptions.registerOption(NAMESPACE_OPTIONS_KEY, OptionType.CUSTOM_TYPE,
new NamespaceWrappedOption(), new HelpLocation("CodeBrowserPlugin", "XREFs_Field"),
- "Adjusts the XREFs Field namespace display", namespaceOptionsEditor);
+ "Adjusts the XREFs Field namespace display", () -> new NamespacePropertyEditor());
CustomOption customOption = fieldOptions.getCustomOption(NAMESPACE_OPTIONS_KEY, null);
if (!(customOption instanceof NamespaceWrappedOption)) {
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FormatManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FormatManager.java
index 33c8111386..ff085e412a 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FormatManager.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FormatManager.java
@@ -71,7 +71,7 @@ public class FormatManager implements OptionsChangeListener {
TemplateSimplifier templateSimplifier;
// NOTE: Unused custom format code was removed. The custom format code last existed in
- // commit #204e7892bf2f110ebb05ca4beee3fe5b397f88c9.
+ // commit #204e7892bf2f110ebb05ca4beee3fe5b397f88c9.
/**
* Constructs a new FormatManager.
@@ -100,7 +100,7 @@ public class FormatManager implements OptionsChangeListener {
private void getArrayDisplayOptions(Options options) {
options.registerOption(ARRAY_DISPLAY_OPTIONS, OptionType.CUSTOM_TYPE,
new ArrayElementWrappedOption(), null, ARRAY_DISPLAY_DESCRIPTION,
- new ArrayElementPropertyEditor());
+ () -> new ArrayElementPropertyEditor());
CustomOption option = options.getCustomOption(ARRAY_DISPLAY_OPTIONS, null);
if (option instanceof ArrayElementWrappedOption) {
ArrayElementWrappedOption arrayOption = (ArrayElementWrappedOption) option;
@@ -174,7 +174,7 @@ public class FormatManager implements OptionsChangeListener {
/**
* Returns the total number of model in the format manager.
- * @return the total number of model in the format manager
+ * @return the total number of model in the format manager
*/
public int getNumModels() {
return NUM_MODELS;
@@ -200,7 +200,7 @@ public class FormatManager implements OptionsChangeListener {
/**
* Returns the format model for the plate field.
- * @return the format model for the plate field
+ * @return the format model for the plate field
*/
public FieldFormatModel getPlateFormat() {
return models[FieldFormatModel.PLATE];
@@ -279,7 +279,7 @@ public class FormatManager implements OptionsChangeListener {
/**
* Returns the Options used for field specific properties.
- * @return the Options used for field specific properties
+ * @return the Options used for field specific properties
*/
public ToolOptions getFieldOptions() {
return fieldOptions;
@@ -847,7 +847,7 @@ public class FormatManager implements OptionsChangeListener {
}
/**
- * Gets all {@link ListingHighlightProvider}s installed on this FormatManager via the
+ * Gets all {@link ListingHighlightProvider}s installed on this FormatManager via the
* {@link #addHighlightProvider(ListingHighlightProvider)}.
*
* @return all {@link ListingHighlightProvider}s installed on this FormatManager.
@@ -930,12 +930,12 @@ public class FormatManager implements OptionsChangeListener {
public Highlight[] createHighlights(String text, ListingField field, int cursorTextOffset) {
//
- // Gather and use all other registered providers.
- //
+ // Gather and use all other registered providers.
+ //
// Note: we loop backwards here as a hacky method to make sure that the middle-mouse
- // highlighter runs last and is thus painted above other highlights. This
- // works because the middle-mouse highlighter is installed before any other
- // highlighters.
+ // highlighter runs last and is thus painted above other highlights. This
+ // works because the middle-mouse highlighter is installed before any other
+ // highlighters.
List list = new ArrayList<>();
int size = highlightProviders.size();
for (int i = size - 1; i >= 0; i--) {
diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/misc/PropertyEditorTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/misc/PropertyEditorTest.java
index 04709a96a7..8722978282 100644
--- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/misc/PropertyEditorTest.java
+++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/misc/PropertyEditorTest.java
@@ -15,8 +15,7 @@
*/
package ghidra.app.plugin.core.misc;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.*;
import java.awt.Component;
import java.awt.Container;
@@ -53,7 +52,7 @@ public class PropertyEditorTest extends AbstractGhidraHeadedIntegrationTest {
runSwing(() -> DockingDialog.createDialog(null, dialogComponent, null));
SwingUtilities.invokeLater(() -> editorDialog.setVisible(true));
- waitForJDialog(null, "Test Properties", 500);
+ waitForJDialog("Test Properties");
assertNotNull("Dialog failed to launch", editorDialog);
waitForSwing();
waitForOptionsTree(dialogComponent);
@@ -219,7 +218,7 @@ public class PropertyEditorTest extends AbstractGhidraHeadedIntegrationTest {
Options options = new ToolOptions("Test");
String[] choices = new String[] { "abc", "def", "ghi", "jkl" };
options.registerOption("TestStringWithChoices", OptionType.STRING_TYPE, choices[0], null,
- "String Choices", new StringWithChoicesEditor(choices));
+ "String Choices", () -> new StringWithChoicesEditor(choices));
dialog = showEditor(options);
diff --git a/Ghidra/Features/Base/src/test/java/ghidra/framework/data/OptionsDBTest.java b/Ghidra/Features/Base/src/test/java/ghidra/framework/data/OptionsDBTest.java
index 9df103ea09..62bb3efeee 100644
--- a/Ghidra/Features/Base/src/test/java/ghidra/framework/data/OptionsDBTest.java
+++ b/Ghidra/Features/Base/src/test/java/ghidra/framework/data/OptionsDBTest.java
@@ -303,7 +303,7 @@ public class OptionsDBTest extends AbstractDockingTest {
@Test
public void testRegisterPropertyEditor() {
MyPropertyEditor editor = new MyPropertyEditor();
- options.registerOption("foo", OptionType.INT_TYPE, 5, null, "description", editor);
+ options.registerOption("foo", OptionType.INT_TYPE, 5, null, "description", () -> editor);
assertEquals(editor, options.getRegisteredPropertyEditor("foo"));
}
@@ -561,12 +561,11 @@ public class OptionsDBTest extends AbstractDockingTest {
@Test
public void testRegisteringOptionsEditor() {
MyOptionsEditor myOptionsEditor = new MyOptionsEditor();
- options.registerOptionsEditor(myOptionsEditor);
+ options.registerOptionsEditor(() -> myOptionsEditor);
assertEquals(myOptionsEditor, options.getOptionsEditor());
Options subOptions = options.getOptions("SUB");
- subOptions.registerOptionsEditor(myOptionsEditor);
+ subOptions.registerOptionsEditor(() -> myOptionsEditor);
assertEquals(myOptionsEditor, subOptions.getOptionsEditor());
-
}
@Test
diff --git a/Ghidra/Features/Base/src/test/java/ghidra/framework/options/OptionsTest.java b/Ghidra/Features/Base/src/test/java/ghidra/framework/options/OptionsTest.java
index 3b627130c3..68e970cc52 100644
--- a/Ghidra/Features/Base/src/test/java/ghidra/framework/options/OptionsTest.java
+++ b/Ghidra/Features/Base/src/test/java/ghidra/framework/options/OptionsTest.java
@@ -296,7 +296,8 @@ public class OptionsTest extends AbstractGuiTest {
@Test
public void testRegisterPropertyEditor() {
MyPropertyEditor editor = new MyPropertyEditor();
- options.registerOption("color", OptionType.COLOR_TYPE, Color.RED, null, "foo", editor);
+ options.registerOption("color", OptionType.COLOR_TYPE, Color.RED, null, "foo",
+ () -> editor);
assertEquals(editor, options.getRegisteredPropertyEditor("color"));
}
@@ -570,10 +571,10 @@ public class OptionsTest extends AbstractGuiTest {
@Test
public void testRegisteringOptionsEditor() {
MyOptionsEditor myOptionsEditor = new MyOptionsEditor();
- options.registerOptionsEditor(myOptionsEditor);
+ options.registerOptionsEditor(() -> myOptionsEditor);
assertEquals(myOptionsEditor, options.getOptionsEditor());
Options subOptions = options.getOptions("SUB");
- subOptions.registerOptionsEditor(myOptionsEditor);
+ subOptions.registerOptionsEditor(() -> myOptionsEditor);
assertEquals(myOptionsEditor, subOptions.getOptionsEditor());
}
diff --git a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/plugin/core/analysis/GnuDemanglerAnalyzer.java b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/plugin/core/analysis/GnuDemanglerAnalyzer.java
index 52a70190c5..252ed6b38c 100644
--- a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/plugin/core/analysis/GnuDemanglerAnalyzer.java
+++ b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/plugin/core/analysis/GnuDemanglerAnalyzer.java
@@ -15,8 +15,7 @@
*/
package ghidra.app.plugin.core.analysis;
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
+import java.beans.*;
import java.util.Arrays;
import docking.options.editor.BooleanEditor;
@@ -93,24 +92,16 @@ public class GnuDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
options.registerOption(OPTION_NAME_DEMANGLE_USE_KNOWN_PATTERNS, demangleOnlyKnownPatterns,
help, OPTION_DESCRIPTION_USE_KNOWN_PATTERNS);
- BooleanEditor deprecatedEditor = null;
- FormatEditor formatEditor = null;
- if (!SystemUtilities.isInHeadlessMode()) {
- // Only add the custom options editor when not headless. The custom editor allows
- // the list of choices presented to the user to change depending on the state of the
- // useDeprecatedDemangler flag.
- deprecatedEditor = new BooleanEditor();
- deprecatedEditor.setValue(Boolean.valueOf(useDeprecatedDemangler));
- formatEditor = new FormatEditor(demanglerFormat, deprecatedEditor);
- deprecatedEditor.addPropertyChangeListener(formatEditor);
- }
+ GnuOptionsEditor optionsEditor = new GnuOptionsEditor();
options.registerOption(OPTION_NAME_USE_DEPRECATED_DEMANGLER, OptionType.BOOLEAN_TYPE,
useDeprecatedDemangler, help, OPTION_DESCRIPTION_DEPRECATED_DEMANGLER,
- deprecatedEditor);
+ () -> optionsEditor.getDeprecatedNameEditor());
options.registerOption(OPTION_NAME_DEMANGLER_FORMAT, OptionType.ENUM_TYPE,
- demanglerFormat, help, OPTION_DESCRIPTION_DEMANGLER_FORMAT, formatEditor);
+ demanglerFormat, help, OPTION_DESCRIPTION_DEMANGLER_FORMAT,
+ () -> optionsEditor.getFormatEditor());
+
}
@Override
@@ -143,6 +134,45 @@ public class GnuDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
return demangler.demangle(mangled, demanglerOtions);
}
+//==================================================================================================
+// Inner Classes
+//==================================================================================================
+
+ // We only use the editor when not headless, since GUI code in headless will throw an exception.
+ // Further, the options below have a relationship, so we need to build them together.
+ // The format editor's list of choices presented to the user will change depending on the state
+ // of the deprecated boolean editor.
+ private class GnuOptionsEditor {
+
+ private BooleanEditor deprecatedEditor;
+ private FormatEditor formatEditor;
+
+ private void lazyInit() {
+ if (SystemUtilities.isInHeadlessMode()) {
+ return; // the editor should not be requested in headless mode
+ }
+
+ if (deprecatedEditor != null) {
+ return; // already loaded
+ }
+
+ deprecatedEditor = new BooleanEditor();
+ deprecatedEditor.setValue(Boolean.valueOf(useDeprecatedDemangler));
+ formatEditor = new FormatEditor(demanglerFormat, deprecatedEditor);
+ deprecatedEditor.addPropertyChangeListener(formatEditor);
+ }
+
+ PropertyEditor getDeprecatedNameEditor() {
+ lazyInit();
+ return deprecatedEditor;
+ }
+
+ PropertyEditor getFormatEditor() {
+ lazyInit();
+ return formatEditor;
+ }
+ }
+
private static class FormatEditor extends EnumEditor implements PropertyChangeListener {
private final FormatSelector selector;
@@ -221,6 +251,5 @@ public class GnuDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
void setFormat(GnuDemanglerFormat format) {
setSelectedItem(format.name());
}
-
}
}
diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTPlugin.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTPlugin.java
index 9bbd0e9624..c83da509d1 100644
--- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTPlugin.java
+++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTPlugin.java
@@ -133,7 +133,7 @@ public class VTPlugin extends Plugin {
private void initializeOptions() {
Options options = tool.getOptions(GhidraOptions.CATEGORY_BROWSER_DISPLAY);
- options.registerOptionsEditor(new ListingDisplayOptionsEditor(options));
+ options.registerOptionsEditor(() -> new ListingDisplayOptionsEditor(options));
options.setOptionsHelpLocation(new HelpLocation(CodeBrowserPlugin.class.getSimpleName(),
GhidraOptions.CATEGORY_BROWSER_DISPLAY));
diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/VTMatchTableProvider.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/VTMatchTableProvider.java
index 478b09cfd9..a6110bd493 100644
--- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/VTMatchTableProvider.java
+++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/matchtable/VTMatchTableProvider.java
@@ -15,159 +15,34 @@
*/
package ghidra.feature.vt.gui.provider.matchtable;
-import static ghidra.feature.vt.gui.actions.TableSelectionTrackingState.MAINTAIN_SELECTED_ROW_INDEX;
-import static ghidra.feature.vt.gui.actions.TableSelectionTrackingState.MAINTAIN_SELECTED_ROW_VALUE;
-import static ghidra.feature.vt.gui.actions.TableSelectionTrackingState.NO_SELECTION_TRACKING;
-import static ghidra.feature.vt.gui.plugin.VTPlugin.FILTERED_ICON;
-import static ghidra.feature.vt.gui.plugin.VTPlugin.UNFILTERED_ICON;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.ACCEPT_MATCH_OPTIONS_NAME;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.APPLY_DATA_NAME_ON_ACCEPT;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.APPLY_FUNCTION_NAME_ON_ACCEPT;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.APPLY_IMPLIED_MATCHES_OPTION;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.APPLY_MARKUP_OPTIONS_NAME;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.AUTO_CREATE_IMPLIED_MATCH;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.AUTO_VT_DATA_CORRELATOR;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.AUTO_VT_DUPLICATE_FUNCTION_CORRELATOR;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.AUTO_VT_EXACT_FUNCTION_CORRELATORS;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.AUTO_VT_IMPLIED_MATCH_CORRELATOR;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.AUTO_VT_OPTIONS_NAME;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.AUTO_VT_REFERENCE_CORRELATORS;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.AUTO_VT_SYMBOL_CORRELATOR;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.CALLING_CONVENTION;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.CALL_FIXUP;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.CREATE_IMPLIED_MATCHES_OPTION;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DATA_CORRELATOR_MIN_LEN_OPTION;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DATA_MATCH_DATA_TYPE;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_CALLING_CONVENTION;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_CALL_FIXUP;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_DATA_MATCH_DATA_TYPE;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_EOL_COMMENTS;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_FUNCTION_NAME;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_FUNCTION_RETURN_TYPE;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_FUNCTION_SIGNATURE;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_HIGHEST_NAME_PRIORITY;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_IGNORE_EXCLUDED_MARKUP_ITEMS;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_IGNORE_INCOMPLETE_MARKUP_ITEMS;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_INLINE;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_LABELS;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_NO_RETURN;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_PARAMETER_COMMENTS;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_PARAMETER_DATA_TYPES;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_PARAMETER_NAMES;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_PARAMETER_NAMES_REPLACE_IF_SAME_PRIORITY;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_PLATE_COMMENTS;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_POST_COMMENTS;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_PRE_COMMENTS;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_REPEATABLE_COMMENTS;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_VAR_ARGS;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DISPLAY_APPLY_MARKUP_OPTIONS;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.DUPE_FUNCTION_CORRELATOR_MIN_LEN_OPTION;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.END_OF_LINE_COMMENT;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.FUNCTION_CORRELATOR_MIN_LEN_OPTION;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.FUNCTION_NAME;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.FUNCTION_RETURN_TYPE;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.FUNCTION_SIGNATURE;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.HIGHEST_NAME_PRIORITY;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.IGNORE_EXCLUDED_MARKUP_ITEMS;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.IGNORE_INCOMPLETE_MARKUP_ITEMS;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.INLINE;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.LABELS;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.MAX_CONFLICTS_OPTION;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.MIN_VOTES_OPTION;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.NO_RETURN;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.PARAMETER_COMMENTS;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.PARAMETER_DATA_TYPES;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.PARAMETER_NAMES;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.PARAMETER_NAMES_REPLACE_IF_SAME_PRIORITY;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.PLATE_COMMENT;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.POST_COMMENT;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.PRE_COMMENT;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.REF_CORRELATOR_MIN_CONF_OPTION;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.REF_CORRELATOR_MIN_SCORE_OPTION;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.REPEATABLE_COMMENT;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.RUN_DUPE_FUNCTION_OPTION;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.RUN_EXACT_DATA_OPTION;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.RUN_EXACT_FUNCTION_BYTES_OPTION;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.RUN_EXACT_FUNCTION_INST_OPTION;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.RUN_EXACT_SYMBOL_OPTION;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.RUN_REF_CORRELATORS_OPTION;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.SYMBOL_CORRELATOR_MIN_LEN_OPTION;
-import static ghidra.feature.vt.gui.util.VTOptionDefines.VAR_ARGS;
+import static ghidra.feature.vt.gui.actions.TableSelectionTrackingState.*;
+import static ghidra.feature.vt.gui.plugin.VTPlugin.*;
+import static ghidra.feature.vt.gui.util.VTOptionDefines.*;
-import java.awt.Adjustable;
-import java.awt.BorderLayout;
-import java.awt.Dimension;
-import java.awt.Rectangle;
-import java.awt.event.FocusAdapter;
-import java.awt.event.FocusEvent;
-import java.awt.event.MouseEvent;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
import java.util.List;
-import java.util.Set;
-import javax.swing.BorderFactory;
-import javax.swing.JButton;
-import javax.swing.JComponent;
-import javax.swing.JPanel;
-import javax.swing.JScrollBar;
-import javax.swing.JTable;
-import javax.swing.ListSelectionModel;
+import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
-import javax.swing.table.TableCellRenderer;
-import javax.swing.table.TableColumn;
-import javax.swing.table.TableColumnModel;
+import javax.swing.table.*;
-import docking.ActionContext;
-import docking.DockingWindowManager;
-import docking.WindowPosition;
-import docking.widgets.table.AbstractSortedTableModel;
-import docking.widgets.table.GTable;
-import docking.widgets.table.RowObjectSelectionManager;
-import docking.widgets.table.RowObjectTableModel;
-import docking.widgets.table.SelectionManager;
+import docking.*;
+import docking.widgets.table.*;
import docking.widgets.table.threaded.ThreadedTableModel;
import ghidra.feature.vt.api.impl.VTChangeManager;
import ghidra.feature.vt.api.impl.VersionTrackingChangeRecord;
-import ghidra.feature.vt.api.main.VTMarkupItem;
-import ghidra.feature.vt.api.main.VTMatch;
-import ghidra.feature.vt.api.main.VTSession;
-import ghidra.feature.vt.gui.actions.AcceptMatchAction;
-import ghidra.feature.vt.gui.actions.ApplyBlockedMatchAction;
-import ghidra.feature.vt.gui.actions.ApplyMatchAction;
-import ghidra.feature.vt.gui.actions.ChooseMatchTagAction;
-import ghidra.feature.vt.gui.actions.ClearMatchAction;
-import ghidra.feature.vt.gui.actions.CreateSelectionAction;
-import ghidra.feature.vt.gui.actions.EditAllTagsAction;
-import ghidra.feature.vt.gui.actions.MatchTableSelectionAction;
-import ghidra.feature.vt.gui.actions.RejectMatchAction;
-import ghidra.feature.vt.gui.actions.RemoveMatchAction;
-import ghidra.feature.vt.gui.actions.RemoveMatchTagAction;
-import ghidra.feature.vt.gui.actions.TableSelectionTrackingState;
+import ghidra.feature.vt.api.main.*;
+import ghidra.feature.vt.gui.actions.*;
import ghidra.feature.vt.gui.editors.MatchTagCellEditor;
-import ghidra.feature.vt.gui.filters.AncillaryFilterDialogComponentProvider;
-import ghidra.feature.vt.gui.filters.Filter;
+import ghidra.feature.vt.gui.filters.*;
import ghidra.feature.vt.gui.filters.Filter.FilterEditingStatus;
-import ghidra.feature.vt.gui.filters.FilterDialogModel;
-import ghidra.feature.vt.gui.filters.FilterStatusListener;
-import ghidra.feature.vt.gui.plugin.VTController;
-import ghidra.feature.vt.gui.plugin.VTControllerListener;
-import ghidra.feature.vt.gui.plugin.VTPlugin;
-import ghidra.feature.vt.gui.plugin.VersionTrackingPluginPackage;
-import ghidra.feature.vt.gui.util.AbstractVTMatchTableModel.DestinationLabelTableColumn;
-import ghidra.feature.vt.gui.util.AbstractVTMatchTableModel.SourceLabelTableColumn;
-import ghidra.feature.vt.gui.util.AbstractVTMatchTableModel.StatusTableColumn;
-import ghidra.feature.vt.gui.util.AbstractVTMatchTableModel.TagTableColumn;
-import ghidra.feature.vt.gui.util.AllTextFilter;
-import ghidra.feature.vt.gui.util.FilterIconFlashTimer;
-import ghidra.feature.vt.gui.util.MatchInfo;
-import ghidra.feature.vt.gui.util.MatchStatusRenderer;
-import ghidra.feature.vt.gui.util.VTSymbolRenderer;
-import ghidra.framework.model.DomainObject;
-import ghidra.framework.model.DomainObjectChangeRecord;
-import ghidra.framework.model.DomainObjectChangedEvent;
+import ghidra.feature.vt.gui.plugin.*;
+import ghidra.feature.vt.gui.util.*;
+import ghidra.feature.vt.gui.util.AbstractVTMatchTableModel.*;
+import ghidra.framework.model.*;
import ghidra.framework.options.Options;
import ghidra.framework.options.SaveState;
import ghidra.framework.plugintool.ComponentProviderAdapter;
@@ -828,26 +703,28 @@ public class VTMatchTableProvider extends ComponentProviderAdapter
"should become ignored by applying a match.");
vtOptions.getOptions(APPLY_MARKUP_OPTIONS_NAME)
- .registerOptionsEditor(new ApplyMarkupPropertyEditor(controller));
+ .registerOptionsEditor(() -> new ApplyMarkupPropertyEditor(controller));
vtOptions.getOptions(DISPLAY_APPLY_MARKUP_OPTIONS)
.setOptionsHelpLocation(
new HelpLocation("VersionTracking", "Apply Markup Options"));
-
// Auto VT options
// put checkboxes to determine which correlators to run during auto VT
vtOptions.registerOption(CREATE_IMPLIED_MATCHES_OPTION, true, null,
"Create Implied Matches when AutoVT correlators apply function matches.");
- vtOptions.registerOption(RUN_EXACT_DATA_OPTION, true, null, "Run the Exact Data Correlator");
- vtOptions.registerOption(RUN_EXACT_SYMBOL_OPTION, true, null, "Run the Exact Symbol Correlator");
+ vtOptions.registerOption(RUN_EXACT_DATA_OPTION, true, null,
+ "Run the Exact Data Correlator");
+ vtOptions.registerOption(RUN_EXACT_SYMBOL_OPTION, true, null,
+ "Run the Exact Symbol Correlator");
vtOptions.registerOption(RUN_EXACT_FUNCTION_BYTES_OPTION, true, null,
"Run the Exact Function Bytes Correlator");
vtOptions.registerOption(RUN_EXACT_FUNCTION_INST_OPTION, true, null,
"Run the Exact Function Instruction Bytes and Mnemonics Correlators");
vtOptions.registerOption(RUN_DUPE_FUNCTION_OPTION, true, null,
"Run the Duplicate Function Instruction Correlator");
- vtOptions.registerOption(RUN_REF_CORRELATORS_OPTION, true, null, "Run the Reference Correlators");
+ vtOptions.registerOption(RUN_REF_CORRELATORS_OPTION, true, null,
+ "Run the Reference Correlators");
// set help for the sub categories
diff --git a/Ghidra/Framework/Graph/src/main/java/ghidra/service/graph/GraphDisplayOptions.java b/Ghidra/Framework/Graph/src/main/java/ghidra/service/graph/GraphDisplayOptions.java
index df4ad9bae3..a17ec64b69 100644
--- a/Ghidra/Framework/Graph/src/main/java/ghidra/service/graph/GraphDisplayOptions.java
+++ b/Ghidra/Framework/Graph/src/main/java/ghidra/service/graph/GraphDisplayOptions.java
@@ -111,6 +111,7 @@ public class GraphDisplayOptions implements OptionsChangeListener {
* {@link GraphType}s that have options registered in the tool.
* @param graphType The {@link GraphType} for which to define display options
* @param tool the tool from which to initialize from {@link ToolOptions}
+ * @param help the help location
*/
protected GraphDisplayOptions(GraphType graphType, Tool tool, HelpLocation help) {
this(graphType);
@@ -380,7 +381,7 @@ public class GraphDisplayOptions implements OptionsChangeListener {
/**
* Sets the color for vertices with the given vertex type. Note that this method does not
- * allow the vertex color to be registered in tool options.
+ * allow the vertex color to be registered in tool options.
* See {@link #setVertexColor(String, String)}.
* @param vertexType the vertex type for which to set its color
* @param color the color to use for vertices with the given vertex type
@@ -392,7 +393,7 @@ public class GraphDisplayOptions implements OptionsChangeListener {
/**
* Sets the vertex color using a theme color id. By using a theme color id, this property
- * is eligible to be registered as a tool option.
+ * is eligible to be registered as a tool option.
* @param vertexType the vertex type for which to set its color
* @param themeColorId the theme color id of the color for this vertex type
*/
@@ -428,7 +429,7 @@ public class GraphDisplayOptions implements OptionsChangeListener {
/**
* Sets the edge color using a theme color id. By using a theme color id, this property
- * is eligible to be registered as a tool option.
+ * is eligible to be registered as a tool option.
* @param edgeType the edge type for which to set its color
* @param themeColorId the theme color id of the color for this edge type
*/
@@ -574,7 +575,7 @@ public class GraphDisplayOptions implements OptionsChangeListener {
/**
* Returns true if the rendering mode is to use icons for the vertices. If using
- * icons, the label is drawn inside the shape.
+ * icons, the label is drawn inside the shape.
* @return true if the rendering mode is to use icons.
*/
public boolean usesIcons() {
@@ -592,7 +593,7 @@ public class GraphDisplayOptions implements OptionsChangeListener {
}
/**
- * Returns the label position relative to the vertex. Note this is only relevant
+ * Returns the label position relative to the vertex. Note this is only relevant
* if {@link #usesIcons()} is false
* @return the label position relative to the vertex
*/
@@ -659,8 +660,8 @@ public class GraphDisplayOptions implements OptionsChangeListener {
}
/**
- * Sets the maximum number of nodes a graph can have and still be displayed. Be careful,
- * setting this value too high can result in Ghidra running out of memory and/or
+ * Sets the maximum number of nodes a graph can have and still be displayed. Be careful,
+ * setting this value too high can result in Ghidra running out of memory and/or
* making the system very sluggish.
* @param maxNodeCount the maximum number of nodes a graph can have and still be displayed.
*/
@@ -705,7 +706,7 @@ public class GraphDisplayOptions implements OptionsChangeListener {
* are registered with tool options, show the tool options with the appropriate
* graph options selected. Otherwise, show an editor for locally editing these
* options.
- * @param tool the tool
+ * @param tool the tool
* @param help the help location to use if the options are edited locally
*/
public void displayEditor(Tool tool, HelpLocation help) {
@@ -723,7 +724,7 @@ public class GraphDisplayOptions implements OptionsChangeListener {
}
// Otherwise, create a new empty options, register the graph options into the
- // those options and use our options editor on those options to allow the
+ // those options and use our options editor on those options to allow the
// user to change these graph display options.
ToolOptions transientOptions = new ToolOptions("Graph");
@@ -740,7 +741,7 @@ public class GraphDisplayOptions implements OptionsChangeListener {
}
/**
- * Sets default values for vertex types. This method does not allow the vertexType color to
+ * Sets default values for vertex types. This method does not allow the vertexType color to
* be eligible to be registered as a tool option.
* @param vertexType the vertex type whose default color and shape are being defined
* @param vertexShape the default vertex shape for the given vertex type
@@ -765,7 +766,7 @@ public class GraphDisplayOptions implements OptionsChangeListener {
}
/**
- * Sets default values for edge types. This method does not allow the vertexType color to
+ * Sets default values for edge types. This method does not allow the vertexType color to
* be eligible to be registered as a tool option.
* @param edgeType the edge type whose default color and shape are being defined
* @param color the default color for the given edge type
@@ -879,8 +880,7 @@ public class GraphDisplayOptions implements OptionsChangeListener {
}
}
List list = new ArrayList<>(graphType.getVertexTypes());
- OptionsEditor editor = new ScrollableOptionsEditor(VERTEX_COLORS, list);
- options.registerOptionsEditor(editor);
+ options.registerOptionsEditor(() -> new ScrollableOptionsEditor(VERTEX_COLORS, list));
}
private void registerVertexShapeOptions(Options rootOptions, HelpLocation help) {
@@ -889,14 +889,12 @@ public class GraphDisplayOptions implements OptionsChangeListener {
List shapeNames = VertexShape.getShapeNames();
for (String vertexType : graphType.getVertexTypes()) {
- StringWithChoicesEditor editor = new StringWithChoicesEditor(shapeNames);
options.registerOption(vertexType, OptionType.STRING_TYPE,
getVertexShapeName(vertexType), help, "Choose the shape for this vertex type",
- editor);
+ () -> new StringWithChoicesEditor(shapeNames));
}
List list = new ArrayList<>(graphType.getVertexTypes());
- OptionsEditor editor = new ScrollableOptionsEditor(VERTEX_SHAPES, list);
- options.registerOptionsEditor(editor);
+ options.registerOptionsEditor(() -> new ScrollableOptionsEditor(VERTEX_SHAPES, list));
}
private void registerEdgeColorOptions(Options rootOptions, HelpLocation help) {
@@ -909,8 +907,7 @@ public class GraphDisplayOptions implements OptionsChangeListener {
}
}
List list = new ArrayList<>(graphType.getEdgeTypes());
- OptionsEditor editor = new ScrollableOptionsEditor(EDGE_COLORS, list);
- options.registerOptionsEditor(editor);
+ options.registerOptionsEditor(() -> new ScrollableOptionsEditor(EDGE_COLORS, list));
}
private void registerMiscellaneousOptions(Options rootOptions, HelpLocation help) {
@@ -921,7 +918,6 @@ public class GraphDisplayOptions implements OptionsChangeListener {
optionNamesInDisplayOrder.add(MAX_NODES_SIZE);
options.registerOption(MAX_NODES_SIZE, OptionType.INT_TYPE, maxNodeCount, help,
"Graphs with more than this number of nodes will not be displayed. (Large graphs can cause Ghidra to become unstable/sluggish)");
- StringWithChoicesEditor editor = new StringWithChoicesEditor(VertexShape.getShapeNames());
if (defaultRegistrations.containsKey(VERTEX_SELECTION_COLOR)) {
optionNamesInDisplayOrder.add(VERTEX_SELECTION_COLOR);
@@ -954,20 +950,21 @@ public class GraphDisplayOptions implements OptionsChangeListener {
optionNamesInDisplayOrder.add(DEFAULT_VERTEX_SHAPE);
options.registerOption(DEFAULT_VERTEX_SHAPE, OptionType.STRING_TYPE,
defaultVertexShape.getName(), help,
- "Shape for vertices that have no vertex type defined", editor);
+ "Shape for vertices that have no vertex type defined",
+ () -> new StringWithChoicesEditor(VertexShape.getShapeNames()));
optionNamesInDisplayOrder.add(FAVORED_EDGE_TYPE);
List edgeTypes = graphType.getEdgeTypes();
if (!edgeTypes.isEmpty()) {
- editor = new StringWithChoicesEditor(edgeTypes);
options.registerOption(FAVORED_EDGE_TYPE, OptionType.STRING_TYPE, favoredEdgeType, help,
- "Favored edge is used to influence layout algorithms", editor);
+ "Favored edge is used to influence layout algorithms",
+ () -> new StringWithChoicesEditor(edgeTypes));
}
optionNamesInDisplayOrder.add(DEFAULT_LAYOUT_ALGORITHM);
- editor = new StringWithChoicesEditor(LayoutAlgorithmNames.getLayoutAlgorithmNames());
options.registerOption(DEFAULT_LAYOUT_ALGORITHM, OptionType.STRING_TYPE,
- defaultLayoutAlgorithmName, help, "Initial layout algorithm", editor);
+ defaultLayoutAlgorithmName, help, "Initial layout algorithm",
+ () -> new StringWithChoicesEditor(LayoutAlgorithmNames.getLayoutAlgorithmNames()));
optionNamesInDisplayOrder.add(LABEL_POSITION);
options.registerOption(LABEL_POSITION, OptionType.ENUM_TYPE, labelPosition, help,
@@ -982,11 +979,8 @@ public class GraphDisplayOptions implements OptionsChangeListener {
optionNamesInDisplayOrder.add(USE_ICONS);
options.registerOption(USE_ICONS, OptionType.BOOLEAN_TYPE, useIcons, help,
"If true, vertices are drawn using pre-rendered images versus compact shapes");
-
- OptionsEditor optionsEditor =
- new ScrollableOptionsEditor(MISCELLANEOUS_OPTIONS, optionNamesInDisplayOrder);
- options.registerOptionsEditor(optionsEditor);
-
+ options.registerOptionsEditor(
+ () -> new ScrollableOptionsEditor(MISCELLANEOUS_OPTIONS, optionNamesInDisplayOrder));
}
private void checkVertexType(String vertexType) {
diff --git a/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/AbstractOptions.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/AbstractOptions.java
index c1c4454790..fb3d854c6d 100644
--- a/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/AbstractOptions.java
+++ b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/AbstractOptions.java
@@ -21,17 +21,17 @@ import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;
import java.io.File;
import java.util.*;
+import java.util.function.Supplier;
import javax.swing.KeyStroke;
-import javax.swing.SwingUtilities;
import generic.theme.*;
-import ghidra.util.HelpLocation;
-import ghidra.util.Msg;
+import ghidra.util.*;
import ghidra.util.datastruct.WeakDataStructureFactory;
import ghidra.util.datastruct.WeakSet;
import ghidra.util.exception.AssertException;
import utilities.util.reflection.ReflectionUtilities;
+import utility.function.Dummy;
public abstract class AbstractOptions implements Options {
public static final Set> SUPPORTED_CLASSES = buildSupportedClassSet();
@@ -83,7 +83,14 @@ public abstract class AbstractOptions implements Options {
protected abstract boolean notifyOptionChanged(String optionName, Object oldValue,
Object newValue);
- public synchronized void registerOptionsEditor(String categoryPath, OptionsEditor editor) {
+ public synchronized void registerOptionsEditor(String categoryPath,
+ Supplier editorSupplier) {
+
+ OptionsEditor editor = null;
+ if (!SystemUtilities.isInHeadlessMode()) {
+ editor = editorSupplier.get();
+ }
+
optionsEditorMap.put(categoryPath, editor);
}
@@ -128,12 +135,13 @@ public abstract class AbstractOptions implements Options {
@Override
public void registerOption(String optionName, OptionType type, Object defaultValue,
HelpLocation help, String description) {
- registerOption(optionName, type, defaultValue, help, description, null);
+ registerOption(optionName, type, defaultValue, help, description,
+ (Supplier) null);
}
@Override
public synchronized void registerOption(String optionName, OptionType type, Object defaultValue,
- HelpLocation help, String description, PropertyEditor editor) {
+ HelpLocation help, String description, Supplier editorSupplier) {
if (type == OptionType.NO_TYPE) {
throw new IllegalArgumentException(
@@ -153,10 +161,20 @@ public abstract class AbstractOptions implements Options {
", defaultValue = " + defaultValue);
}
- if (type == OptionType.CUSTOM_TYPE && editor == null) {
- throw new IllegalStateException(
- "Can't register a custom option without a property editor");
+ editorSupplier = Dummy.ifNull(editorSupplier);
+ PropertyEditor editor = null;
+ boolean isHeadless = SystemUtilities.isInHeadlessMode();
+ if (!isHeadless) {
+ editor = editorSupplier.get();
}
+
+ if (type == OptionType.CUSTOM_TYPE) {
+ if (!isHeadless && editor == null) {
+ throw new IllegalStateException(
+ "Can't register a custom option without a property editor");
+ }
+ }
+
if (description == null) {
Msg.error(this, "Registered an option without a description: " + optionName,
ReflectionUtilities.createJavaFilteredThrowable());
@@ -169,7 +187,8 @@ public abstract class AbstractOptions implements Options {
}
Option option =
- createRegisteredOption(optionName, type, description, help, defaultValue, editor);
+ createRegisteredOption(optionName, type, description, help, defaultValue,
+ editor);
valueMap.put(optionName, option);
}
@@ -594,8 +613,8 @@ public abstract class AbstractOptions implements Options {
@Override
public PropertyEditor getPropertyEditor(String optionName) {
- if (!SwingUtilities.isEventDispatchThread()) {
- throw new IllegalStateException("This method must be called from the swing thread.");
+ if (!Swing.isSwingThread()) {
+ throw new IllegalStateException("This method must be called from the Swing thread");
}
Option option = getOption(optionName, OptionType.NO_TYPE, null);
PropertyEditor editor = option.getPropertyEditor();
@@ -688,8 +707,8 @@ public abstract class AbstractOptions implements Options {
}
@Override
- public synchronized void registerOptionsEditor(OptionsEditor editor) {
- optionsEditorMap.put("", editor);
+ public synchronized void registerOptionsEditor(Supplier editor) {
+ registerOptionsEditor("", editor);
}
@Override
diff --git a/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/Options.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/Options.java
index 821431476d..14c713cebe 100644
--- a/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/Options.java
+++ b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/Options.java
@@ -20,10 +20,13 @@ import java.awt.Font;
import java.beans.PropertyEditor;
import java.io.File;
import java.util.*;
+import java.util.function.Supplier;
import javax.swing.KeyStroke;
import ghidra.util.HelpLocation;
+import ghidra.util.Msg;
+import utilities.util.reflection.ReflectionUtilities;
public interface Options {
public static final char DELIMITER = '.';
@@ -108,11 +111,11 @@ public interface Options {
/**
* Registers an option with a description, help location, and a default value without specifying
* the option type. This form requires that the default value not be null so that the option
- * type can be inferred from the default value.
+ * type can be inferred from the default value.
*
* Note, this method should not be used for
* colors and font as doing so will result in those colors and fonts becoming disconnected
- * to the current theme. Instead use
+ * to the current theme. Instead use
*
* {@link #registerThemeColorBinding(String, String, HelpLocation, String)} or
* {@link #registerThemeFontBinding(String, String, HelpLocation, String)}.
@@ -133,7 +136,7 @@ public interface Options {
*
* Note, this method should not be used for
* colors and font as doing so will result in those colors and fonts becoming disconnected
- * to the current theme. Instead use
+ * to the current theme. Instead use
* {@link #registerThemeColorBinding(String, String, HelpLocation, String)} or
* {@link #registerThemeFontBinding(String, String, HelpLocation, String)}.
*
@@ -153,9 +156,16 @@ public interface Options {
*
* Note, this method should not be used for
* colors and font as doing so will result in those colors and fonts becoming disconnected
- * to the current theme. Instead use
+ * to the current theme. Instead use
* {@link #registerThemeColorBinding(String, String, HelpLocation, String)} or
* {@link #registerThemeFontBinding(String, String, HelpLocation, String)}.
+ *
+ * Note: we use a supplier of a custom editor, instead of a custom editor, to avoid
+ * creating {@link PropertyEditor}s until needed. This allows us to use the same API in both
+ * GUI mode and headless mode. If GUI property editors are created in headless mode, exceptions
+ * may be thrown. This API will not use the supplier when in headless mode, this avoiding the
+ * creation of GUI components. For this to work correctly, clients using custom property
+ * editors must defer construction of the editor until the supplier is called.
*
* @param optionName the name of the option being registered.
* @param type the OptionType for this options.
@@ -163,12 +173,37 @@ public interface Options {
* value may be null.
* @param help the HelpLocation for this option.
* @param description a description of the option.
- * @param editor an optional custom editor for this property. Note if the option is a custom option,
- * then the property editor can't be null;
+ * @param editor an optional supplier of a custom editor for this property. Note if the option
+ * is a custom option, then the property editor can't be null;
* @throws IllegalStateException if the options is a custom option and the editor is null.
*/
public void registerOption(String optionName, OptionType type, Object defaultValue,
- HelpLocation help, String description, PropertyEditor editor);
+ HelpLocation help, String description, Supplier editor);
+
+ /**
+ * Use instead
+ * {@link #registerOption(String, OptionType, Object, HelpLocation, String, Supplier)}
+ * @param optionName the name of the option being registered.
+ * @param type the OptionType for this options.
+ * @param defaultValue the defaultValue for the option. In this version of the method, the default
+ * value may be null.
+ * @param help the HelpLocation for this option.
+ * @param description a description of the option.
+ * @param editor an optional supplier of a custom editor for this property. Note if the option
+ * is a custom option, then the property editor can't be null;
+ * @deprecated Use instead
+ * {@link #registerOption(String, OptionType, Object, HelpLocation, String, Supplier)}
+ */
+ @Deprecated(since = "11.1", forRemoval = true)
+ default public void registerOption(String optionName, OptionType type, Object defaultValue,
+ HelpLocation help, String description, PropertyEditor editor) {
+ String caller = ReflectionUtilities.getClassNameOlderThan(Options.class);
+ String message = """
+ Using deprecated call to registerOption(PropertyEditor) from % for option %s
+ """.formatted(caller, optionName);
+ Msg.debug(this, message);
+ registerOption(optionName, type, defaultValue, help, description, () -> editor);
+ }
/**
* Register/binds the option to a theme color id. Changing the option's color via the options
@@ -185,7 +220,7 @@ public interface Options {
* Register/binds the option to a theme font id. Changing the option's font via the options
* Gui will result in directly changing the theme color of the given font id.
* @param optionName the name of the font option
- * @param fontId the theme color id whose color value is changed when the option's color
+ * @param fontId the theme color id whose color value is changed when the option's color
* is changed
* @param help the HelpLocation for this option
* @param description a description of the option
@@ -194,10 +229,34 @@ public interface Options {
String description);
/**
- * Register the options editor that will handle the editing for all the options or a sub group of options.
- * @param editor the custom editor panel to be used to edit the options or sub group of options.
+ * Register the options editor that will handle the editing for all the options or a sub-group
+ * of options.
+ *
+ * Note: we use a supplier of a custom editor, instead of a custom editor, to avoid
+ * creating {@link PropertyEditor}s until needed. This allows us to use the same API in both
+ * GUI mode and headless mode. If GUI property editors are created in headless mode, exceptions
+ * may be thrown. This API will not use the supplier when in headless mode, this avoiding the
+ * creation of GUI components. For this to work correctly, clients using custom property
+ * editors must defer construction of the editor until the supplier is called.
+ * @param editor a supplier for the custom editor panel to be used to edit the options or
+ * sub-group of options.
*/
- public void registerOptionsEditor(OptionsEditor editor);
+ public void registerOptionsEditor(Supplier editor);
+
+ /**
+ * Use instead {@link #registerOptionsEditor(Supplier)}
+ * @param editor the editor
+ * @deprecated Use instead {@link #registerOptionsEditor(Supplier)}
+ */
+ @Deprecated(since = "11.1", forRemoval = true)
+ default public void registerOptionsEditor(OptionsEditor editor) {
+ String caller = ReflectionUtilities.getClassNameOlderThan(Options.class);
+ String message = """
+ Using deprecated call to registerOption(OptionsEditor) from % for options %s
+ """.formatted(caller, getName());
+ Msg.debug(this, message);
+ registerOptionsEditor(() -> editor);
+ }
/**
* Get the editor that will handle editing all the values in this options or sub group of options.
diff --git a/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/SubOptions.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/SubOptions.java
index 53b72c9fdb..8a7cea7229 100644
--- a/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/SubOptions.java
+++ b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/SubOptions.java
@@ -20,6 +20,7 @@ import java.awt.Font;
import java.beans.PropertyEditor;
import java.io.File;
import java.util.*;
+import java.util.function.Supplier;
import javax.swing.KeyStroke;
@@ -61,7 +62,7 @@ public class SubOptions implements Options {
public List getChildOptions() {
List optionPaths = getOptionNames();
Set childCategories = AbstractOptions.getChildCategories(optionPaths);
- List childOptions = new ArrayList(childCategories.size());
+ List childOptions = new ArrayList<>(childCategories.size());
for (String categoryName : childCategories) {
childOptions.add(new SubOptions(options, categoryName, prefix + categoryName +
DELIMITER));
@@ -88,7 +89,7 @@ public class SubOptions implements Options {
@Override
public void registerOption(String optionName, OptionType type, Object defaultValue,
- HelpLocation help, String description, PropertyEditor editor) {
+ HelpLocation help, String description, Supplier editor) {
options.registerOption(prefix + optionName, type, defaultValue, help, description, editor);
}
@@ -252,7 +253,7 @@ public class SubOptions implements Options {
@Override
public List getOptionNames() {
List allOptionPaths = options.getOptionNames();
- List names = new ArrayList();
+ List names = new ArrayList<>();
for (String path : allOptionPaths) {
if (path.startsWith(prefix)) {
names.add(path.substring(prefix.length()));
@@ -317,7 +318,7 @@ public class SubOptions implements Options {
}
@Override
- public void registerOptionsEditor(OptionsEditor editor) {
+ public void registerOptionsEditor(Supplier editor) {
options.registerOptionsEditor(prefix, editor);
}
@@ -378,7 +379,7 @@ public class SubOptions implements Options {
public List getLeafOptionNames() {
List optionPaths = getOptionNames();
Set leaves = AbstractOptions.getLeaves(optionPaths);
- return new ArrayList(leaves);
+ return new ArrayList<>(leaves);
}
@Override
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/mgr/OptionsManager.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/mgr/OptionsManager.java
index 2ddef1377a..e93ba220d5 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/mgr/OptionsManager.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/mgr/OptionsManager.java
@@ -238,7 +238,7 @@ public class OptionsManager implements OptionsService, OptionsChangeListener {
oldEditor.dispose();
}
- keyBindingOptions.registerOptionsEditor(new KeyBindingOptionsEditor());
+ keyBindingOptions.registerOptionsEditor(() -> new KeyBindingOptionsEditor());
OptionsDialog dialog =
new OptionsDialog("Options for " + tool.getName(), "Options", getEditableOptions(),
null, true);
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramCompilerSpec.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramCompilerSpec.java
index a086a0fd89..91c4373868 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramCompilerSpec.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramCompilerSpec.java
@@ -363,7 +363,7 @@ public class ProgramCompilerSpec extends BasicCompilerSpec {
OptionType.STRING_TYPE, evalChoices[0],
new HelpLocation("DecompilePlugin", "OptionProtoEval"),
"Select the default function prototype/evaluation model to be used during Decompiler analysis",
- new StringWithChoicesEditor(evalChoices));
+ () -> new StringWithChoicesEditor(evalChoices));
// TODO: registration of DECOMPILER_OUTPUT_LANGUAGE option should be tied to Processor
// and not presence of stored option.
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/SpecExtension.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/SpecExtension.java
index 8589e7d180..e89f614cfb 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/SpecExtension.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/SpecExtension.java
@@ -36,7 +36,7 @@ import ghidra.xml.*;
* Utility class for installing/removing "specification extensions" to a Program.
* A specification extension is a program specific version of either a:
* - Prototype Model
- * - Call Fixup or
+ * - Call Fixup or
* - Callother Fixup
* Normally these objects are provided by the language specific configuration files (.cspec or .pspec),
* but this class allows additional objects to be added that are specific to the program.
@@ -48,7 +48,7 @@ import ghidra.xml.*;
* - \ - describing a Callother Fixup
* - \ - describing a typical Prototype Model
* - \ - describing a Prototype Model merged from other models
- *
+ *
* Each type of object has a unique name or target, which must be specified as part of the XML tag,
* which is referred to in this class as the extension's "formal name". In the \ tag,
* the formal name is given by the "targetop" attribute; for all the other tags, the formal name is
@@ -332,7 +332,7 @@ public class SpecExtension {
if (!SystemUtilities.isInHeadlessMode()) {
Options options = program.getOptions(SPEC_EXTENSION);
options.setOptionsHelpLocation(new HelpLocation("DecompilePlugin", "ExtensionOptions"));
- options.registerOptionsEditor(new SpecExtensionEditor((ProgramDB) program));
+ options.registerOptionsEditor(() -> new SpecExtensionEditor((ProgramDB) program));
}
}