mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-01-21 00:40:10 +00:00
Merge remote-tracking branch
'origin/GP-1-dragonmacher-help-headless-fix' Conflicts: Ghidra/Framework/Help/src/main/java/help/GHelpBuilder.java
This commit is contained in:
commit
75ddd08bbd
@ -33,14 +33,15 @@ import ghidra.util.filechooser.ExtensionFileFilter;
|
||||
|
||||
/**
|
||||
* Some common methods related to saving themes. These are invoked from various places to handle
|
||||
* what to do if a change is made that would result in loosing theme changes.
|
||||
* what to do if a change is made that would result in loosing theme changes.
|
||||
*/
|
||||
public class ThemeUtils {
|
||||
|
||||
/**
|
||||
* Asks the user if they want to save the current theme changes. If they answer yes, it
|
||||
* will handle several use cases such as whether it gets saved to a new file or
|
||||
* will handle several use cases such as whether it gets saved to a new file or
|
||||
* overwrites an existing file.
|
||||
* @param themeManager the theme manager
|
||||
* @return true if the operation was not cancelled
|
||||
*/
|
||||
public static boolean askToSaveThemeChanges(ThemeManager themeManager) {
|
||||
@ -61,6 +62,7 @@ public class ThemeUtils {
|
||||
/**
|
||||
* Saves all current theme changes. Handles several use cases such as requesting a new theme
|
||||
* name and asking to overwrite an existing file.
|
||||
* @param themeManager the theme manager
|
||||
* @return true if the operation was not cancelled
|
||||
*/
|
||||
public static boolean saveThemeChanges(ThemeManager themeManager) {
|
||||
@ -78,10 +80,11 @@ public class ThemeUtils {
|
||||
|
||||
/**
|
||||
* Resets the theme to the default, handling the case where the current theme has changes.
|
||||
* @param themeManager the theme manager
|
||||
*/
|
||||
public static void resetThemeToDefault(ThemeManager themeManager) {
|
||||
if (askToSaveThemeChanges(themeManager)) {
|
||||
themeManager.setTheme(themeManager.getDefaultTheme());
|
||||
themeManager.setTheme(ThemeManager.getDefaultTheme());
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,7 +132,7 @@ public class ThemeUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports a theme, prompting the user to pick an file. Also handles dealing with any
|
||||
* Exports a theme, prompting the user to pick an file. Also handles dealing with any
|
||||
* existing changes to the current theme.
|
||||
* @param themeManager the ThemeManager that actually does the export
|
||||
*/
|
||||
@ -138,9 +141,8 @@ public class ThemeUtils {
|
||||
return;
|
||||
}
|
||||
boolean hasExternalIcons = !themeManager.getActiveTheme().getExternalIconFiles().isEmpty();
|
||||
String message =
|
||||
"Export as zip file? (You are not using any external icons so the zip\n" +
|
||||
"file would only contain a single theme file.)";
|
||||
String message = "Export as zip file? (You are not using any external icons so the zip\n" +
|
||||
"file would only contain a single theme file.)";
|
||||
if (hasExternalIcons) {
|
||||
message =
|
||||
"Export as zip file? (You have external icons so a zip file is required if you\n" +
|
||||
@ -159,6 +161,7 @@ public class ThemeUtils {
|
||||
|
||||
/**
|
||||
* Prompts for and deletes a selected theme.
|
||||
* @param themeManager the theme manager
|
||||
*/
|
||||
public static void deleteTheme(ThemeManager themeManager) {
|
||||
List<GTheme> savedThemes = new ArrayList<>(
|
||||
@ -198,7 +201,7 @@ public class ThemeUtils {
|
||||
if (existing == null) {
|
||||
return true;
|
||||
}
|
||||
// if the existing theme is a built-in theme, then we definitely can't save to that name
|
||||
// if the existing theme is a built-in theme, then we definitely can't save to that name
|
||||
if (existing instanceof DiscoverableGTheme) {
|
||||
return false;
|
||||
}
|
||||
@ -239,7 +242,7 @@ public class ThemeUtils {
|
||||
|
||||
private static File getSaveFile(String themeName) {
|
||||
File dir = Application.getUserSettingsDirectory();
|
||||
File themeDir = new File(dir, ThemeFileLoader.THEME_DIR);
|
||||
File themeDir = new File(dir, ThemeManager.THEME_DIR);
|
||||
if (!themeDir.exists()) {
|
||||
themeDir.mkdir();
|
||||
}
|
||||
|
@ -16,34 +16,28 @@
|
||||
package generic.theme;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.io.File;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
|
||||
import com.formdev.flatlaf.FlatDarkLaf;
|
||||
import com.formdev.flatlaf.FlatLightLaf;
|
||||
|
||||
import generic.theme.laf.LookAndFeelManager;
|
||||
import ghidra.framework.Application;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
|
||||
/**
|
||||
* This is the fully functional {@link ThemeManager} that manages themes in a application. To
|
||||
* activate the theme functionality, Applications (or tests) must call
|
||||
* activate the theme functionality, Applications (or tests) must call
|
||||
* {@link ApplicationThemeManager#initialize()}
|
||||
*/
|
||||
public class ApplicationThemeManager extends ThemeManager {
|
||||
private GTheme activeTheme = getDefaultTheme();
|
||||
|
||||
private Set<GTheme> allThemes = null;
|
||||
|
||||
private GThemeValueMap applicationDefaults = new GThemeValueMap();
|
||||
private GThemeValueMap applicationDarkDefaults = new GThemeValueMap();
|
||||
private GThemeValueMap javaDefaults = new GThemeValueMap();
|
||||
private GThemeValueMap systemValues = new GThemeValueMap();
|
||||
|
||||
protected ThemeFileLoader themeFileLoader = new ThemeFileLoader();
|
||||
protected ThemePreferences themePreferences = new ThemePreferences();
|
||||
|
||||
private Map<String, GColorUIResource> gColorMap = new HashMap<>();
|
||||
@ -58,7 +52,8 @@ public class ApplicationThemeManager extends ThemeManager {
|
||||
*/
|
||||
public static void initialize() {
|
||||
if (INSTANCE instanceof ApplicationThemeManager) {
|
||||
Msg.error(ThemeManager.class, "Attempted to initialize theming more than once!");
|
||||
Msg.error(ApplicationThemeManager.class,
|
||||
"Attempted to initialize theming more than once!");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -74,13 +69,13 @@ public class ApplicationThemeManager extends ThemeManager {
|
||||
|
||||
protected void doInitialize() {
|
||||
installFlatLookAndFeels();
|
||||
loadThemeDefaults();
|
||||
loadDefaultThemeValues();
|
||||
setTheme(themePreferences.load());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reloadApplicationDefaults() {
|
||||
loadThemeDefaults();
|
||||
loadDefaultThemeValues();
|
||||
buildCurrentValues();
|
||||
lookAndFeelManager.resetAll(javaDefaults);
|
||||
notifyThemeChanged(new AllValuesChangedThemeEvent(false));
|
||||
@ -183,16 +178,6 @@ public class ApplicationThemeManager extends ThemeManager {
|
||||
return supported;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GTheme getActiveTheme() {
|
||||
return activeTheme;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LafType getLookAndFeelType() {
|
||||
return activeTheme.getLookAndFeelType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GTheme getTheme(String themeName) {
|
||||
Optional<GTheme> first =
|
||||
@ -200,19 +185,6 @@ public class ApplicationThemeManager extends ThemeManager {
|
||||
return first.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GThemeValueMap getThemeValues() {
|
||||
GThemeValueMap map = new GThemeValueMap();
|
||||
map.load(javaDefaults);
|
||||
map.load(systemValues);
|
||||
map.load(applicationDefaults);
|
||||
if (activeTheme.useDarkDefaults()) {
|
||||
map.load(applicationDarkDefaults);
|
||||
}
|
||||
map.load(activeTheme);
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFont(FontValue newValue) {
|
||||
FontValue currentValue = currentValues.getFont(newValue.getId());
|
||||
@ -286,49 +258,14 @@ public class ApplicationThemeManager extends ThemeManager {
|
||||
return gIcon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GThemeValueMap getJavaDefaults() {
|
||||
GThemeValueMap map = new GThemeValueMap();
|
||||
map.load(javaDefaults);
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GThemeValueMap getApplicationDarkDefaults() {
|
||||
GThemeValueMap map = new GThemeValueMap(applicationDefaults);
|
||||
map.load(applicationDarkDefaults);
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GThemeValueMap getApplicationLightDefaults() {
|
||||
GThemeValueMap map = new GThemeValueMap(applicationDefaults);
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link GThemeValueMap} containing all default values for the current theme. It
|
||||
* is a combination of application defined defaults and java {@link LookAndFeel} defaults.
|
||||
* @return the current set of defaults.
|
||||
*/
|
||||
public GThemeValueMap getDefaults() {
|
||||
GThemeValueMap currentDefaults = new GThemeValueMap(javaDefaults);
|
||||
currentDefaults.load(systemValues);
|
||||
currentDefaults.load(applicationDefaults);
|
||||
if (activeTheme.useDarkDefaults()) {
|
||||
currentDefaults.load(applicationDarkDefaults);
|
||||
}
|
||||
return currentDefaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets specially defined system UI values. These values are created by the application as a
|
||||
* convenience for mapping generic concepts to values that differ by Look and Feel. This allows
|
||||
* clients to use 'system' properties without knowing the actual Look and Feel terms.
|
||||
*
|
||||
*
|
||||
* <p>For example, 'system.color.border' defaults to 'controlShadow', but maps to 'nimbusBorder'
|
||||
* in the Nimbus Look and Feel.
|
||||
*
|
||||
*
|
||||
* @param map the map
|
||||
*/
|
||||
public void setSystemDefaults(GThemeValueMap map) {
|
||||
@ -336,7 +273,7 @@ public class ApplicationThemeManager extends ThemeManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the map of Java default UI values. These are the UI values defined by the current Java
|
||||
* Sets the map of Java default UI values. These are the UI values defined by the current Java
|
||||
* Look and Feel.
|
||||
* @param map the default theme values defined by the {@link LookAndFeel}
|
||||
*/
|
||||
@ -347,16 +284,6 @@ public class ApplicationThemeManager extends ThemeManager {
|
||||
GIcon.refreshAll(currentValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUsingAquaUI(ComponentUI UI) {
|
||||
return activeTheme.getLookAndFeelType() == LafType.MAC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUsingNimbusUI() {
|
||||
return activeTheme.getLookAndFeelType() == LafType.NIMBUS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasThemeChanges() {
|
||||
return !changedValuesMap.isEmpty();
|
||||
@ -367,32 +294,14 @@ public class ApplicationThemeManager extends ThemeManager {
|
||||
lookAndFeelManager.registerFont(component, fontId);
|
||||
}
|
||||
|
||||
public boolean isDarkTheme() {
|
||||
return activeTheme.useDarkDefaults();
|
||||
}
|
||||
|
||||
private void installFlatLookAndFeels() {
|
||||
UIManager.installLookAndFeel(LafType.FLAT_LIGHT.getName(), FlatLightLaf.class.getName());
|
||||
UIManager.installLookAndFeel(LafType.FLAT_DARK.getName(), FlatDarkLaf.class.getName());
|
||||
}
|
||||
|
||||
private void loadThemeDefaults() {
|
||||
themeFileLoader.loadThemeDefaultFiles();
|
||||
applicationDefaults = themeFileLoader.getDefaults();
|
||||
applicationDarkDefaults = themeFileLoader.getDarkDefaults();
|
||||
}
|
||||
|
||||
private void buildCurrentValues() {
|
||||
GThemeValueMap map = new GThemeValueMap();
|
||||
|
||||
map.load(javaDefaults);
|
||||
map.load(systemValues);
|
||||
map.load(applicationDefaults);
|
||||
if (activeTheme.useDarkDefaults()) {
|
||||
map.load(applicationDarkDefaults);
|
||||
}
|
||||
map.load(activeTheme);
|
||||
currentValues = map;
|
||||
@Override
|
||||
protected void buildCurrentValues() {
|
||||
super.buildCurrentValues();
|
||||
changedValuesMap.clear();
|
||||
}
|
||||
|
||||
@ -400,11 +309,42 @@ public class ApplicationThemeManager extends ThemeManager {
|
||||
if (allThemes == null) {
|
||||
Set<GTheme> set = new HashSet<>();
|
||||
set.addAll(findDiscoverableThemes());
|
||||
set.addAll(themeFileLoader.loadThemeFiles());
|
||||
set.addAll(loadThemeFiles());
|
||||
allThemes = set;
|
||||
}
|
||||
}
|
||||
|
||||
protected Collection<GTheme> loadThemeFiles() {
|
||||
List<File> fileList = new ArrayList<>();
|
||||
FileFilter themeFileFilter = file -> file.getName().endsWith("." + GTheme.FILE_EXTENSION);
|
||||
|
||||
File dir = Application.getUserSettingsDirectory();
|
||||
File themeDir = new File(dir, THEME_DIR);
|
||||
File[] files = themeDir.listFiles(themeFileFilter);
|
||||
if (files != null) {
|
||||
fileList.addAll(Arrays.asList(files));
|
||||
}
|
||||
|
||||
List<GTheme> list = new ArrayList<>();
|
||||
for (File file : fileList) {
|
||||
GTheme theme = loadTheme(file);
|
||||
if (theme != null) {
|
||||
list.add(theme);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private static GTheme loadTheme(File file) {
|
||||
try {
|
||||
return new ThemeReader(file).readTheme();
|
||||
}
|
||||
catch (IOException e) {
|
||||
Msg.error(Gui.class, "Could not load theme from file: " + file.getAbsolutePath(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Collection<DiscoverableGTheme> findDiscoverableThemes() {
|
||||
return ClassSearcher.getInstances(DiscoverableGTheme.class);
|
||||
}
|
||||
|
@ -24,19 +24,19 @@ import javax.swing.LookAndFeel;
|
||||
* Provides a static set of methods for globally managing application themes and their values.
|
||||
* <P>
|
||||
* The basic idea is that all the colors, fonts, and icons used in an application should be
|
||||
* accessed indirectly via an "id" string. Then the actual color, font, or icon can be changed
|
||||
* accessed indirectly via an "id" string. Then the actual color, font, or icon can be changed
|
||||
* without changing the source code. The default mapping of the id strings to a value is defined
|
||||
* in <name>.theme.properties files which are dynamically discovered by searching the module's
|
||||
* in {name}.theme.properties files which are dynamically discovered by searching the module's
|
||||
* data directory. Also, these files can optionally define a dark default value for an id which
|
||||
* would replace the standard default value in the event that the current theme specifies that it
|
||||
* is a dark theme. Themes are used to specify the application's {@link LookAndFeel}, whether or
|
||||
* not it is dark, and any customized values for colors, fonts, or icons. There are several
|
||||
* not it is dark, and any customized values for colors, fonts, or icons. There are several
|
||||
* "built-in" themes, one for each supported {@link LookAndFeel}, but additional themes can
|
||||
* be defined and stored in the users application home directory as a <name>.theme file.
|
||||
*
|
||||
* be defined and stored in the users application home directory as a {name}.theme file.
|
||||
*
|
||||
*/
|
||||
public class Gui {
|
||||
// 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
|
||||
// called ThemeManager.initialize() which will replace this with a fully initialized version.
|
||||
private static ThemeManager themeManager = new StubThemeManager();
|
||||
|
@ -0,0 +1,50 @@
|
||||
/* ###
|
||||
* 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 ghidra.util.Msg;
|
||||
|
||||
/**
|
||||
* This is a strange implementation of {@link ThemeManager} that is meant to be used in a headless
|
||||
* environment, but also needs theme properties to have been loaded. This is needed by any
|
||||
* application that needs to do theme property validation.
|
||||
*/
|
||||
public class HeadlessThemeManager extends ThemeManager {
|
||||
|
||||
public static void initialize() {
|
||||
if (INSTANCE instanceof HeadlessThemeManager) {
|
||||
Msg.error(HeadlessThemeManager.class,
|
||||
"Attempted to initialize theming more than once!");
|
||||
return;
|
||||
}
|
||||
|
||||
HeadlessThemeManager themeManager = new HeadlessThemeManager();
|
||||
themeManager.doInitialize();
|
||||
}
|
||||
|
||||
public HeadlessThemeManager() {
|
||||
INSTANCE = this;
|
||||
installInGui();
|
||||
}
|
||||
|
||||
private void doInitialize() {
|
||||
loadDefaultThemeValues();
|
||||
|
||||
buildCurrentValues();
|
||||
GColor.refreshAll(currentValues);
|
||||
GIcon.refreshAll(currentValues);
|
||||
}
|
||||
}
|
@ -24,7 +24,7 @@ import java.util.Set;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
|
||||
/**
|
||||
* Version of ThemeManager that is used before an application or test installs a full
|
||||
* Version of ThemeManager that is used before an application or test installs a full
|
||||
* ApplicationThemeManager. Provides enough basic functionality used by the Gui class to
|
||||
* allow simple unit tests to run.
|
||||
*/
|
||||
@ -35,7 +35,7 @@ public class StubThemeManager extends ThemeManager {
|
||||
}
|
||||
|
||||
// palette colors are used statically throughout the application, so having them have values
|
||||
// in the stub will allow unit tests to run withouth initializing theming
|
||||
// in the stub will allow unit tests to run without initializing theming
|
||||
protected void installPaletteColors() {
|
||||
addPalette("nocolor", BLACK);
|
||||
addPalette("black", BLACK);
|
||||
|
@ -15,8 +15,8 @@
|
||||
*/
|
||||
package generic.theme;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import generic.jar.ResourceFile;
|
||||
import ghidra.framework.Application;
|
||||
@ -26,17 +26,20 @@ import ghidra.util.Msg;
|
||||
* Loads all the system theme.property files that contain all the default color, font, and
|
||||
* icon values.
|
||||
*/
|
||||
public class ThemeFileLoader {
|
||||
public static final String THEME_DIR = "themes";
|
||||
public class ThemeDefaultsProvider {
|
||||
|
||||
private GThemeValueMap defaults = new GThemeValueMap();
|
||||
private GThemeValueMap darkDefaults = new GThemeValueMap();
|
||||
|
||||
ThemeDefaultsProvider() {
|
||||
loadThemeDefaultFiles();
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for all the theme.property files and loads them into either the standard
|
||||
* defaults (light) map or the dark defaults map.
|
||||
*/
|
||||
public void loadThemeDefaultFiles() {
|
||||
private void loadThemeDefaultFiles() {
|
||||
defaults.clear();
|
||||
darkDefaults.clear();
|
||||
|
||||
@ -56,28 +59,6 @@ public class ThemeFileLoader {
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<GTheme> loadThemeFiles() {
|
||||
List<File> fileList = new ArrayList<>();
|
||||
FileFilter themeFileFilter = file -> file.getName().endsWith("." + GTheme.FILE_EXTENSION);
|
||||
|
||||
File dir = Application.getUserSettingsDirectory();
|
||||
File themeDir = new File(dir, THEME_DIR);
|
||||
File[] files = themeDir.listFiles(themeFileFilter);
|
||||
if (files != null) {
|
||||
fileList.addAll(Arrays.asList(files));
|
||||
}
|
||||
|
||||
List<GTheme> list = new ArrayList<>();
|
||||
for (File file : fileList) {
|
||||
GTheme theme = loadTheme(file);
|
||||
if (theme != null) {
|
||||
list.add(theme);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the standard defaults {@link GThemeValueMap}
|
||||
* @return the standard defaults {@link GThemeValueMap}
|
||||
@ -93,14 +74,4 @@ public class ThemeFileLoader {
|
||||
public GThemeValueMap getDarkDefaults() {
|
||||
return darkDefaults;
|
||||
}
|
||||
|
||||
private static GTheme loadTheme(File file) {
|
||||
try {
|
||||
return new ThemeReader(file).readTheme();
|
||||
}
|
||||
catch (IOException e) {
|
||||
Msg.error(Gui.class, "Could not load theme from file: " + file.getAbsolutePath(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -33,35 +33,45 @@ import utilities.util.reflection.ReflectionUtilities;
|
||||
|
||||
/**
|
||||
* This class manages application themes and their values. The ThemeManager is an abstract
|
||||
* base class that has two concrete subclasses (and others for testing purposes) -
|
||||
* base class that has two concrete subclasses (and others for testing purposes) -
|
||||
* StubThemeManager and ApplicationThememManager. The StubThemeManager exists as a placeholder
|
||||
* until the ApplicationThemeManager is installed via {@link ApplicationThemeManager#initialize()}.
|
||||
* <P>
|
||||
* The basic idea is that all the colors, fonts, and icons used in an application should be
|
||||
* accessed indirectly via an "id" string. Then the actual color, font, or icon can be changed
|
||||
* accessed indirectly via an "id" string. Then the actual color, font, or icon can be changed
|
||||
* without changing the source code. The default mapping of the id strings to a value is defined
|
||||
* in <name>.theme.properties files which are dynamically discovered by searching the module's
|
||||
* data directory. Also, these files can optionally define a dark default value for an id which
|
||||
* would replace the standard default value in the event that the current theme specifies that it
|
||||
* is a dark theme. Themes are used to specify the application's {@link LookAndFeel}, whether or
|
||||
* not it is dark, and any customized values for colors, fonts, or icons. There are several
|
||||
* not it is dark, and any customized values for colors, fonts, or icons. There are several
|
||||
* "built-in" themes, one for each supported {@link LookAndFeel}, but additional themes can
|
||||
* be defined and stored in the users application home directory as a <name>.theme file.
|
||||
* be defined and stored in the users application home directory as a <name>.theme file.
|
||||
* <P>
|
||||
* Clients that just need to access the colors, fonts, and icons from the theme can use the
|
||||
* convenience methods in the {@link Gui} class. Clients that need to directly manipulate the
|
||||
* Clients that just need to access the colors, fonts, and icons from the theme can use the
|
||||
* convenience methods in the {@link Gui} class. Clients that need to directly manipulate the
|
||||
* themes and values will need to directly use the ThemeManager which and be retrieved using the
|
||||
* static {@link #getInstance()} method.
|
||||
*/
|
||||
|
||||
public abstract class ThemeManager {
|
||||
|
||||
public static final String THEME_DIR = "themes";
|
||||
|
||||
static final Font DEFAULT_FONT = new Font("Dialog", Font.PLAIN, 12);
|
||||
static final Color DEFAULT_COLOR = Color.CYAN;
|
||||
|
||||
protected static ThemeManager INSTANCE;
|
||||
|
||||
protected GTheme activeTheme = getDefaultTheme();
|
||||
|
||||
protected GThemeValueMap javaDefaults = new GThemeValueMap();
|
||||
protected GThemeValueMap systemValues = new GThemeValueMap();
|
||||
protected GThemeValueMap currentValues = new GThemeValueMap();
|
||||
|
||||
protected GThemeValueMap applicationDefaults = new GThemeValueMap();
|
||||
protected GThemeValueMap applicationDarkDefaults = new GThemeValueMap();
|
||||
|
||||
// these notifications are only when the user is manipulating theme values, so rare and at
|
||||
// user speed, so using copy on read
|
||||
private WeakSet<ThemeListener> themeListeners =
|
||||
@ -82,37 +92,66 @@ public abstract class ThemeManager {
|
||||
Gui.setThemeManager(this);
|
||||
}
|
||||
|
||||
protected void loadDefaultThemeValues() {
|
||||
ThemeDefaultsProvider provider = new ThemeDefaultsProvider();
|
||||
applicationDefaults = provider.getDefaults();
|
||||
applicationDarkDefaults = provider.getDarkDefaults();
|
||||
}
|
||||
|
||||
protected void buildCurrentValues() {
|
||||
GThemeValueMap map = new GThemeValueMap();
|
||||
|
||||
map.load(javaDefaults);
|
||||
map.load(systemValues);
|
||||
map.load(applicationDefaults);
|
||||
if (activeTheme.useDarkDefaults()) {
|
||||
map.load(applicationDarkDefaults);
|
||||
}
|
||||
map.load(activeTheme);
|
||||
currentValues = map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads the defaults from all the discoverable theme.property files.
|
||||
*/
|
||||
public abstract void reloadApplicationDefaults();
|
||||
public void reloadApplicationDefaults() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores all the current application back to the values as specified by the active theme.
|
||||
* In other words, reverts any changes to the active theme that haven't been saved.
|
||||
*/
|
||||
public abstract void restoreThemeValues();
|
||||
public void restoreThemeValues() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the current color value for the given color id to the value established by the
|
||||
* current theme.
|
||||
* @param id the color id to restore back to the original theme value
|
||||
*/
|
||||
public abstract void restoreColor(String id);
|
||||
public void restoreColor(String id) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the current font value for the given font id to the value established by the
|
||||
* current theme.
|
||||
* @param id the font id to restore back to the original theme value
|
||||
*/
|
||||
public abstract void restoreFont(String id);
|
||||
public void restoreFont(String id) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the current icon value for the given icon id to the value established by the
|
||||
* current theme.
|
||||
* @param id the icon id to restore back to the original theme value
|
||||
*/
|
||||
public abstract void restoreIcon(String id);
|
||||
public void restoreIcon(String id) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the color associated with the given id has been changed from the current
|
||||
@ -121,7 +160,9 @@ public abstract class ThemeManager {
|
||||
* @return true if the color associated with the given id has been changed from the current
|
||||
* theme value for that id.
|
||||
*/
|
||||
public abstract boolean isChangedColor(String id);
|
||||
public boolean isChangedColor(String id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the font associated with the given id has been changed from the current
|
||||
@ -130,7 +171,9 @@ public abstract class ThemeManager {
|
||||
* @return true if the font associated with the given id has been changed from the current
|
||||
* theme value for that id.
|
||||
*/
|
||||
public abstract boolean isChangedFont(String id);
|
||||
public boolean isChangedFont(String id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the Icon associated with the given id has been changed from the current
|
||||
@ -139,57 +182,75 @@ public abstract class ThemeManager {
|
||||
* @return true if the Icon associated with the given id has been changed from the current
|
||||
* theme value for that id.
|
||||
*/
|
||||
public abstract boolean isChangedIcon(String id);
|
||||
public boolean isChangedIcon(String id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the application's active theme to the given theme.
|
||||
* @param theme the theme to make active
|
||||
*/
|
||||
public abstract void setTheme(GTheme theme);
|
||||
public void setTheme(GTheme theme) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given theme to set of all themes.
|
||||
* @param newTheme the theme to add
|
||||
*/
|
||||
public abstract void addTheme(GTheme newTheme);
|
||||
public void addTheme(GTheme newTheme) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the theme from the set of all themes. Also, if the theme has an associated
|
||||
* file, the file will be deleted.
|
||||
* @param theme the theme to delete
|
||||
*/
|
||||
public abstract void deleteTheme(GTheme theme);
|
||||
public void deleteTheme(GTheme theme) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a set of all known themes.
|
||||
* @return a set of all known themes.
|
||||
*/
|
||||
public abstract Set<GTheme> getAllThemes();
|
||||
public Set<GTheme> getAllThemes() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a set of all known themes that are supported on the current platform.
|
||||
* @return a set of all known themes that are supported on the current platform.
|
||||
*/
|
||||
public abstract Set<GTheme> getSupportedThemes();
|
||||
public Set<GTheme> getSupportedThemes() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the active theme.
|
||||
* @return the active theme.
|
||||
*/
|
||||
public abstract GTheme getActiveTheme();
|
||||
public GTheme getActiveTheme() {
|
||||
return activeTheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link LafType} for the currently active {@link LookAndFeel}
|
||||
* @return the {@link LafType} for the currently active {@link LookAndFeel}
|
||||
*/
|
||||
public abstract LafType getLookAndFeelType();
|
||||
public LafType getLookAndFeelType() {
|
||||
return activeTheme.getLookAndFeelType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the known theme that has the given name.
|
||||
* @param themeName the name of the theme to retrieve
|
||||
* @return the known theme that has the given name
|
||||
*/
|
||||
public abstract GTheme getTheme(String themeName);
|
||||
public GTheme getTheme(String themeName) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link GThemeValueMap} of all current theme values including unsaved changes to the
|
||||
@ -206,7 +267,17 @@ public abstract class ThemeManager {
|
||||
* @return the theme values as defined by the current theme, ignoring any unsaved changes that
|
||||
* are currently applied to the application
|
||||
*/
|
||||
public abstract GThemeValueMap getThemeValues();
|
||||
public GThemeValueMap getThemeValues() {
|
||||
GThemeValueMap map = new GThemeValueMap();
|
||||
map.load(javaDefaults);
|
||||
map.load(systemValues);
|
||||
map.load(applicationDefaults);
|
||||
if (activeTheme.useDarkDefaults()) {
|
||||
map.load(applicationDarkDefaults);
|
||||
}
|
||||
map.load(activeTheme);
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link GThemeValueMap} contains all values that differ from the default
|
||||
@ -277,7 +348,9 @@ public abstract class ThemeManager {
|
||||
* Updates the current value for the font id in the newValue
|
||||
* @param newValue the new {@link FontValue} to install in the current values.
|
||||
*/
|
||||
public abstract void setFont(FontValue newValue);
|
||||
public void setFont(FontValue newValue) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the current color for the given id.
|
||||
@ -303,7 +376,9 @@ public abstract class ThemeManager {
|
||||
* Updates the current value for the color id in the newValue
|
||||
* @param newValue the new {@link ColorValue} to install in the current values.
|
||||
*/
|
||||
public abstract void setColor(ColorValue newValue);
|
||||
public void setColor(ColorValue newValue) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the current {@link Icon} for the given id.
|
||||
@ -318,25 +393,31 @@ public abstract class ThemeManager {
|
||||
* Updates the current value for the {@link Icon} id in the newValue
|
||||
* @param newValue the new {@link IconValue} to install in the current values.
|
||||
*/
|
||||
public abstract void setIcon(IconValue newValue);
|
||||
public void setIcon(IconValue newValue) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* gets a UIResource version of the GColor for the given id. Using this method ensures that
|
||||
* the same instance is used for a given id. This combats some poor code in some of the
|
||||
* the same instance is used for a given id. This combats some poor code in some of the
|
||||
* {@link LookAndFeel}s where the use == in some places to test for equals.
|
||||
* @param id the id to get a GColorUIResource for
|
||||
* @return a GColorUIResource for the given id
|
||||
*/
|
||||
public abstract GColorUIResource getGColorUiResource(String id);
|
||||
public GColorUIResource getGColorUiResource(String id) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* gets a UIResource version of the GIcon for the given id. Using this method ensures that
|
||||
* the same instance is used for a given id. This combats some poor code in some of the
|
||||
* the same instance is used for a given id. This combats some poor code in some of the
|
||||
* {@link LookAndFeel}s where the use == in some places to test for equals.
|
||||
* @param id the id to get a {@link GIconUIResource} for
|
||||
* @return a GIconUIResource for the given id
|
||||
*/
|
||||
public abstract GIconUIResource getGIconUiResource(String id);
|
||||
public GIconUIResource getGIconUiResource(String id) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link GThemeValueMap} containing all the default theme values defined by the
|
||||
@ -344,44 +425,67 @@ public abstract class ThemeManager {
|
||||
* @return the {@link GThemeValueMap} containing all the default theme values defined by the
|
||||
* current {@link LookAndFeel}
|
||||
*/
|
||||
public abstract GThemeValueMap getJavaDefaults();
|
||||
public GThemeValueMap getJavaDefaults() {
|
||||
GThemeValueMap map = new GThemeValueMap();
|
||||
map.load(javaDefaults);
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link GThemeValueMap} containing all the dark default values defined
|
||||
* in theme.properties files. Note that dark defaults includes light defaults that haven't
|
||||
* been overridden by a dark default with the same id.
|
||||
* @return the {@link GThemeValueMap} containing all the dark values defined in
|
||||
* @return the {@link GThemeValueMap} containing all the dark values defined in
|
||||
* theme.properties files
|
||||
*/
|
||||
public abstract GThemeValueMap getApplicationDarkDefaults();
|
||||
public GThemeValueMap getApplicationDarkDefaults() {
|
||||
GThemeValueMap map = new GThemeValueMap(applicationDefaults);
|
||||
map.load(applicationDarkDefaults);
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link GThemeValueMap} containing all the standard default values defined
|
||||
* in theme.properties files.
|
||||
* @return the {@link GThemeValueMap} containing all the standard values defined in
|
||||
* in theme.properties files.
|
||||
* @return the {@link GThemeValueMap} containing all the standard values defined in
|
||||
* theme.properties files
|
||||
*/
|
||||
public abstract GThemeValueMap getApplicationLightDefaults();
|
||||
public GThemeValueMap getApplicationLightDefaults() {
|
||||
GThemeValueMap map = new GThemeValueMap(applicationDefaults);
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link GThemeValueMap} containing all default values for the current theme. It
|
||||
* is a combination of application defined defaults and java {@link LookAndFeel} defaults.
|
||||
* @return the current set of defaults.
|
||||
*/
|
||||
public abstract GThemeValueMap getDefaults();
|
||||
public GThemeValueMap getDefaults() {
|
||||
GThemeValueMap currentDefaults = new GThemeValueMap(javaDefaults);
|
||||
currentDefaults.load(systemValues);
|
||||
currentDefaults.load(applicationDefaults);
|
||||
if (activeTheme.useDarkDefaults()) {
|
||||
currentDefaults.load(applicationDarkDefaults);
|
||||
}
|
||||
return currentDefaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given UI object is using the Aqua Look and Feel.
|
||||
* @param UI the UI to examine.
|
||||
* @return true if the UI is using Aqua
|
||||
*/
|
||||
public abstract boolean isUsingAquaUI(ComponentUI UI);
|
||||
public boolean isUsingAquaUI(ComponentUI UI) {
|
||||
return activeTheme.getLookAndFeelType() == LafType.MAC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if 'Nimbus' is the current Look and Feel
|
||||
* @return true if 'Nimbus' is the current Look and Feel
|
||||
*/
|
||||
public abstract boolean isUsingNimbusUI();
|
||||
public boolean isUsingNimbusUI() {
|
||||
return activeTheme.getLookAndFeelType() == LafType.NIMBUS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link ThemeListener} to be notified of theme changes.
|
||||
@ -400,29 +504,13 @@ public abstract class ThemeManager {
|
||||
themeListeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default theme for the current platform.
|
||||
* @return the default theme for the current platform.
|
||||
*/
|
||||
public static GTheme getDefaultTheme() {
|
||||
OperatingSystem OS = Platform.CURRENT_PLATFORM.getOperatingSystem();
|
||||
switch (OS) {
|
||||
case MAC_OS_X:
|
||||
return new MacTheme();
|
||||
case WINDOWS:
|
||||
return new WindowsTheme();
|
||||
case LINUX:
|
||||
case UNSUPPORTED:
|
||||
default:
|
||||
return new NimbusTheme();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there are any unsaved changes to the current theme.
|
||||
* @return true if there are any unsaved changes to the current theme.
|
||||
*/
|
||||
public abstract boolean hasThemeChanges();
|
||||
public boolean hasThemeChanges() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if an color for the given Id has been defined
|
||||
@ -457,13 +545,35 @@ public abstract class ThemeManager {
|
||||
* @param component the component to set/update the font
|
||||
* @param fontId the id of the font to register with the given component
|
||||
*/
|
||||
public abstract void registerFont(Component component, String fontId);
|
||||
public void registerFont(Component component, String fontId) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current theme use dark default values.
|
||||
* @return true if the current theme use dark default values.
|
||||
*/
|
||||
public abstract boolean isDarkTheme();
|
||||
public boolean isDarkTheme() {
|
||||
return activeTheme.useDarkDefaults();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default theme for the current platform.
|
||||
* @return the default theme for the current platform.
|
||||
*/
|
||||
public static GTheme getDefaultTheme() {
|
||||
OperatingSystem OS = Platform.CURRENT_PLATFORM.getOperatingSystem();
|
||||
switch (OS) {
|
||||
case MAC_OS_X:
|
||||
return new MacTheme();
|
||||
case WINDOWS:
|
||||
return new WindowsTheme();
|
||||
case LINUX:
|
||||
case UNSUPPORTED:
|
||||
default:
|
||||
return new NimbusTheme();
|
||||
}
|
||||
}
|
||||
|
||||
protected void notifyThemeChanged(ThemeEvent event) {
|
||||
for (ThemeListener listener : themeListeners) {
|
||||
@ -474,10 +584,10 @@ public abstract class ThemeManager {
|
||||
protected void error(String message) {
|
||||
Throwable t = ReflectionUtilities.createThrowableWithStackOlderThan();
|
||||
StackTraceElement[] trace = t.getStackTrace();
|
||||
StackTraceElement[] filtered =
|
||||
ReflectionUtilities.filterStackTrace(trace, "java.", "theme.Gui", "theme.ThemeManager",
|
||||
"theme.GColor");
|
||||
StackTraceElement[] filtered = ReflectionUtilities.filterStackTrace(trace, "java.",
|
||||
"theme.Gui", "theme.ThemeManager", "theme.GColor");
|
||||
t.setStackTrace(filtered);
|
||||
Msg.error(this, message, t);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -36,11 +36,11 @@ import ghidra.util.SystemUtilities;
|
||||
*/
|
||||
public abstract class LookAndFeelManager {
|
||||
|
||||
/**
|
||||
* These are color ids (see {@link GColor} used to represent general concepts that
|
||||
/**
|
||||
* These are color ids (see {@link GColor} used to represent general concepts that
|
||||
* application developers can use to get the color for that concept as defined by
|
||||
* a specific {@link LookAndFeel}. This class will define some standard default
|
||||
* mappings in the constructor, but it is expected that each specific LookAndFeelManager
|
||||
* mappings in the constructor, but it is expected that each specific LookAndFeelManager
|
||||
* will override these mappings with values appropriate for that LookAndFeel.
|
||||
*/
|
||||
protected static final String SYSTEM_APP_BACKGROUND_COLOR_ID = "system.color.bg.application";
|
||||
@ -91,6 +91,7 @@ public abstract class LookAndFeelManager {
|
||||
installJavaDefaults();
|
||||
fixupLookAndFeelIssues();
|
||||
installGlobalProperties();
|
||||
installCustomLookAndFeelActions();
|
||||
updateComponentUis();
|
||||
}
|
||||
|
||||
@ -459,7 +460,6 @@ public abstract class LookAndFeelManager {
|
||||
private void installGlobalProperties() {
|
||||
installGlobalLookAndFeelAttributes();
|
||||
installGlobalFontSizeOverride();
|
||||
installCustomLookAndFeelActions();
|
||||
installPopupMenuSettingsOverride();
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ import generic.theme.builtin.*;
|
||||
import resources.ResourceManager;
|
||||
import resources.icons.UrlImageIcon;
|
||||
|
||||
public class ThemeManagerTest {
|
||||
public class ApplicationThemeManagerTest {
|
||||
|
||||
private Font FONT = new Font("Dialog", Font.PLAIN, 13);
|
||||
private Font SMALL_FONT = new Font("Dialog", Font.PLAIN, 4);
|
||||
@ -51,6 +51,8 @@ public class ThemeManagerTest {
|
||||
private GTheme MAC_THEME = new MacTheme();
|
||||
private ThemeManager themeManager;
|
||||
|
||||
private boolean errorsExpected;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
@ -69,7 +71,6 @@ public class ThemeManagerTest {
|
||||
darkDefaultValues.addColor(new ColorValue("color.test.bg", BLACK));
|
||||
darkDefaultValues.addColor(new ColorValue("color.test.fg", BLUE));
|
||||
themeManager = new DummyApplicationThemeManager();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -264,16 +265,19 @@ public class ThemeManagerTest {
|
||||
|
||||
@Test
|
||||
public void testGetColorWithUnresolvedId() {
|
||||
errorsExpected = true;
|
||||
assertEquals(CYAN, themeManager.getColor("color.badid"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIconWithUnresolvedId() {
|
||||
errorsExpected = true;
|
||||
assertEquals(ResourceManager.getDefaultIcon(), themeManager.getIcon("icon.badid"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetFontWithUnresolvedId() {
|
||||
errorsExpected = true;
|
||||
assertEquals(ThemeManager.DEFAULT_FONT, themeManager.getFont("font.badid"));
|
||||
}
|
||||
|
||||
@ -337,7 +341,7 @@ public class ThemeManagerTest {
|
||||
}
|
||||
|
||||
// ApplicationThemeManager that doesn't read in theme.properties files or preferences
|
||||
class DummyApplicationThemeManager extends ApplicationThemeManager {
|
||||
private class DummyApplicationThemeManager extends ApplicationThemeManager {
|
||||
DummyApplicationThemeManager() {
|
||||
themePreferences = new ThemePreferences() {
|
||||
@Override
|
||||
@ -350,28 +354,25 @@ public class ThemeManagerTest {
|
||||
// do nothing
|
||||
}
|
||||
};
|
||||
themeFileLoader = new ThemeFileLoader() {
|
||||
@Override
|
||||
public void loadThemeDefaultFiles() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<GTheme> loadThemeFiles() {
|
||||
return new HashSet<>(themes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GThemeValueMap getDefaults() {
|
||||
return defaultValues;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GThemeValueMap getDarkDefaults() {
|
||||
return darkDefaultValues;
|
||||
}
|
||||
};
|
||||
doInitialize();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadDefaultThemeValues() {
|
||||
this.applicationDefaults = defaultValues;
|
||||
this.applicationDarkDefaults = darkDefaultValues;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<GTheme> loadThemeFiles() {
|
||||
return new HashSet<>(themes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void error(String message) {
|
||||
if (!errorsExpected) {
|
||||
super.error(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@ import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
|
||||
import generic.application.GenericApplicationLayout;
|
||||
import generic.theme.ApplicationThemeManager;
|
||||
import generic.theme.HeadlessThemeManager;
|
||||
import ghidra.framework.Application;
|
||||
import ghidra.framework.ApplicationConfiguration;
|
||||
import help.validator.*;
|
||||
@ -70,12 +70,11 @@ public class GHelpBuilder {
|
||||
ApplicationConfiguration config = new ApplicationConfiguration() {
|
||||
@Override
|
||||
protected void initializeApplication() {
|
||||
ApplicationThemeManager.initialize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHeadless() {
|
||||
return false;
|
||||
//
|
||||
// We must be headless, as we are utility class. But, we also need theme properties
|
||||
// to be loaded and correct for the help system to function properly.
|
||||
//
|
||||
HeadlessThemeManager.initialize();
|
||||
}
|
||||
};
|
||||
Application.initializeApplication(new GenericApplicationLayout("Help Builder", "0.1"),
|
||||
|
Loading…
Reference in New Issue
Block a user