mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-25 07:26:31 +08:00
GP-1981 Refactored Gui to use ThemeManager
This commit is contained in:
@@ -212,10 +212,10 @@ public interface AutoOptions {
|
||||
else {
|
||||
options.registerOption(key.getName(), type, defaultValue, help, description,
|
||||
editor);
|
||||
// TODO: Wish Ghidra would do this upon any option registration
|
||||
options.putObject(key.getName(), defaultValue, type);
|
||||
}
|
||||
|
||||
// TODO: Wish Ghidra would do this upon any option registration
|
||||
options.putObject(key.getName(), defaultValue, type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,8 @@ color.fg.plugin.comments.history.text = blue
|
||||
color.fg.plugin.comments.history.user = color.fg
|
||||
color.fg.plugin.comments.history.date = rgb(124, 37, 18)
|
||||
|
||||
color.bg.plugin.programtree = color.bg
|
||||
|
||||
color.bg.plugin.datamgr.edge.default = blue
|
||||
color.bg.plugin.datamgr.edge.composite = magenta
|
||||
color.bg.plugin.datamgr.edge.reference = blue
|
||||
|
||||
@@ -37,6 +37,6 @@
|
||||
|
||||
icon.fsbrowser.file.substring.release. = images/famfamfam_silk_icons_v013/bullet_purple.png
|
||||
|
||||
icon.fsbrowser.file.overlay.imported = images/checkmark_green.gif
|
||||
icon.fsbrowser.file.overlay.filesystem = EMPTY_ICON{images/nuvola/16x16/ledgreen.png[size(8,8)][move(8,8)]} // lower right quadrant
|
||||
icon.fsbrowser.file.overlay.imported = EMPTY_ICON{images/checkmark_green.gif[size(8,8)][move(8,8)]} // lower right quadrant
|
||||
icon.fsbrowser.file.overlay.filesystem = EMPTY_ICON{images/nuvola/16x16/ledgreen.png[size(8,8)][move(0,8)]} // lower left quadrant
|
||||
icon.fsbrowser.file.overlay.missing.password = EMPTY_ICON{images/lock.png[size(8,8)][move(8,0)]} // upper right quadrant
|
||||
@@ -38,7 +38,6 @@ import ghidra.program.database.ProgramDB;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.exception.UsrException;
|
||||
import ghidra.util.task.TaskLauncher;
|
||||
import ghidra.util.task.TaskMonitorAdapter;
|
||||
|
||||
/**
|
||||
* Main Ghidra application class. Creates
|
||||
@@ -73,7 +72,6 @@ public class GhidraRun implements GhidraLaunchable {
|
||||
Runnable mainTask = () -> {
|
||||
|
||||
GhidraApplicationConfiguration configuration = new GhidraApplicationConfiguration();
|
||||
configuration.setTaskMonitor(new StatusReportingTaskMonitor());
|
||||
Application.initializeApplication(layout, configuration);
|
||||
|
||||
log = LogManager.getLogger(GhidraRun.class);
|
||||
@@ -243,15 +241,3 @@ public class GhidraRun implements GhidraLaunchable {
|
||||
// this exists just to allow access to the constructor
|
||||
}
|
||||
}
|
||||
|
||||
class StatusReportingTaskMonitor extends TaskMonitorAdapter {
|
||||
@Override
|
||||
public synchronized void setCancelEnabled(boolean enable) {
|
||||
// Not permitted
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMessage(String message) {
|
||||
SplashScreen.updateSplashScreenStatus(message);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -33,8 +33,7 @@ import docking.actions.KeyBindingUtils;
|
||||
import docking.options.editor.FontEditor;
|
||||
import docking.widgets.OptionDialog;
|
||||
import docking.widgets.filechooser.GhidraFileChooser;
|
||||
import generic.theme.GIcon;
|
||||
import generic.theme.Gui;
|
||||
import generic.theme.*;
|
||||
import ghidra.framework.plugintool.ComponentProviderAdapter;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.Msg;
|
||||
@@ -274,7 +273,7 @@ public class TextEditorComponentProvider extends ComponentProviderAdapter {
|
||||
FontEditor editor = new FontEditor();
|
||||
editor.setValue(Gui.getFont(FONT_ID));
|
||||
editor.showDialog();
|
||||
Gui.setFont(FONT_ID, (Font) editor.getValue());
|
||||
ThemeManager.getInstance().setFont(FONT_ID, (Font) editor.getValue());
|
||||
}
|
||||
|
||||
private void save() {
|
||||
|
||||
+4
-2
@@ -34,6 +34,8 @@ import resources.ResourceManager;
|
||||
* Cell renderer for the drag and drop tree.
|
||||
*/
|
||||
class DnDTreeCellRenderer extends DefaultTreeCellRenderer {
|
||||
private static final Color BACKGROUND_UNSELECTED = new GColor("color.bg.tree");
|
||||
private static final Color BACKGROUND_SELECTED = new GColor("color.bg.tree.selected");
|
||||
|
||||
private static final String DISABLED_DOCS = "DisabledDocument.gif";
|
||||
private static final String DISABLED_FRAGMENT = "DisabledFragment";
|
||||
@@ -73,8 +75,8 @@ class DnDTreeCellRenderer extends DefaultTreeCellRenderer {
|
||||
*/
|
||||
DnDTreeCellRenderer() {
|
||||
super();
|
||||
defaultNonSelectionColor = new GColor("Tree.textBackground");
|
||||
defaultSelectionColor = new GColor("Tree.selectionBackground");
|
||||
defaultNonSelectionColor = BACKGROUND_UNSELECTED;
|
||||
defaultSelectionColor = BACKGROUND_SELECTED;
|
||||
rowForFeedback = -1;
|
||||
|
||||
// disable HTML rendering
|
||||
|
||||
+1
@@ -70,6 +70,7 @@ public abstract class DragNDropTree extends JTree implements Draggable, Droppabl
|
||||
|
||||
public DragNDropTree(DefaultTreeModel model) {
|
||||
super(model);
|
||||
setBackground(new GColor("color.bg.tree"));
|
||||
treeModel = model;
|
||||
this.root = (ProgramNode) model.getRoot();
|
||||
//setEditable(true); // edit interferes with drag gesture listener
|
||||
|
||||
+3
-2
@@ -315,8 +315,9 @@ public class ProgramDnDTree extends DragNDropTree {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
Object data = e.getTransferable().getTransferData(
|
||||
SelectionTransferable.localProgramSelectionFlavor);
|
||||
Object data = e.getTransferable()
|
||||
.getTransferData(
|
||||
SelectionTransferable.localProgramSelectionFlavor);
|
||||
SelectionTransferData transferData = (SelectionTransferData) data;
|
||||
return program.getDomainFile().getPathname().equals(transferData.getProgramPath());
|
||||
}
|
||||
|
||||
+2
-3
@@ -31,9 +31,8 @@ import docking.actions.KeyBindingUtils;
|
||||
import docking.options.editor.FontEditor;
|
||||
import docking.widgets.OptionDialog;
|
||||
import generic.jar.ResourceFile;
|
||||
import generic.theme.GIcon;
|
||||
import generic.theme.*;
|
||||
import generic.theme.GThemeDefaults.Colors;
|
||||
import generic.theme.Gui;
|
||||
import ghidra.app.script.GhidraScriptUtil;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.datastruct.FixedSizeStack;
|
||||
@@ -508,7 +507,7 @@ public class GhidraScriptEditorComponentProvider extends ComponentProvider {
|
||||
FontEditor editor = new FontEditor();
|
||||
editor.setValue(Gui.getFont(FONT_ID));
|
||||
editor.showDialog();
|
||||
Gui.setFont(FONT_ID, (Font) editor.getValue());
|
||||
ThemeManager.getInstance().setFont(FONT_ID, (Font) editor.getValue());
|
||||
}
|
||||
|
||||
private void save() {
|
||||
|
||||
+17
-2
@@ -20,7 +20,7 @@ import docking.DockingWindowManager;
|
||||
import docking.framework.ApplicationInformationDisplayFactory;
|
||||
import docking.framework.SplashScreen;
|
||||
import docking.widgets.PopupKeyStorePasswordProvider;
|
||||
import generic.theme.Gui;
|
||||
import generic.theme.ApplicationThemeManager;
|
||||
import ghidra.docking.util.LookAndFeelUtils;
|
||||
import ghidra.formats.gfilesystem.crypto.CryptoProviders;
|
||||
import ghidra.formats.gfilesystem.crypto.PopupGUIPasswordProvider;
|
||||
@@ -30,6 +30,7 @@ import ghidra.framework.preferences.Preferences;
|
||||
import ghidra.net.ApplicationKeyManagerFactory;
|
||||
import ghidra.util.ErrorDisplay;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.util.task.TaskMonitorAdapter;
|
||||
|
||||
public class GhidraApplicationConfiguration extends HeadlessGhidraApplicationConfiguration {
|
||||
|
||||
@@ -43,12 +44,13 @@ public class GhidraApplicationConfiguration extends HeadlessGhidraApplicationCon
|
||||
|
||||
@Override
|
||||
protected void initializeApplication() {
|
||||
Gui.initialize();
|
||||
ApplicationThemeManager.initialize();
|
||||
LookAndFeelUtils.performPlatformSpecificFixups();
|
||||
|
||||
if (showSplashScreen) {
|
||||
showUserAgreement();
|
||||
SplashScreen.showSplashScreen();
|
||||
this.monitor = new StatusReportingTaskMonitor();
|
||||
}
|
||||
|
||||
super.initializeApplication();
|
||||
@@ -89,4 +91,17 @@ public class GhidraApplicationConfiguration extends HeadlessGhidraApplicationCon
|
||||
public ErrorDisplay getErrorDisplay() {
|
||||
return new DockingErrorDisplay();
|
||||
}
|
||||
|
||||
private static class StatusReportingTaskMonitor extends TaskMonitorAdapter {
|
||||
@Override
|
||||
public synchronized void setCancelEnabled(boolean enable) {
|
||||
// Not permitted
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMessage(String message) {
|
||||
SplashScreen.updateSplashScreenStatus(message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ public class FileIconService {
|
||||
}
|
||||
|
||||
private void createSubstringMap() {
|
||||
GThemeValueMap values = Gui.getAllValues();
|
||||
GThemeValueMap values = ThemeManager.getInstance().getCurrentValues();
|
||||
List<IconValue> icons = values.getIcons();
|
||||
for (IconValue iconValue : icons) {
|
||||
String id = iconValue.getId();
|
||||
|
||||
@@ -32,7 +32,7 @@ import org.junit.*;
|
||||
import docking.test.AbstractDockingTest;
|
||||
import generic.theme.GColor;
|
||||
import generic.theme.GThemeDefaults.Colors.Palette;
|
||||
import generic.theme.Gui;
|
||||
import generic.theme.ThemeManager;
|
||||
import ghidra.framework.options.*;
|
||||
import ghidra.framework.options.OptionsTest.FRUIT;
|
||||
import ghidra.program.database.ProgramBuilder;
|
||||
@@ -61,7 +61,7 @@ public class OptionsDBTest extends AbstractDockingTest {
|
||||
ProgramDB program = builder.getProgram();
|
||||
txID = program.startTransaction("Test");
|
||||
options = new OptionsDB(program);
|
||||
Gui.setColor("color.test", Palette.MAGENTA);
|
||||
ThemeManager.getInstance().setColor("color.test", Palette.MAGENTA);
|
||||
testColor = new GColor("color.test");
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ public class TokenHighlightColors {
|
||||
float h = (float) Math.random(); // 0-360
|
||||
float s = .25f; // saturation; gray to full color; full color is too harsh for highlights
|
||||
float b = 1f; // brightness; black to full color
|
||||
if (Gui.getActiveTheme().useDarkDefaults()) {
|
||||
if (Gui.isDarkTheme()) {
|
||||
s = .5f; // a bit more color against a dark background
|
||||
b = .5f; // less brightness, as the background is not as bright
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ src/main/resources/images/page_go.png||FAMFAMFAM Icons - CC 2.5||||END|
|
||||
src/main/resources/images/page_green.png||FAMFAMFAM Icons - CC 2.5||||END|
|
||||
src/main/resources/images/play.png||GHIDRA||||END|
|
||||
src/main/resources/images/preferences-system-windows.png||Tango Icons - Public Domain||||END|
|
||||
src/main/resources/images/redo.png||GHIDRA||||END|
|
||||
src/main/resources/images/redo.png||Crystal Clear Icons - LGPL 2.1||||END|
|
||||
src/main/resources/images/software-update-available.png||Tango Icons - Public Domain|||tango icon set|END|
|
||||
src/main/resources/images/table.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
|
||||
src/main/resources/images/tag.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
|
||||
@@ -100,7 +100,7 @@ src/main/resources/images/text_lowercase.png||FAMFAMFAM Icons - CC 2.5|||famfamf
|
||||
src/main/resources/images/textfield_rename.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
|
||||
src/main/resources/images/tip.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END|
|
||||
src/main/resources/images/trash-empty.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END|
|
||||
src/main/resources/images/undo.png||GHIDRA||||END|
|
||||
src/main/resources/images/undo.png||Crystal Clear Icons - LGPL 2.1||||END|
|
||||
src/main/resources/images/user-home.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END|
|
||||
src/main/resources/images/view-filter.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END|
|
||||
src/main/resources/images/warning.help.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END|
|
||||
|
||||
@@ -82,12 +82,16 @@ color.border.provider.disconnected = orange
|
||||
|
||||
color.bg.filechooser = color.bg
|
||||
color.fg.filechooser = color.fg
|
||||
color.bg.filechooser.shortcut = lightGray
|
||||
|
||||
color.bg.fieldpanel = color.bg
|
||||
color.fg.fieldpanel = color.fg
|
||||
color.bg.fieldpanel.selection = color.bg.selection
|
||||
color.bg.fieldpanel.highlight = color.bg.highlight
|
||||
color.bg.fieldpanel.selection.and.highlight = green
|
||||
|
||||
color.bg.tree = [color]Tree.textBackground
|
||||
color.bg.tree.selected = [color]Tree.selectionBackground
|
||||
// docking buttons
|
||||
color.fg.button = black
|
||||
|
||||
@@ -239,3 +243,10 @@ color.bg.tableheader.gradient.end.primary = darkBlue
|
||||
|
||||
// docking buttons
|
||||
color.fg.button = darkGray
|
||||
|
||||
color.bg.filechooser.shortcut = system.color.bg.widget
|
||||
|
||||
color.bg.tree = color.bg
|
||||
color.bg.tree.selected = [color]Tree.selectionBackground
|
||||
icon.undo = eatbits1.png
|
||||
icon.redo = eatbits2.png
|
||||
|
||||
@@ -23,6 +23,7 @@ import javax.swing.*;
|
||||
|
||||
import docking.action.*;
|
||||
import generic.theme.Gui;
|
||||
import generic.theme.ThemeManager;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import help.HelpDescriptor;
|
||||
@@ -801,7 +802,7 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
|
||||
else {
|
||||
size = Math.max(size - 1, 3);
|
||||
}
|
||||
Gui.setFont(registeredFontId, font.deriveFont((float) size));
|
||||
ThemeManager.getInstance().setFont(registeredFontId, font.deriveFont((float) size));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,7 +38,7 @@ import docking.widgets.list.GListCellRenderer;
|
||||
import docking.widgets.table.GTableCellRenderer;
|
||||
import docking.widgets.tree.support.GTreeRenderer;
|
||||
import generic.theme.GThemeDefaults.Colors.Palette;
|
||||
import generic.theme.Gui;
|
||||
import ghidra.docking.util.LookAndFeelUtils;
|
||||
import ghidra.util.HTMLUtilities;
|
||||
import resources.ResourceManager;
|
||||
|
||||
@@ -126,7 +126,7 @@ public class DockingUtils {
|
||||
public static JSeparator createToolbarSeparator() {
|
||||
Dimension sepDim = new Dimension(2, ICON_SIZE + 2);
|
||||
JSeparator separator = new JSeparator(SwingConstants.VERTICAL);
|
||||
if (Gui.isUsingAquaUI(separator.getUI())) {
|
||||
if (LookAndFeelUtils.isUsingAquaUI(separator.getUI())) {
|
||||
separator.setUI(new BasicSeparatorUI());
|
||||
}
|
||||
separator.setPreferredSize(sepDim); // ugly work around to force height of separator
|
||||
|
||||
@@ -312,7 +312,7 @@ public class StatusBar extends JPanel {
|
||||
|
||||
int value = 0;
|
||||
int delta = 16;
|
||||
if (Gui.getActiveTheme().useDarkDefaults()) {
|
||||
if (Gui.isDarkTheme()) {
|
||||
value = 128;
|
||||
delta = -16;
|
||||
}
|
||||
|
||||
+7
-7
@@ -32,9 +32,9 @@ import ghidra.util.Msg;
|
||||
|
||||
public class ApplicationInformationDisplayFactory {
|
||||
|
||||
private static final GIcon ICON_HOME = new GIcon("icon.docking.application.home");
|
||||
private static final GIcon ICON_16 = new GIcon("icon.docking.application.16");
|
||||
private static final GIcon ICON_128 = new GIcon("icon.base.application.128");
|
||||
private static final String ICON_HOME = "icon.docking.application.home";
|
||||
private static final String ICON_16 = "icon.docking.application.16";
|
||||
private static final String ICON_128 = "icon.docking.application.128";
|
||||
|
||||
static {
|
||||
PluggableServiceRegistry.registerPluggableService(
|
||||
@@ -144,13 +144,13 @@ public class ApplicationInformationDisplayFactory {
|
||||
}
|
||||
|
||||
protected Icon getSplashScreenIcon128() {
|
||||
return ICON_128;
|
||||
return new GIcon(ICON_128);
|
||||
}
|
||||
|
||||
protected List<Image> doGetWindowIcons() {
|
||||
List<Image> list = new ArrayList<>();
|
||||
list.add(ICON_128.getImageIcon().getImage());
|
||||
list.add(ICON_16.getImageIcon().getImage());
|
||||
list.add(new GIcon(ICON_128).getImageIcon().getImage());
|
||||
list.add(new GIcon(ICON_16).getImageIcon().getImage());
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ public class ApplicationInformationDisplayFactory {
|
||||
}
|
||||
|
||||
protected Icon doGetHomeIcon() {
|
||||
return ICON_HOME;
|
||||
return new GIcon(ICON_HOME);
|
||||
}
|
||||
|
||||
protected Runnable doGetHomeCallback() {
|
||||
|
||||
+2
-2
@@ -17,7 +17,7 @@ package docking.framework;
|
||||
|
||||
import docking.DockingErrorDisplay;
|
||||
import docking.widgets.PopupKeyStorePasswordProvider;
|
||||
import generic.theme.Gui;
|
||||
import generic.theme.ApplicationThemeManager;
|
||||
import ghidra.docking.util.LookAndFeelUtils;
|
||||
import ghidra.framework.ApplicationConfiguration;
|
||||
import ghidra.net.ApplicationKeyManagerFactory;
|
||||
@@ -49,7 +49,7 @@ public class DockingApplicationConfiguration extends ApplicationConfiguration {
|
||||
protected void initializeApplication() {
|
||||
super.initializeApplication();
|
||||
|
||||
Gui.initialize();
|
||||
ApplicationThemeManager.initialize();
|
||||
LookAndFeelUtils.performPlatformSpecificFixups();
|
||||
|
||||
if (showSplashScreen) {
|
||||
|
||||
@@ -24,7 +24,7 @@ import javax.swing.KeyStroke;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import docking.action.DockingActionIf;
|
||||
import generic.theme.Gui;
|
||||
import ghidra.docking.util.LookAndFeelUtils;
|
||||
import ghidra.util.StringUtilities;
|
||||
|
||||
class DockingToolBarUtils {
|
||||
@@ -96,7 +96,7 @@ class DockingToolBarUtils {
|
||||
builder.append(InputEvent.getModifiersExText(modifiers));
|
||||
|
||||
// The Aqua LaF does not use the '+' symbol between modifiers
|
||||
if (!Gui.isUsingAquaUI(button.getUI())) {
|
||||
if (!LookAndFeelUtils.isUsingAquaUI(button.getUI())) {
|
||||
builder.append('+');
|
||||
}
|
||||
}
|
||||
|
||||
+10
@@ -97,6 +97,16 @@ public class MultipleActionDockingToolbarButton extends EmptyBorderButton {
|
||||
popupContext = createPopupContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateUI() {
|
||||
|
||||
removeMouseListener(popupListener);
|
||||
|
||||
super.updateUI();
|
||||
|
||||
installMouseListeners();
|
||||
}
|
||||
|
||||
private void installMouseListeners() {
|
||||
MouseListener[] mouseListeners = getMouseListeners();
|
||||
for (MouseListener mouseListener : mouseListeners) {
|
||||
|
||||
@@ -43,9 +43,11 @@ public class ExportThemeDialog extends DialogComponentProvider {
|
||||
private JTextField fileTextField;
|
||||
private GCheckBox includeDefaultsCheckbox;
|
||||
private boolean exportAsZip;
|
||||
private ThemeManager themeManager;
|
||||
|
||||
public ExportThemeDialog(boolean exportAsZip) {
|
||||
public ExportThemeDialog(ThemeManager themeManager, boolean exportAsZip) {
|
||||
super("Export Theme");
|
||||
this.themeManager = themeManager;
|
||||
this.exportAsZip = exportAsZip;
|
||||
addWorkPanel(buildMainPanel());
|
||||
addOKButton();
|
||||
@@ -62,7 +64,7 @@ public class ExportThemeDialog extends DialogComponentProvider {
|
||||
|
||||
private boolean exportTheme() {
|
||||
String themeName = nameField.getText();
|
||||
GTheme activeTheme = Gui.getActiveTheme();
|
||||
GTheme activeTheme = themeManager.getActiveTheme();
|
||||
LafType laf = activeTheme.getLookAndFeelType();
|
||||
boolean useDarkDefaults = activeTheme.useDarkDefaults();
|
||||
File file = new File(fileTextField.getText());
|
||||
@@ -87,10 +89,10 @@ public class ExportThemeDialog extends DialogComponentProvider {
|
||||
|
||||
private void loadValues(GTheme exportTheme) {
|
||||
if (includeDefaultsCheckbox.isSelected()) {
|
||||
exportTheme.load(Gui.getAllValues());
|
||||
exportTheme.load(themeManager.getCurrentValues());
|
||||
}
|
||||
else {
|
||||
exportTheme.load(Gui.getNonDefaultValues());
|
||||
exportTheme.load(themeManager.getNonDefaultValues());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +116,7 @@ public class ExportThemeDialog extends DialogComponentProvider {
|
||||
|
||||
private Component buildNameField() {
|
||||
nameField = new JTextField(25);
|
||||
nameField.setText(Gui.getActiveTheme().getName());
|
||||
nameField.setText(themeManager.getActiveTheme().getName());
|
||||
return nameField;
|
||||
}
|
||||
|
||||
@@ -127,7 +129,7 @@ public class ExportThemeDialog extends DialogComponentProvider {
|
||||
private Component buildFilePanel() {
|
||||
File homeDir = new File(System.getProperty("user.home")); // prefer the home directory
|
||||
|
||||
String name = Gui.getActiveTheme().getName();
|
||||
String name = themeManager.getActiveTheme().getName();
|
||||
String filename = name.replaceAll(" ", "_") + ".";
|
||||
filename += exportAsZip ? GTheme.ZIP_FILE_EXTENSION : GTheme.FILE_EXTENSION;
|
||||
File file = new File(homeDir, filename);
|
||||
|
||||
@@ -37,7 +37,7 @@ public class IconValueEditor extends ThemeValueEditor<Icon> {
|
||||
|
||||
@Override
|
||||
protected Icon getRawValue(String id) {
|
||||
return Gui.getIcon(id, true);
|
||||
return Gui.getIcon(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -29,7 +29,7 @@ import docking.action.ActionContextProvider;
|
||||
import docking.widgets.table.GFilterTable;
|
||||
import docking.widgets.table.GTable;
|
||||
import generic.theme.ColorValue;
|
||||
import generic.theme.Gui;
|
||||
import generic.theme.ThemeManager;
|
||||
import ghidra.util.Swing;
|
||||
|
||||
/**
|
||||
@@ -41,10 +41,12 @@ public class ThemeColorTable extends JPanel implements ActionContextProvider {
|
||||
private ColorValueEditor colorEditor = new ColorValueEditor(this::colorValueChanged);
|
||||
private GTable table;
|
||||
private GFilterTable<ColorValue> filterTable;
|
||||
private ThemeManager themeManager;
|
||||
|
||||
public ThemeColorTable() {
|
||||
public ThemeColorTable(ThemeManager themeManager) {
|
||||
super(new BorderLayout());
|
||||
colorTableModel = new ThemeColorTableModel();
|
||||
this.themeManager = themeManager;
|
||||
colorTableModel = new ThemeColorTableModel(themeManager);
|
||||
|
||||
filterTable = new GFilterTable<>(colorTableModel);
|
||||
table = filterTable.getTable();
|
||||
@@ -87,7 +89,7 @@ public class ThemeColorTable extends JPanel implements ActionContextProvider {
|
||||
// run later - don't rock the boat in the middle of a listener callback
|
||||
Swing.runLater(() -> {
|
||||
ColorValue newValue = (ColorValue) event.getNewValue();
|
||||
Gui.setColor(newValue);
|
||||
themeManager.setColor(newValue);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+14
-12
@@ -43,9 +43,11 @@ public class ThemeColorTableModel extends GDynamicColumnTableModel<ColorValue, O
|
||||
private GThemeValueMap defaultValues;
|
||||
private GThemeValueMap lightDefaultValues;
|
||||
private GThemeValueMap darkDefaultValues;
|
||||
private ThemeManager themeManager;
|
||||
|
||||
public ThemeColorTableModel() {
|
||||
public ThemeColorTableModel(ThemeManager themeManager) {
|
||||
super(new ServiceProviderStub());
|
||||
this.themeManager = themeManager;
|
||||
load();
|
||||
}
|
||||
|
||||
@@ -53,7 +55,7 @@ public class ThemeColorTableModel extends GDynamicColumnTableModel<ColorValue, O
|
||||
* Reloads the just the current values shown in the table. Called whenever a color changes.
|
||||
*/
|
||||
public void reloadCurrent() {
|
||||
currentValues = Gui.getAllValues();
|
||||
currentValues = themeManager.getCurrentValues();
|
||||
colors = currentValues.getColors();
|
||||
fireTableDataChanged();
|
||||
}
|
||||
@@ -67,20 +69,17 @@ public class ThemeColorTableModel extends GDynamicColumnTableModel<ColorValue, O
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the original value for the current theme
|
||||
*/
|
||||
public ColorValue getThemeValue(String id) {
|
||||
ColorValue getThemeValue(String id) {
|
||||
return themeValues.getColor(id);
|
||||
}
|
||||
|
||||
private void load() {
|
||||
currentValues = Gui.getAllValues();
|
||||
currentValues = themeManager.getCurrentValues();
|
||||
colors = currentValues.getColors();
|
||||
themeValues = Gui.getThemeValues();
|
||||
defaultValues = Gui.getDefaults();
|
||||
lightDefaultValues = Gui.getApplicationLightDefaults();
|
||||
darkDefaultValues = Gui.getApplicationDarkDefaults();
|
||||
themeValues = themeManager.getThemeValues();
|
||||
defaultValues = themeManager.getDefaults();
|
||||
lightDefaultValues = themeManager.getApplicationLightDefaults();
|
||||
darkDefaultValues = themeManager.getApplicationDarkDefaults();
|
||||
|
||||
}
|
||||
|
||||
@@ -155,7 +154,10 @@ public class ThemeColorTableModel extends GDynamicColumnTableModel<ColorValue, O
|
||||
if (colorValue == null) {
|
||||
return null;
|
||||
}
|
||||
Color color = colorValue.get(valueMap);
|
||||
Color color = colorValue.hasResolvableValue(valueMap) ? colorValue.get(valueMap) : null;
|
||||
if (color == null) {
|
||||
return null;
|
||||
}
|
||||
return new ResolvedColor(id, colorValue.getReferenceId(), color);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,8 +49,11 @@ public class ThemeDialog extends DialogComponentProvider {
|
||||
private ThemeFontTable fontTable;
|
||||
private ThemeIconTable iconTable;
|
||||
|
||||
public ThemeDialog() {
|
||||
private ThemeManager themeManager;
|
||||
|
||||
public ThemeDialog(ThemeManager themeManager) {
|
||||
super("Theme Dialog", false);
|
||||
this.themeManager = themeManager;
|
||||
addWorkPanel(createMainPanel());
|
||||
|
||||
addDismissButton();
|
||||
@@ -79,7 +82,7 @@ public class ThemeDialog extends DialogComponentProvider {
|
||||
.enabledWhen(c -> c.isChanged())
|
||||
.popupWhen(c -> true)
|
||||
.helpLocation(new HelpLocation("Theming", "Restore_Value"))
|
||||
.onAction(c -> c.getThemeValue().installValue())
|
||||
.onAction(c -> c.getThemeValue().installValue(themeManager))
|
||||
.build();
|
||||
addAction(resetValueAction);
|
||||
}
|
||||
@@ -93,44 +96,44 @@ public class ThemeDialog extends DialogComponentProvider {
|
||||
}
|
||||
|
||||
private boolean handleChanges() {
|
||||
if (Gui.hasThemeChanges()) {
|
||||
if (themeManager.hasThemeChanges()) {
|
||||
int result = OptionDialog.showYesNoCancelDialog(null, "Close Theme Dialog",
|
||||
"You have changed the theme.\n Do you want save your changes?");
|
||||
if (result == OptionDialog.CANCEL_OPTION) {
|
||||
return false;
|
||||
}
|
||||
if (result == OptionDialog.YES_OPTION) {
|
||||
return ThemeUtils.saveThemeChanges();
|
||||
return ThemeUtils.saveThemeChanges(themeManager);
|
||||
}
|
||||
Gui.restoreThemeValues();
|
||||
themeManager.restoreThemeValues();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void saveCallback() {
|
||||
ThemeUtils.saveThemeChanges();
|
||||
ThemeUtils.saveThemeChanges(themeManager);
|
||||
}
|
||||
|
||||
private void restoreCallback() {
|
||||
if (Gui.hasThemeChanges()) {
|
||||
if (themeManager.hasThemeChanges()) {
|
||||
int result = OptionDialog.showYesNoDialog(null, "Restore Theme Values",
|
||||
"Are you sure you want to discard all your changes?");
|
||||
if (result == OptionDialog.NO_OPTION) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
Gui.restoreThemeValues();
|
||||
themeManager.restoreThemeValues();
|
||||
}
|
||||
|
||||
private void reloadDefaultsCallback() {
|
||||
if (Gui.hasThemeChanges()) {
|
||||
if (themeManager.hasThemeChanges()) {
|
||||
int result = OptionDialog.showYesNoDialog(null, "Reload Ghidra Default Values",
|
||||
"This will discard all your theme changes. Continue?");
|
||||
if (result == OptionDialog.NO_OPTION) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
Gui.reloadApplicationDefaults();
|
||||
themeManager.reloadApplicationDefaults();
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
@@ -147,15 +150,15 @@ public class ThemeDialog extends DialogComponentProvider {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ThemeUtils.askToSaveThemeChanges()) {
|
||||
if (!ThemeUtils.askToSaveThemeChanges(themeManager)) {
|
||||
Swing.runLater(() -> updateCombo());
|
||||
return;
|
||||
}
|
||||
String themeName = (String) e.getItem();
|
||||
|
||||
Swing.runLater(() -> {
|
||||
GTheme theme = Gui.getTheme(themeName);
|
||||
Gui.setTheme(theme);
|
||||
GTheme theme = themeManager.getTheme(themeName);
|
||||
themeManager.setTheme(theme);
|
||||
if (theme.getLookAndFeelType() == LafType.GTK) {
|
||||
setStatusText(
|
||||
"Warning - Themes using the GTK LookAndFeel do not support changing java component colors, fonts or icons.",
|
||||
@@ -171,7 +174,7 @@ public class ThemeDialog extends DialogComponentProvider {
|
||||
}
|
||||
|
||||
private void updateButtons() {
|
||||
boolean hasChanges = Gui.hasThemeChanges();
|
||||
boolean hasChanges = themeManager.hasThemeChanges();
|
||||
saveButton.setEnabled(hasChanges);
|
||||
restoreButton.setEnabled(hasChanges);
|
||||
}
|
||||
@@ -194,25 +197,25 @@ public class ThemeDialog extends DialogComponentProvider {
|
||||
}
|
||||
|
||||
private void updateCombo() {
|
||||
Set<GTheme> supportedThemes = Gui.getSupportedThemes();
|
||||
Set<GTheme> supportedThemes = themeManager.getSupportedThemes();
|
||||
List<String> themeNames =
|
||||
supportedThemes.stream().map(t -> t.getName()).collect(Collectors.toList());
|
||||
Collections.sort(themeNames);
|
||||
combo.removeItemListener(comboListener);
|
||||
combo.setModel(new DefaultComboBoxModel<String>(new Vector<String>(themeNames)));
|
||||
combo.setSelectedItem(Gui.getActiveTheme().getName());
|
||||
combo.setSelectedItem(themeManager.getActiveTheme().getName());
|
||||
combo.addItemListener(comboListener);
|
||||
}
|
||||
|
||||
private Component buildThemeCombo() {
|
||||
JPanel panel = new JPanel();
|
||||
Set<GTheme> supportedThemes = Gui.getSupportedThemes();
|
||||
Set<GTheme> supportedThemes = themeManager.getSupportedThemes();
|
||||
List<String> themeNames =
|
||||
supportedThemes.stream().map(t -> t.getName()).collect(Collectors.toList());
|
||||
Collections.sort(themeNames);
|
||||
|
||||
combo = new GhidraComboBox<>(themeNames);
|
||||
combo.setSelectedItem(Gui.getActiveTheme().getName());
|
||||
combo.setSelectedItem(themeManager.getActiveTheme().getName());
|
||||
combo.addItemListener(comboListener);
|
||||
|
||||
panel.add(new JLabel("Theme: "), BorderLayout.WEST);
|
||||
@@ -223,9 +226,9 @@ public class ThemeDialog extends DialogComponentProvider {
|
||||
|
||||
private Component buildTabedTables() {
|
||||
tabbedPane = new JTabbedPane();
|
||||
colorTable = new ThemeColorTable();
|
||||
fontTable = new ThemeFontTable();
|
||||
iconTable = new ThemeIconTable();
|
||||
colorTable = new ThemeColorTable(themeManager);
|
||||
fontTable = new ThemeFontTable(themeManager);
|
||||
iconTable = new ThemeIconTable(themeManager);
|
||||
tabbedPane.add("Colors", colorTable);
|
||||
tabbedPane.add("Fonts", fontTable);
|
||||
tabbedPane.add("Icons", iconTable);
|
||||
@@ -250,12 +253,16 @@ public class ThemeDialog extends DialogComponentProvider {
|
||||
return saveButton;
|
||||
}
|
||||
|
||||
public static void editTheme() {
|
||||
/**
|
||||
* Edits the current theme
|
||||
* @param themeManager the application ThemeManager
|
||||
*/
|
||||
public static void editTheme(ThemeManager themeManager) {
|
||||
if (INSTANCE != null) {
|
||||
INSTANCE.toFront();
|
||||
return;
|
||||
}
|
||||
INSTANCE = new ThemeDialog();
|
||||
INSTANCE = new ThemeDialog(themeManager);
|
||||
DockingWindowManager.showDialog(INSTANCE);
|
||||
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import docking.action.ActionContextProvider;
|
||||
import docking.widgets.table.GFilterTable;
|
||||
import docking.widgets.table.GTable;
|
||||
import generic.theme.FontValue;
|
||||
import generic.theme.Gui;
|
||||
import generic.theme.ThemeManager;
|
||||
import ghidra.util.Swing;
|
||||
|
||||
/**
|
||||
@@ -41,11 +41,13 @@ public class ThemeFontTable extends JPanel implements ActionContextProvider {
|
||||
private FontValueEditor fontEditor = new FontValueEditor(this::fontValueChanged);
|
||||
private GTable table;
|
||||
private GFilterTable<FontValue> filterTable;
|
||||
private ThemeManager themeManager;
|
||||
|
||||
public ThemeFontTable() {
|
||||
public ThemeFontTable(ThemeManager themeManager) {
|
||||
super(new BorderLayout());
|
||||
this.themeManager = themeManager;
|
||||
|
||||
fontTableModel = new ThemeFontTableModel();
|
||||
fontTableModel = new ThemeFontTableModel(themeManager);
|
||||
filterTable = new GFilterTable<>(fontTableModel);
|
||||
table = filterTable.getTable();
|
||||
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
@@ -86,7 +88,7 @@ public class ThemeFontTable extends JPanel implements ActionContextProvider {
|
||||
// run later - don't rock the boat in the middle of a listener callback
|
||||
Swing.runLater(() -> {
|
||||
FontValue newValue = (FontValue) event.getNewValue();
|
||||
Gui.setFont(newValue);
|
||||
themeManager.setFont(newValue);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -39,9 +39,11 @@ public class ThemeFontTableModel extends GDynamicColumnTableModel<FontValue, Obj
|
||||
private GThemeValueMap currentValues;
|
||||
private GThemeValueMap themeValues;
|
||||
private GThemeValueMap defaultValues;
|
||||
private ThemeManager themeManager;
|
||||
|
||||
public ThemeFontTableModel() {
|
||||
public ThemeFontTableModel(ThemeManager themeManager) {
|
||||
super(new ServiceProviderStub());
|
||||
this.themeManager = themeManager;
|
||||
load();
|
||||
}
|
||||
|
||||
@@ -49,7 +51,7 @@ public class ThemeFontTableModel extends GDynamicColumnTableModel<FontValue, Obj
|
||||
* Reloads the just the current values shown in the table. Called whenever a font changes.
|
||||
*/
|
||||
public void reloadCurrent() {
|
||||
currentValues = Gui.getAllValues();
|
||||
currentValues = themeManager.getCurrentValues();
|
||||
fonts = currentValues.getFonts();
|
||||
fireTableDataChanged();
|
||||
}
|
||||
@@ -64,10 +66,10 @@ public class ThemeFontTableModel extends GDynamicColumnTableModel<FontValue, Obj
|
||||
}
|
||||
|
||||
private void load() {
|
||||
currentValues = Gui.getAllValues();
|
||||
currentValues = themeManager.getCurrentValues();
|
||||
fonts = currentValues.getFonts();
|
||||
themeValues = Gui.getThemeValues();
|
||||
defaultValues = Gui.getDefaults();
|
||||
themeValues = themeManager.getThemeValues();
|
||||
defaultValues = themeManager.getDefaults();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,8 +26,8 @@ import docking.ActionContext;
|
||||
import docking.action.ActionContextProvider;
|
||||
import docking.widgets.table.GFilterTable;
|
||||
import docking.widgets.table.GTable;
|
||||
import generic.theme.Gui;
|
||||
import generic.theme.IconValue;
|
||||
import generic.theme.ThemeManager;
|
||||
import ghidra.util.Swing;
|
||||
|
||||
/**
|
||||
@@ -39,10 +39,12 @@ public class ThemeIconTable extends JPanel implements ActionContextProvider {
|
||||
private IconValueEditor iconEditor = new IconValueEditor(this::iconValueChanged);
|
||||
private GTable table;
|
||||
private GFilterTable<IconValue> filterTable;
|
||||
private ThemeManager themeManager;
|
||||
|
||||
public ThemeIconTable() {
|
||||
public ThemeIconTable(ThemeManager themeManager) {
|
||||
super(new BorderLayout());
|
||||
iconTableModel = new ThemeIconTableModel();
|
||||
this.themeManager = themeManager;
|
||||
iconTableModel = new ThemeIconTableModel(themeManager);
|
||||
filterTable = new GFilterTable<>(iconTableModel);
|
||||
table = filterTable.getTable();
|
||||
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
@@ -82,7 +84,7 @@ public class ThemeIconTable extends JPanel implements ActionContextProvider {
|
||||
// run later - don't rock the boat in the middle of a listener callback
|
||||
Swing.runLater(() -> {
|
||||
IconValue newValue = (IconValue) event.getNewValue();
|
||||
Gui.setIcon(newValue);
|
||||
themeManager.setIcon(newValue);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -39,9 +39,11 @@ public class ThemeIconTableModel extends GDynamicColumnTableModel<IconValue, Obj
|
||||
private GThemeValueMap currentValues;
|
||||
private GThemeValueMap themeValues;
|
||||
private GThemeValueMap defaultValues;
|
||||
private ThemeManager themeManager;
|
||||
|
||||
public ThemeIconTableModel() {
|
||||
public ThemeIconTableModel(ThemeManager themeManager) {
|
||||
super(new ServiceProviderStub());
|
||||
this.themeManager = themeManager;
|
||||
load();
|
||||
}
|
||||
|
||||
@@ -49,7 +51,7 @@ public class ThemeIconTableModel extends GDynamicColumnTableModel<IconValue, Obj
|
||||
* Reloads the just the current values shown in the table. Called whenever an icon changes.
|
||||
*/
|
||||
public void reloadCurrent() {
|
||||
currentValues = Gui.getAllValues();
|
||||
currentValues = themeManager.getCurrentValues();
|
||||
icons = currentValues.getIcons();
|
||||
fireTableDataChanged();
|
||||
}
|
||||
@@ -64,10 +66,10 @@ public class ThemeIconTableModel extends GDynamicColumnTableModel<IconValue, Obj
|
||||
}
|
||||
|
||||
private void load() {
|
||||
currentValues = Gui.getAllValues();
|
||||
currentValues = themeManager.getCurrentValues();
|
||||
icons = currentValues.getIcons();
|
||||
themeValues = Gui.getThemeValues();
|
||||
defaultValues = Gui.getDefaults();
|
||||
themeValues = themeManager.getThemeValues();
|
||||
defaultValues = themeManager.getDefaults();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -43,17 +43,17 @@ public class ThemeUtils {
|
||||
* overwrites an existing file.
|
||||
* @return true if the operation was not cancelled
|
||||
*/
|
||||
public static boolean askToSaveThemeChanges() {
|
||||
if (Gui.hasThemeChanges()) {
|
||||
public static boolean askToSaveThemeChanges(ThemeManager themeManager) {
|
||||
if (themeManager.hasThemeChanges()) {
|
||||
int result = OptionDialog.showYesNoCancelDialog(null, "Save Theme Changes?",
|
||||
"You have made changes to the theme.\n Do you want save your changes?");
|
||||
if (result == OptionDialog.CANCEL_OPTION) {
|
||||
return false;
|
||||
}
|
||||
if (result == OptionDialog.YES_OPTION) {
|
||||
return ThemeUtils.saveThemeChanges();
|
||||
return ThemeUtils.saveThemeChanges(themeManager);
|
||||
}
|
||||
Gui.reloadApplicationDefaults();
|
||||
themeManager.reloadApplicationDefaults();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -63,32 +63,33 @@ public class ThemeUtils {
|
||||
* name and asking to overwrite an existing file.
|
||||
* @return true if the operation was not cancelled
|
||||
*/
|
||||
public static boolean saveThemeChanges() {
|
||||
GTheme activeTheme = Gui.getActiveTheme();
|
||||
public static boolean saveThemeChanges(ThemeManager themeManager) {
|
||||
GTheme activeTheme = themeManager.getActiveTheme();
|
||||
String name = activeTheme.getName();
|
||||
|
||||
while (!canSaveToName(name)) {
|
||||
while (!canSaveToName(themeManager, name)) {
|
||||
name = getNameFromUser(name);
|
||||
if (name == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return saveCurrentValues(name);
|
||||
return saveCurrentValues(themeManager, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the theme to the default, handling the case where the current theme has changes.
|
||||
*/
|
||||
public static void resetThemeToDefault() {
|
||||
if (askToSaveThemeChanges()) {
|
||||
Gui.setTheme(Gui.getDefaultTheme());
|
||||
public static void resetThemeToDefault(ThemeManager themeManager) {
|
||||
if (askToSaveThemeChanges(themeManager)) {
|
||||
themeManager.setTheme(themeManager.getDefaultTheme());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports a theme. Handles the case where there are existing changes to the current theme.
|
||||
* @param themeManager the application ThemeManager
|
||||
*/
|
||||
public static void importTheme() {
|
||||
public static void importTheme(ThemeManager themeManager) {
|
||||
GhidraFileChooser chooser = new GhidraFileChooser(null);
|
||||
chooser.setTitle("Choose Theme File");
|
||||
chooser.setApproveButtonToolTipText("Select File");
|
||||
@@ -100,14 +101,14 @@ public class ThemeUtils {
|
||||
if (file == null) {
|
||||
return;
|
||||
}
|
||||
importTheme(file);
|
||||
importTheme(themeManager, file);
|
||||
}
|
||||
|
||||
static void importTheme(File themeFile) {
|
||||
if (!ThemeUtils.askToSaveThemeChanges()) {
|
||||
static void importTheme(ThemeManager themeManager, File themeFile) {
|
||||
if (!ThemeUtils.askToSaveThemeChanges(themeManager)) {
|
||||
return;
|
||||
}
|
||||
GTheme startingTheme = Gui.getActiveTheme();
|
||||
GTheme startingTheme = themeManager.getActiveTheme();
|
||||
try {
|
||||
GTheme imported = GTheme.loadTheme(themeFile);
|
||||
// by setting the theme, we can let the normal save handle all the edge cases
|
||||
@@ -115,9 +116,9 @@ public class ThemeUtils {
|
||||
// Also, the imported theme may contain default values which we don't want to save. So
|
||||
// by going through the usual save mechanism, only values that differ from defaults
|
||||
// be saved.
|
||||
Gui.setTheme(imported);
|
||||
if (!ThemeUtils.saveThemeChanges()) {
|
||||
Gui.setTheme(startingTheme);
|
||||
themeManager.setTheme(imported);
|
||||
if (!ThemeUtils.saveThemeChanges(themeManager)) {
|
||||
themeManager.setTheme(startingTheme);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
@@ -130,12 +131,13 @@ public class ThemeUtils {
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public static void exportTheme() {
|
||||
if (!ThemeUtils.askToSaveThemeChanges()) {
|
||||
public static void exportTheme(ThemeManager themeManager) {
|
||||
if (!ThemeUtils.askToSaveThemeChanges(themeManager)) {
|
||||
return;
|
||||
}
|
||||
boolean hasExternalIcons = !Gui.getActiveTheme().getExternalIconFiles().isEmpty();
|
||||
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.)";
|
||||
@@ -151,16 +153,16 @@ public class ThemeUtils {
|
||||
}
|
||||
boolean exportAsZip = result == OptionDialog.OPTION_ONE;
|
||||
|
||||
ExportThemeDialog dialog = new ExportThemeDialog(exportAsZip);
|
||||
ExportThemeDialog dialog = new ExportThemeDialog(themeManager, exportAsZip);
|
||||
DockingWindowManager.showDialog(dialog);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompts for and deletes a selected theme.
|
||||
*/
|
||||
public static void deleteTheme() {
|
||||
public static void deleteTheme(ThemeManager themeManager) {
|
||||
List<GTheme> savedThemes = new ArrayList<>(
|
||||
Gui.getAllThemes().stream().filter(t -> t.getFile() != null).toList());
|
||||
themeManager.getAllThemes().stream().filter(t -> t.getFile() != null).toList());
|
||||
if (savedThemes.isEmpty()) {
|
||||
Msg.showInfo(ThemeUtils.class, null, "Delete Theme", "There are no deletable themes");
|
||||
return;
|
||||
@@ -171,7 +173,7 @@ public class ThemeUtils {
|
||||
if (selectedTheme == null) {
|
||||
return;
|
||||
}
|
||||
if (Gui.getActiveTheme().equals(selectedTheme)) {
|
||||
if (themeManager.getActiveTheme().equals(selectedTheme)) {
|
||||
Msg.showWarn(ThemeUtils.class, null, "Delete Failed",
|
||||
"Can't delete the current theme.");
|
||||
return;
|
||||
@@ -180,7 +182,7 @@ public class ThemeUtils {
|
||||
int result = OptionDialog.showYesNoDialog(null, "Delete Theme: " + fileTheme.getName(),
|
||||
"Are you sure you want to delete theme " + fileTheme.getName());
|
||||
if (result == OptionDialog.YES_OPTION) {
|
||||
Gui.deleteTheme(fileTheme);
|
||||
themeManager.deleteTheme(fileTheme);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,8 +192,8 @@ public class ThemeUtils {
|
||||
return inputDialog.getValue();
|
||||
}
|
||||
|
||||
private static boolean canSaveToName(String name) {
|
||||
GTheme existing = Gui.getTheme(name);
|
||||
private static boolean canSaveToName(ThemeManager themeManager, String name) {
|
||||
GTheme existing = themeManager.getTheme(name);
|
||||
// if no theme exists with that name, then we are save to save it
|
||||
if (existing == null) {
|
||||
return true;
|
||||
@@ -210,17 +212,17 @@ public class ThemeUtils {
|
||||
return result == OptionDialog.YES_OPTION;
|
||||
}
|
||||
|
||||
private static boolean saveCurrentValues(String themeName) {
|
||||
GTheme activeTheme = Gui.getActiveTheme();
|
||||
private static boolean saveCurrentValues(ThemeManager themeManager, String themeName) {
|
||||
GTheme activeTheme = themeManager.getActiveTheme();
|
||||
File file = getSaveFile(themeName);
|
||||
|
||||
GTheme newTheme = new GTheme(file, themeName, activeTheme.getLookAndFeelType(),
|
||||
activeTheme.useDarkDefaults());
|
||||
newTheme.load(Gui.getNonDefaultValues());
|
||||
newTheme.load(themeManager.getNonDefaultValues());
|
||||
try {
|
||||
newTheme.save();
|
||||
Gui.addTheme(newTheme);
|
||||
Gui.setTheme(newTheme);
|
||||
themeManager.addTheme(newTheme);
|
||||
themeManager.setTheme(newTheme);
|
||||
}
|
||||
catch (IOException e) {
|
||||
Msg.showError(ThemeUtils.class, null, "I/O Error",
|
||||
|
||||
@@ -24,7 +24,7 @@ import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import generic.theme.Gui;
|
||||
import ghidra.docking.util.LookAndFeelUtils;
|
||||
import resources.ResourceManager;
|
||||
|
||||
/**
|
||||
@@ -123,7 +123,7 @@ public class EmptyBorderButton extends JButton {
|
||||
|
||||
// Mac OSX LNF doesn't give us rollover callbacks, so we have to add a mouse listener to
|
||||
// do the work
|
||||
if (Gui.isUsingAquaUI(getUI())) {
|
||||
if (LookAndFeelUtils.isUsingAquaUI(getUI())) {
|
||||
addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
|
||||
+3
-2
@@ -38,7 +38,6 @@ import docking.widgets.label.GLabel;
|
||||
import docking.widgets.list.GListCellRenderer;
|
||||
import generic.theme.GColor;
|
||||
import generic.theme.GIcon;
|
||||
import generic.theme.GThemeDefaults.Colors.Palette;
|
||||
import ghidra.framework.preferences.Preferences;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.exception.AssertException;
|
||||
@@ -74,6 +73,8 @@ public class GhidraFileChooser extends DialogComponentProvider implements FileFi
|
||||
static final String UP_BUTTON_NAME = "UP_BUTTON";
|
||||
private static final Color FOREROUND_COLOR = new GColor("color.fg.filechooser");
|
||||
private static final Color BACKGROUND_COLOR = new GColor("color.bg.filechooser");
|
||||
private static final Color SHORTCUT_BACKGROUND_COLOR =
|
||||
new GColor("color.bg.filechooser.shortcut");
|
||||
static final String PREFERENCES_PREFIX = "G_FILE_CHOOSER";
|
||||
private static final String WIDTH_PREFERENCE_PREFIX = PREFERENCES_PREFIX + ".WIDTH.";
|
||||
private static final String HEIGHT_PREFERENCE_PREFIX = PREFERENCES_PREFIX + ".HEIGHT.";
|
||||
@@ -343,7 +344,7 @@ public class GhidraFileChooser extends DialogComponentProvider implements FileFi
|
||||
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.setBorder(BorderFactory.createLoweredBevelBorder());
|
||||
panel.setBackground(Palette.DARK_GRAY);
|
||||
panel.setBackground(SHORTCUT_BACKGROUND_COLOR);
|
||||
panel.add(shortCutPanel, BorderLayout.NORTH);
|
||||
return panel;
|
||||
}
|
||||
|
||||
+11
-6
@@ -22,12 +22,14 @@ import java.text.DecimalFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import javax.swing.table.TableModel;
|
||||
|
||||
import docking.widgets.AbstractGCellRenderer;
|
||||
import generic.theme.GColor;
|
||||
import generic.theme.Gui;
|
||||
import ghidra.docking.settings.*;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.exception.AssertException;
|
||||
@@ -56,7 +58,13 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe
|
||||
* Constructs a new GTableCellRenderer.
|
||||
*/
|
||||
public GTableCellRenderer() {
|
||||
|
||||
// When the Look And Feel changes, renderers are not auto updated because they
|
||||
// are not part of the component tree. So listen for a change to the Look And Feel.
|
||||
Gui.addThemeListener(e -> {
|
||||
if (e.isLookAndFeelChanged()) {
|
||||
updateUI();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,10 +108,7 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe
|
||||
"Using a GTableCellRenderer in a non-GTable table. (Model class: " +
|
||||
table.getModel().getClass().getName() + ")");
|
||||
}
|
||||
// check if LookAndFeel has changed
|
||||
if (UIManager.getUI(this) != getUI()) {
|
||||
updateUI();
|
||||
}
|
||||
|
||||
GTable gTable = (GTable) table;
|
||||
GTableCellRenderingData data = gTable.getRenderingData(column);
|
||||
Object rowObject = null;
|
||||
|
||||
@@ -45,6 +45,7 @@ import docking.widgets.tree.internal.*;
|
||||
import docking.widgets.tree.support.*;
|
||||
import docking.widgets.tree.support.GTreeSelectionEvent.EventOrigin;
|
||||
import docking.widgets.tree.tasks.*;
|
||||
import generic.theme.*;
|
||||
import generic.timer.ExpiringSwingTimer;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
@@ -55,8 +56,8 @@ import ghidra.util.worker.PriorityWorker;
|
||||
* Class for creating a JTree that supports filtering, threading, and a progress bar.
|
||||
*/
|
||||
|
||||
public class GTree extends JPanel implements BusyListener {
|
||||
|
||||
public class GTree extends JPanel implements BusyListener, ThemeListener {
|
||||
private static final Color BACKGROUND = new GColor("color.bg.tree");
|
||||
private AutoScrollTree tree;
|
||||
private GTreeModel model;
|
||||
|
||||
@@ -134,6 +135,7 @@ public class GTree extends JPanel implements BusyListener {
|
||||
uniquePreferenceKey));
|
||||
|
||||
filterUpdateManager = new SwingUpdateManager(1000, 30000, () -> updateModelFilter());
|
||||
Gui.addThemeListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,6 +148,13 @@ public class GTree extends JPanel implements BusyListener {
|
||||
threadLocalMonitor.set(monitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void themeChanged(ThemeEvent event) {
|
||||
if (event.isLookAndFeelChanged()) {
|
||||
model.fireNodeStructureChanged(getModelRoot());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the monitor in associated with the GTree for the calling thread. This method is
|
||||
* designed to be used by slow loading nodes that are loading <b>off the Swing thread</b>. Some
|
||||
@@ -1391,6 +1400,7 @@ public class GTree extends JPanel implements BusyListener {
|
||||
|
||||
public AutoScrollTree(TreeModel model) {
|
||||
super(model);
|
||||
setBackground(BACKGROUND);
|
||||
scroller = new AutoscrollAdapter(this, 5);
|
||||
|
||||
setRowHeight(-1);// variable size rows
|
||||
|
||||
@@ -31,6 +31,8 @@ public class GTreeRenderer extends DefaultTreeCellRenderer implements GComponent
|
||||
|
||||
private static final Color VALID_DROP_TARGET_COLOR = new GColor("color.bg.tree.drag");
|
||||
private static final int DEFAULT_MIN_ICON_WIDTH = 22;
|
||||
private static final Color BACKGROUND_UNSELECTED = new GColor("color.bg.tree");
|
||||
private static final Color BACKGROUND_SELECTED = new GColor("color.bg.tree.selected");
|
||||
|
||||
private Object dropTarget;
|
||||
private boolean paintDropTarget;
|
||||
@@ -41,6 +43,8 @@ public class GTreeRenderer extends DefaultTreeCellRenderer implements GComponent
|
||||
|
||||
public GTreeRenderer() {
|
||||
setHTMLRenderingEnabled(false);
|
||||
setBackgroundNonSelectionColor(BACKGROUND_UNSELECTED);
|
||||
setBackgroundSelectionColor(BACKGROUND_SELECTED);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,10 +21,12 @@ import java.util.Iterator;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.UIDefaults;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.*;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
|
||||
import docking.framework.ApplicationInformationDisplayFactory;
|
||||
import generic.theme.LafType;
|
||||
import generic.theme.ThemeManager;
|
||||
import ghidra.framework.preferences.Preferences;
|
||||
import ghidra.util.SystemUtilities;
|
||||
|
||||
@@ -81,4 +83,30 @@ public class LookAndFeelUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link LafType} for the currently active {@link LookAndFeel}
|
||||
* @return the {@link LafType} for the currently active {@link LookAndFeel}
|
||||
*/
|
||||
public static LafType getLookAndFeelType() {
|
||||
return ThemeManager.getInstance().getLookAndFeelType();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 static boolean isUsingAquaUI(ComponentUI UI) {
|
||||
return ThemeManager.getInstance().isUsingAquaUI(UI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if 'Nimbus' is the current Look and Feel
|
||||
* @return true if 'Nimbus' is the current Look and Feel
|
||||
*/
|
||||
public static boolean isUsingNimbusUI() {
|
||||
return ThemeManager.getInstance().isUsingNimbusUI();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 187 B After Width: | Height: | Size: 727 B |
Binary file not shown.
|
Before Width: | Height: | Size: 185 B After Width: | Height: | Size: 692 B |
@@ -41,67 +41,69 @@ import generic.theme.builtin.NimbusTheme;
|
||||
public class ThemeUtilsTest extends AbstractDockingTest {
|
||||
|
||||
private Color testColor = Palette.RED;
|
||||
private ThemeManager themeManager;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
themeManager = ThemeManager.getInstance();
|
||||
GTheme nimbusTheme = new NimbusTheme();
|
||||
GTheme metalTheme = new MetalTheme();
|
||||
Gui.addTheme(nimbusTheme);
|
||||
Gui.addTheme(metalTheme);
|
||||
Gui.setTheme(nimbusTheme);
|
||||
themeManager.addTheme(nimbusTheme);
|
||||
themeManager.addTheme(metalTheme);
|
||||
themeManager.setTheme(nimbusTheme);
|
||||
|
||||
// get rid of any leftover imported themes from previous tests
|
||||
Set<GTheme> allThemes = Gui.getAllThemes();
|
||||
Set<GTheme> allThemes = themeManager.getAllThemes();
|
||||
for (GTheme theme : allThemes) {
|
||||
if (!(theme instanceof DiscoverableGTheme)) {
|
||||
Gui.deleteTheme(theme);
|
||||
themeManager.deleteTheme(theme);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImportThemeNonZip() throws IOException {
|
||||
assertEquals("Nimbus Theme", Gui.getActiveTheme().getName());
|
||||
assertEquals("Nimbus Theme", themeManager.getActiveTheme().getName());
|
||||
File themeFile = createThemeFile("Bob");
|
||||
ThemeUtils.importTheme(themeFile);
|
||||
assertEquals("Bob", Gui.getActiveTheme().getName());
|
||||
ThemeUtils.importTheme(themeManager, themeFile);
|
||||
assertEquals("Bob", themeManager.getActiveTheme().getName());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImportThemeFromZip() throws IOException {
|
||||
assertEquals("Nimbus Theme", Gui.getActiveTheme().getName());
|
||||
assertEquals("Nimbus Theme", themeManager.getActiveTheme().getName());
|
||||
File themeFile = createZipThemeFile("zippy");
|
||||
ThemeUtils.importTheme(themeFile);
|
||||
assertEquals("zippy", Gui.getActiveTheme().getName());
|
||||
ThemeUtils.importTheme(themeManager, themeFile);
|
||||
assertEquals("zippy", themeManager.getActiveTheme().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImportThemeWithCurrentChangesCancelled() throws IOException {
|
||||
assertEquals("Nimbus Theme", Gui.getActiveTheme().getName());
|
||||
Gui.setColor("Panel.background", testColor);
|
||||
assertTrue(Gui.hasThemeChanges());
|
||||
assertEquals("Nimbus Theme", themeManager.getActiveTheme().getName());
|
||||
themeManager.setColor("Panel.background", testColor);
|
||||
assertTrue(themeManager.hasThemeChanges());
|
||||
|
||||
File themeFile = createThemeFile("Bob");
|
||||
runSwingLater(() -> ThemeUtils.importTheme(themeFile));
|
||||
runSwingLater(() -> ThemeUtils.importTheme(themeManager, themeFile));
|
||||
OptionDialog dialog = waitForDialogComponent(OptionDialog.class);
|
||||
assertNotNull(dialog);
|
||||
assertEquals("Save Theme Changes?", dialog.getTitle());
|
||||
pressButtonByText(dialog, "Cancel");
|
||||
waitForSwing();
|
||||
assertEquals("Nimbus Theme", Gui.getActiveTheme().getName());
|
||||
assertEquals("Nimbus Theme", themeManager.getActiveTheme().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImportThemeWithCurrentChangesSaved() throws IOException {
|
||||
assertEquals("Nimbus Theme", Gui.getActiveTheme().getName());
|
||||
assertEquals("Nimbus Theme", themeManager.getActiveTheme().getName());
|
||||
|
||||
// make a change in the current theme, so you get asked to save
|
||||
Gui.setColor("Panel.background", testColor);
|
||||
assertTrue(Gui.hasThemeChanges());
|
||||
themeManager.setColor("Panel.background", testColor);
|
||||
assertTrue(themeManager.hasThemeChanges());
|
||||
|
||||
File themeFile = createThemeFile("Bob");
|
||||
runSwingLater(() -> ThemeUtils.importTheme(themeFile));
|
||||
runSwingLater(() -> ThemeUtils.importTheme(themeManager, themeFile));
|
||||
OptionDialog dialog = waitForDialogComponent(OptionDialog.class);
|
||||
assertNotNull(dialog);
|
||||
assertEquals("Save Theme Changes?", dialog.getTitle());
|
||||
@@ -111,32 +113,32 @@ public class ThemeUtilsTest extends AbstractDockingTest {
|
||||
runSwing(() -> inputDialog.setValue("Joe"));
|
||||
pressButtonByText(inputDialog, "OK");
|
||||
waitForSwing();
|
||||
assertEquals("Bob", Gui.getActiveTheme().getName());
|
||||
assertNotNull(Gui.getTheme("Joe"));
|
||||
assertEquals("Bob", themeManager.getActiveTheme().getName());
|
||||
assertNotNull(themeManager.getTheme("Joe"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImportThemeWithCurrentChangesThrownAway() throws IOException {
|
||||
assertEquals("Nimbus Theme", Gui.getActiveTheme().getName());
|
||||
assertEquals("Nimbus Theme", themeManager.getActiveTheme().getName());
|
||||
|
||||
// make a change in the current theme, so you get asked to save
|
||||
Gui.setColor("Panel.background", testColor);
|
||||
assertTrue(Gui.hasThemeChanges());
|
||||
themeManager.setColor("Panel.background", testColor);
|
||||
assertTrue(themeManager.hasThemeChanges());
|
||||
|
||||
File bobThemeFile = createThemeFile("Bob");
|
||||
runSwingLater(() -> ThemeUtils.importTheme(bobThemeFile));
|
||||
runSwingLater(() -> ThemeUtils.importTheme(themeManager, bobThemeFile));
|
||||
|
||||
OptionDialog dialog = waitForDialogComponent(OptionDialog.class);
|
||||
assertNotNull(dialog);
|
||||
assertEquals("Save Theme Changes?", dialog.getTitle());
|
||||
pressButtonByText(dialog, "No");
|
||||
waitForSwing();
|
||||
assertEquals("Bob", Gui.getActiveTheme().getName());
|
||||
assertEquals("Bob", themeManager.getActiveTheme().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExportThemeAsZip() throws IOException {
|
||||
runSwingLater(() -> ThemeUtils.exportTheme());
|
||||
runSwingLater(() -> ThemeUtils.exportTheme(themeManager));
|
||||
OptionDialog dialog = waitForDialogComponent(OptionDialog.class);
|
||||
pressButtonByText(dialog, "Export Zip");
|
||||
ExportThemeDialog exportDialog = waitForDialogComponent(ExportThemeDialog.class);
|
||||
@@ -151,7 +153,7 @@ public class ThemeUtilsTest extends AbstractDockingTest {
|
||||
|
||||
@Test
|
||||
public void testExportThemeAsFile() throws IOException {
|
||||
runSwingLater(() -> ThemeUtils.exportTheme());
|
||||
runSwingLater(() -> ThemeUtils.exportTheme(themeManager));
|
||||
OptionDialog dialog = waitForDialogComponent(OptionDialog.class);
|
||||
pressButtonByText(dialog, "Export File");
|
||||
ExportThemeDialog exportDialog = waitForDialogComponent(ExportThemeDialog.class);
|
||||
@@ -167,29 +169,29 @@ public class ThemeUtilsTest extends AbstractDockingTest {
|
||||
@Test
|
||||
public void testDeleteTheme() throws IOException {
|
||||
File themeFile = createThemeFile("Bob");
|
||||
ThemeUtils.importTheme(themeFile);
|
||||
ThemeUtils.importTheme(themeManager, themeFile);
|
||||
themeFile = createThemeFile("Joe");
|
||||
ThemeUtils.importTheme(themeFile);
|
||||
ThemeUtils.importTheme(themeManager, themeFile);
|
||||
themeFile = createThemeFile("Lisa");
|
||||
ThemeUtils.importTheme(themeFile);
|
||||
ThemeUtils.importTheme(themeManager, themeFile);
|
||||
|
||||
assertNotNull(Gui.getTheme("Bob"));
|
||||
assertNotNull(Gui.getTheme("Joe"));
|
||||
assertNotNull(Gui.getTheme("Lisa"));
|
||||
assertNotNull(themeManager.getTheme("Bob"));
|
||||
assertNotNull(themeManager.getTheme("Joe"));
|
||||
assertNotNull(themeManager.getTheme("Lisa"));
|
||||
|
||||
runSwingLater(() -> ThemeUtils.deleteTheme());
|
||||
runSwingLater(() -> ThemeUtils.deleteTheme(themeManager));
|
||||
@SuppressWarnings("unchecked")
|
||||
SelectFromListDialog<GTheme> dialog = waitForDialogComponent(SelectFromListDialog.class);
|
||||
runSwing(() -> dialog.setSelectedObject(Gui.getTheme("Bob")));
|
||||
runSwing(() -> dialog.setSelectedObject(themeManager.getTheme("Bob")));
|
||||
pressButtonByText(dialog, "OK");
|
||||
|
||||
OptionDialog optionDialog = waitForDialogComponent(OptionDialog.class);
|
||||
pressButtonByText(optionDialog, "Yes");
|
||||
waitForSwing();
|
||||
|
||||
assertNotNull(Gui.getTheme("Bob"));
|
||||
assertNull(Gui.getTheme("Joe"));
|
||||
assertNotNull(Gui.getTheme("Lisa"));
|
||||
assertNotNull(themeManager.getTheme("Bob"));
|
||||
assertNull(themeManager.getTheme("Joe"));
|
||||
assertNotNull(themeManager.getTheme("Lisa"));
|
||||
|
||||
}
|
||||
|
||||
@@ -231,7 +233,7 @@ public class ThemeUtilsTest extends AbstractDockingTest {
|
||||
File file = createTempFile("Test_Theme", ".theme.zip");
|
||||
GTheme outputTheme = new GTheme(file, themeName, LafType.METAL, false);
|
||||
outputTheme.addColor(new ColorValue("Panel.Background", testColor));
|
||||
outputTheme.saveToZip(file, false);
|
||||
new ThemeWriter(outputTheme).writeThemeToZipFile(file);
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ icon.expand.all = expand_all.png
|
||||
|
||||
icon.configure.filter = exec.png
|
||||
icon.clear = erase16.png
|
||||
icon.delete = icon.error
|
||||
icon.delete = edit-delete.png
|
||||
icon.error = emblem-important.png
|
||||
|
||||
icon.home = go-home.png
|
||||
|
||||
@@ -0,0 +1,484 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package generic.theme;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.io.File;
|
||||
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.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
|
||||
* {@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<>();
|
||||
private Map<String, GIconUIResource> gIconMap = new HashMap<>();
|
||||
|
||||
// stores the original value for ids whose value has changed from the current theme
|
||||
private GThemeValueMap changedValuesMap = new GThemeValueMap();
|
||||
protected LookAndFeelManager lookAndFeelManager;
|
||||
|
||||
/**
|
||||
* Initialized the Theme and its values for the application.
|
||||
*/
|
||||
public static void initialize() {
|
||||
if (INSTANCE instanceof ApplicationThemeManager) {
|
||||
Msg.error(ThemeManager.class, "Attempted to initialize theming more than once!");
|
||||
return;
|
||||
}
|
||||
|
||||
ApplicationThemeManager themeManager = new ApplicationThemeManager();
|
||||
themeManager.doInitialize();
|
||||
}
|
||||
|
||||
protected ApplicationThemeManager() {
|
||||
// AppliationThemeManagers always replace any other instances
|
||||
INSTANCE = this;
|
||||
installInGui();
|
||||
}
|
||||
|
||||
protected void doInitialize() {
|
||||
installFlatLookAndFeels();
|
||||
loadThemeDefaults();
|
||||
setTheme(themePreferences.load());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reloadApplicationDefaults() {
|
||||
loadThemeDefaults();
|
||||
buildCurrentValues();
|
||||
lookAndFeelManager.resetAll(javaDefaults);
|
||||
notifyThemeChanged(new AllValuesChangedThemeEvent(false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreThemeValues() {
|
||||
buildCurrentValues();
|
||||
lookAndFeelManager.resetAll(javaDefaults);
|
||||
notifyThemeChanged(new AllValuesChangedThemeEvent(false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreColor(String id) {
|
||||
if (changedValuesMap.containsColor(id)) {
|
||||
setColor(changedValuesMap.getColor(id));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFont(String id) {
|
||||
if (changedValuesMap.containsFont(id)) {
|
||||
setFont(changedValuesMap.getFont(id));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreIcon(String id) {
|
||||
if (changedValuesMap.containsIcon(id)) {
|
||||
setIcon(changedValuesMap.getIcon(id));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChangedColor(String id) {
|
||||
return changedValuesMap.containsColor(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChangedFont(String id) {
|
||||
return changedValuesMap.containsFont(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChangedIcon(String id) {
|
||||
return changedValuesMap.containsIcon(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTheme(GTheme theme) {
|
||||
if (theme.hasSupportedLookAndFeel()) {
|
||||
activeTheme = theme;
|
||||
LafType lafType = theme.getLookAndFeelType();
|
||||
lookAndFeelManager = lafType.getLookAndFeelManager(this);
|
||||
try {
|
||||
lookAndFeelManager.installLookAndFeel();
|
||||
themePreferences.save(theme);
|
||||
notifyThemeChanged(new AllValuesChangedThemeEvent(true));
|
||||
}
|
||||
catch (Exception e) {
|
||||
Msg.error(this, "Error setting LookAndFeel: " + lafType.getName(), e);
|
||||
}
|
||||
}
|
||||
currentValues.checkForUnresolvedReferences();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTheme(GTheme newTheme) {
|
||||
loadThemes();
|
||||
allThemes.remove(newTheme);
|
||||
allThemes.add(newTheme);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteTheme(GTheme theme) {
|
||||
File file = theme.getFile();
|
||||
if (file != null) {
|
||||
file.delete();
|
||||
}
|
||||
if (allThemes != null) {
|
||||
allThemes.remove(theme);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<GTheme> getAllThemes() {
|
||||
loadThemes();
|
||||
return new HashSet<>(allThemes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<GTheme> getSupportedThemes() {
|
||||
loadThemes();
|
||||
Set<GTheme> supported = new HashSet<>();
|
||||
for (GTheme theme : allThemes) {
|
||||
if (theme.hasSupportedLookAndFeel()) {
|
||||
supported.add(theme);
|
||||
}
|
||||
}
|
||||
return supported;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GTheme getActiveTheme() {
|
||||
return activeTheme;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LafType getLookAndFeelType() {
|
||||
return activeTheme.getLookAndFeelType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GTheme getTheme(String themeName) {
|
||||
Optional<GTheme> first =
|
||||
getAllThemes().stream().filter(t -> t.getName().equals(themeName)).findFirst();
|
||||
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());
|
||||
if (newValue.equals(currentValue)) {
|
||||
return;
|
||||
}
|
||||
updateChangedValuesMap(currentValue, newValue);
|
||||
|
||||
currentValues.addFont(newValue);
|
||||
notifyThemeChanged(new FontChangedThemeEvent(currentValues, newValue));
|
||||
|
||||
// update all java LookAndFeel fonts affected by this changed
|
||||
String id = newValue.getId();
|
||||
Set<String> changedFontIds = findChangedJavaFontIds(id);
|
||||
lookAndFeelManager.fontsChanged(changedFontIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColor(ColorValue newValue) {
|
||||
ColorValue currentValue = currentValues.getColor(newValue.getId());
|
||||
if (newValue.equals(currentValue)) {
|
||||
return;
|
||||
}
|
||||
updateChangedValuesMap(currentValue, newValue);
|
||||
currentValues.addColor(newValue);
|
||||
notifyThemeChanged(new ColorChangedThemeEvent(currentValues, newValue));
|
||||
|
||||
// now update the ui
|
||||
if (lookAndFeelManager != null) {
|
||||
lookAndFeelManager.colorsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIcon(IconValue newValue) {
|
||||
IconValue currentValue = currentValues.getIcon(newValue.getId());
|
||||
if (newValue.equals(currentValue)) {
|
||||
return;
|
||||
}
|
||||
updateChangedValuesMap(currentValue, newValue);
|
||||
|
||||
currentValues.addIcon(newValue);
|
||||
notifyThemeChanged(new IconChangedThemeEvent(currentValues, newValue));
|
||||
|
||||
// now update the ui
|
||||
// update all java LookAndFeel icons affected by this changed
|
||||
String id = newValue.getId();
|
||||
Set<String> changedIconIds = findChangedJavaIconIds(id);
|
||||
Icon newIcon = newValue.get(currentValues);
|
||||
lookAndFeelManager.iconsChanged(changedIconIds, newIcon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GColorUIResource getGColorUiResource(String id) {
|
||||
GColorUIResource gColor = gColorMap.get(id);
|
||||
if (gColor == null) {
|
||||
gColor = new GColorUIResource(id);
|
||||
gColorMap.put(id, gColor);
|
||||
}
|
||||
return gColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GIconUIResource getGIconUiResource(String id) {
|
||||
|
||||
GIconUIResource gIcon = gIconMap.get(id);
|
||||
if (gIcon == null) {
|
||||
gIcon = new GIconUIResource(id);
|
||||
gIconMap.put(id, gIcon);
|
||||
}
|
||||
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) {
|
||||
systemValues = map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
public void setJavaDefaults(GThemeValueMap map) {
|
||||
javaDefaults = map;
|
||||
buildCurrentValues();
|
||||
GColor.refreshAll(currentValues);
|
||||
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();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerFont(Component component, String fontId) {
|
||||
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;
|
||||
changedValuesMap.clear();
|
||||
}
|
||||
|
||||
private void loadThemes() {
|
||||
if (allThemes == null) {
|
||||
Set<GTheme> set = new HashSet<>();
|
||||
set.addAll(findDiscoverableThemes());
|
||||
set.addAll(themeFileLoader.loadThemeFiles());
|
||||
allThemes = set;
|
||||
}
|
||||
}
|
||||
|
||||
private Collection<DiscoverableGTheme> findDiscoverableThemes() {
|
||||
return ClassSearcher.getInstances(DiscoverableGTheme.class);
|
||||
}
|
||||
|
||||
private void updateChangedValuesMap(ColorValue currentValue, ColorValue newValue) {
|
||||
String id = newValue.getId();
|
||||
ColorValue originalValue = changedValuesMap.getColor(id);
|
||||
|
||||
// if new value is original value, it is no longer changed, remove it from changed map
|
||||
if (newValue.equals(originalValue)) {
|
||||
changedValuesMap.removeColor(id);
|
||||
}
|
||||
else if (originalValue == null) {
|
||||
// first time changed, so current value is original value
|
||||
changedValuesMap.addColor(currentValue);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateChangedValuesMap(FontValue currentValue, FontValue newValue) {
|
||||
String id = newValue.getId();
|
||||
FontValue originalValue = changedValuesMap.getFont(id);
|
||||
|
||||
// if new value is original value, it is no longer changed, remove it from changed map
|
||||
if (newValue.equals(originalValue)) {
|
||||
changedValuesMap.removeFont(id);
|
||||
}
|
||||
else if (originalValue == null) {
|
||||
// first time changed, so current value is original value
|
||||
changedValuesMap.addFont(currentValue);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateChangedValuesMap(IconValue currentValue, IconValue newValue) {
|
||||
String id = newValue.getId();
|
||||
IconValue originalValue = changedValuesMap.getIcon(id);
|
||||
|
||||
// if new value is original value, it is no longer changed, remove it from changed map
|
||||
if (newValue.equals(originalValue)) {
|
||||
changedValuesMap.removeIcon(id);
|
||||
}
|
||||
else if (originalValue == null) {
|
||||
// first time changed, so current value is original value
|
||||
changedValuesMap.addIcon(currentValue);
|
||||
}
|
||||
}
|
||||
|
||||
private Set<String> findChangedJavaFontIds(String id) {
|
||||
Set<String> affectedIds = new HashSet<>();
|
||||
List<FontValue> fonts = javaDefaults.getFonts();
|
||||
for (FontValue fontValue : fonts) {
|
||||
String fontId = fontValue.getId();
|
||||
FontValue currentFontValue = currentValues.getFont(fontId);
|
||||
if (fontId.equals(id) || currentFontValue.inheritsFrom(id, currentValues)) {
|
||||
affectedIds.add(fontId);
|
||||
}
|
||||
}
|
||||
return affectedIds;
|
||||
}
|
||||
|
||||
private Set<String> findChangedJavaIconIds(String id) {
|
||||
Set<String> affectedIds = new HashSet<>();
|
||||
List<IconValue> icons = javaDefaults.getIcons();
|
||||
for (IconValue iconValue : icons) {
|
||||
String iconId = iconValue.getId();
|
||||
if (iconId.equals(id) || iconValue.inheritsFrom(id, currentValues)) {
|
||||
affectedIds.add(iconId);
|
||||
}
|
||||
}
|
||||
return affectedIds;
|
||||
}
|
||||
|
||||
public void refreshGThemeValues() {
|
||||
GColor.refreshAll(currentValues);
|
||||
GIcon.refreshAll(currentValues);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -150,8 +150,8 @@ public class ColorValue extends ThemeValue<Color> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installValue() {
|
||||
Gui.setColor(this);
|
||||
public void installValue(ThemeManager themeManager) {
|
||||
themeManager.setColor(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -232,8 +232,8 @@ public class FontValue extends ThemeValue<Font> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installValue() {
|
||||
Gui.setFont(this);
|
||||
public void installValue(ThemeManager themeManager) {
|
||||
themeManager.setFont(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -50,20 +50,9 @@ public class GColor extends Color {
|
||||
* @param id the id used to lookup the current value for this color
|
||||
*/
|
||||
public GColor(String id) {
|
||||
this(id, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a GColor with an id that will be used to look up the current color associated with
|
||||
* that id, which can be changed at runtime.
|
||||
* @param id the id used to lookup the current value for this color
|
||||
* @param validate if true, an error will be generated if the id can't be resolved to a color
|
||||
* at this time
|
||||
*/
|
||||
public GColor(String id, boolean validate) {
|
||||
super(0x808080);
|
||||
this.id = id;
|
||||
delegate = Gui.getColor(id, validate);
|
||||
delegate = Gui.getColor(id);
|
||||
inUseColors.add(this);
|
||||
|
||||
}
|
||||
@@ -230,9 +219,11 @@ public class GColor extends Color {
|
||||
|
||||
/**
|
||||
* Reloads the delegate.
|
||||
* @param currentValues the map of current theme values
|
||||
*/
|
||||
public void refresh() {
|
||||
Color color = Gui.getColor(id, false);
|
||||
public void refresh(GThemeValueMap currentValues) {
|
||||
ColorValue value = currentValues.getColor(id);
|
||||
Color color = value == null ? null : value.get(currentValues);
|
||||
if (color != null) {
|
||||
if (alpha != null) {
|
||||
delegate = new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha);
|
||||
@@ -246,10 +237,11 @@ public class GColor extends Color {
|
||||
/**
|
||||
* Static method for notifying all the existing GColors that colors have changed and they
|
||||
* should reload their cached indirect color.
|
||||
* @param currentValues the map of current theme values
|
||||
*/
|
||||
public static void refreshAll() {
|
||||
public static void refreshAll(GThemeValueMap currentValues) {
|
||||
for (GColor gcolor : inUseColors.getValues()) {
|
||||
gcolor.refresh();
|
||||
gcolor.refresh(currentValues);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,10 +46,11 @@ public class GIcon implements Icon {
|
||||
/**
|
||||
* Static method for notifying all the existing GIcon that icons have changed and they
|
||||
* should reload their cached indirect icon.
|
||||
* @param currentValues the map of all current theme values
|
||||
*/
|
||||
public static void refreshAll() {
|
||||
public static void refreshAll(GThemeValueMap currentValues) {
|
||||
for (GIcon gIcon : inUseIcons.getValues()) {
|
||||
gIcon.refresh();
|
||||
gIcon.refresh(currentValues);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,19 +60,8 @@ public class GIcon implements Icon {
|
||||
* @param id the id used to lookup the current value for this color
|
||||
*/
|
||||
public GIcon(String id) {
|
||||
this(id, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a GIcon with an id that will be used to look up the current icon associated with
|
||||
* that id, which can be changed at runtime.
|
||||
* @param id the id used to lookup the current value for this icon
|
||||
* @param validate if true, an error will be generated if the id can't be resolved to a icon
|
||||
* at this time
|
||||
*/
|
||||
public GIcon(String id, boolean validate) {
|
||||
this.id = id;
|
||||
delegate = Gui.getIcon(id, validate);
|
||||
delegate = Gui.getIcon(id);
|
||||
inUseIcons.add(this);
|
||||
}
|
||||
|
||||
@@ -134,14 +124,25 @@ public class GIcon implements Icon {
|
||||
|
||||
/**
|
||||
* Reloads the delegate.
|
||||
* @param currentValues the map of current theme values
|
||||
*/
|
||||
public void refresh() {
|
||||
Icon icon = Gui.getIcon(id, false);
|
||||
public void refresh(GThemeValueMap currentValues) {
|
||||
IconValue value = currentValues.getIcon(id);
|
||||
Icon icon = value == null ? null : value.get(currentValues);
|
||||
if (icon != null) {
|
||||
delegate = icon;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current delegate for this GIcon. Note that this delegate can change when the
|
||||
* theme changes or is edited.
|
||||
* @return the current delegate icon for this GIcon.
|
||||
*/
|
||||
public Icon getDelegate() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id.hashCode();
|
||||
|
||||
@@ -217,43 +217,6 @@ public class GTheme extends GThemeValueMap {
|
||||
writer.writeThemeToFile(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves this theme to a new theme file.
|
||||
* @param outputFile the file to save to
|
||||
* @param includeDefaults if true, write all values to the theme file including default values.
|
||||
* Otherwise, just values that are not the default values are written to the file.
|
||||
* @return a new FileGTheme that represents the new file/theme
|
||||
* @throws IOException if an I/O error occurs writing the theme file
|
||||
*/
|
||||
public GTheme saveToFile(File outputFile, boolean includeDefaults) throws IOException {
|
||||
|
||||
GTheme fileTheme = new GTheme(outputFile, name, lookAndFeel, useDarkDefaults);
|
||||
if (includeDefaults) {
|
||||
fileTheme.load(Gui.getDefaults());
|
||||
}
|
||||
fileTheme.load(this);
|
||||
fileTheme.save();
|
||||
return fileTheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves this theme to a new theme file.
|
||||
* @param outputFile the file to save to
|
||||
* @param includeDefaults if true, write all values to the theme file including default values.
|
||||
* Otherwise, just values that are not the default values are written to the file.
|
||||
* @throws IOException if an I/O error occurs writing the theme file
|
||||
*/
|
||||
public void saveToZip(File outputFile, boolean includeDefaults) throws IOException {
|
||||
|
||||
GTheme theme = new GTheme(name, lookAndFeel, useDarkDefaults);
|
||||
if (includeDefaults) {
|
||||
theme.load(Gui.getDefaults());
|
||||
}
|
||||
theme.load(this);
|
||||
ThemeWriter writer = new ThemeWriter(theme);
|
||||
writer.writeThemeToZipFile(outputFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a theme from a file. The file can be either a theme file or a zip file containing
|
||||
* a theme file and optionally a set of icon files.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -247,8 +247,8 @@ public class IconValue extends ThemeValue<Icon> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installValue() {
|
||||
Gui.setIcon(this);
|
||||
public void installValue(ThemeManager themeManager) {
|
||||
themeManager.setIcon(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user