Fixed excessive warnings when switching themes

This commit is contained in:
dragonmacher 2024-02-27 17:41:14 -05:00
parent 23d471731e
commit 86d2bb4dff
5 changed files with 112 additions and 48 deletions

View file

@ -146,20 +146,29 @@ public abstract class AbstractGCellRenderer extends GDHtmlLabel {
public void setFont(Font f) { public void setFont(Font f) {
super.setFont(f); super.setFont(f);
checkForInvalidSetFont(f);
}
private void checkForInvalidSetFont(Font f) {
// //
// Due to the nature of how setFont() is typically used (external client setup vs internal // Due to the nature of how setFont() is typically used (external client setup vs internal
// rendering), we created setBaseFontId() to allow external clients to set the base font in // rendering), we created setBaseFontId() to allow external clients to set the base font in
// a way that is consistent with theming. Ignore any request to use one of our existing // a way that is consistent with theming. Ignore any request to use one of our existing
// fonts, as some clients may do that from the getTableCellRendererComponent() method. // fonts, as some clients may do that from the getTableCellRendererComponent() method.
// //
if (defaultFont != null && if (defaultFont == null ||
!CollectionUtils.isOneOf(f, defaultFont, fixedWidthFont, boldFont)) { CollectionUtils.isOneOf(f, defaultFont, fixedWidthFont, boldFont)) {
return;
String caller =
ReflectionUtilities.getClassNameOlderThan(getClass().getName(), "generic.theme");
Msg.debug(this, "Calling setFont() on the renderer is discouraged. " +
"To change the font, call setBaseFontId(). Called from " + caller);
} }
if (Gui.isUpdatingTheme()) {
return; // the UI will set fonts while the theme is updating
}
String caller = ReflectionUtilities
.getClassNameOlderThan(AbstractGCellRenderer.class.getName(), "generic.theme");
Msg.debug(this, "Calling setFont() on the renderer is discouraged. " +
"To change the font, call setBaseFontId(). Called from " + caller);
} }
/** /**

View file

@ -73,10 +73,12 @@ public class ApplicationThemeManager extends ThemeManager {
@Override @Override
public void restoreThemeValues() { public void restoreThemeValues() {
applicationDefaults = loadApplicationDefaults(); update(() -> {
buildCurrentValues(); applicationDefaults = loadApplicationDefaults();
lookAndFeelManager.resetAll(javaDefaults); buildCurrentValues();
notifyThemeChanged(new AllValuesChangedThemeEvent(false)); lookAndFeelManager.resetAll(javaDefaults);
notifyThemeChanged(new AllValuesChangedThemeEvent(false));
});
} }
@Override @Override
@ -117,22 +119,30 @@ public class ApplicationThemeManager extends ThemeManager {
@Override @Override
public void setTheme(GTheme theme) { public void setTheme(GTheme theme) {
if (theme.hasSupportedLookAndFeel()) { if (!theme.hasSupportedLookAndFeel()) {
Msg.error(this,
"Attempted to set theme with an unsupported Look and Feel: " + theme.getName());
return;
}
update(() -> {
activeTheme = theme; activeTheme = theme;
activeLafType = theme.getLookAndFeelType(); activeLafType = theme.getLookAndFeelType();
useDarkDefaults = theme.useDarkDefaults(); useDarkDefaults = theme.useDarkDefaults();
cleanUiDefaults(); // clear out any values previous themes may have installed cleanUiDefaults(); // clear out any values previous themes may have installed
lookAndFeelManager = activeLafType.getLookAndFeelManager(this); lookAndFeelManager = activeLafType.getLookAndFeelManager(this);
try { try {
lookAndFeelManager.installLookAndFeel(); lookAndFeelManager.installLookAndFeel();
themePreferences.save(theme);
notifyThemeChanged(new AllValuesChangedThemeEvent(true)); notifyThemeChanged(new AllValuesChangedThemeEvent(true));
} }
catch (Exception e) { catch (Exception e) {
Msg.error(this, "Error setting Look and Feel: " + activeLafType.getName(), e); Msg.error(this, "Error setting Look and Feel: " + activeLafType.getName(), e);
} }
themePreferences.save(theme); });
}
currentValues.checkForUnresolvedReferences(); currentValues.checkForUnresolvedReferences();
} }
@ -146,15 +156,18 @@ public class ApplicationThemeManager extends ThemeManager {
this.activeLafType = lafType; this.activeLafType = lafType;
this.useDarkDefaults = useDarkDefaults; this.useDarkDefaults = useDarkDefaults;
cleanUiDefaults(); update(() -> {
lookAndFeelManager = lafType.getLookAndFeelManager(this);
try { cleanUiDefaults(); // clear out any values previous themes may have installed
lookAndFeelManager.installLookAndFeel(); lookAndFeelManager = lafType.getLookAndFeelManager(this);
notifyThemeChanged(new AllValuesChangedThemeEvent(true)); try {
} lookAndFeelManager.installLookAndFeel();
catch (Exception e) { notifyThemeChanged(new AllValuesChangedThemeEvent(true));
Msg.error(this, "Error setting Look and Feel: " + lafType.getName(), e); }
} catch (Exception e) {
Msg.error(this, "Error setting Look and Feel: " + lafType.getName(), e);
}
});
} }
@Override @Override
@ -207,15 +220,17 @@ public class ApplicationThemeManager extends ThemeManager {
if (newValue.equals(currentValue)) { if (newValue.equals(currentValue)) {
return; return;
} }
updateChangedValuesMap(currentValue, newValue);
currentValues.addFont(newValue); update(() -> {
updateChangedValuesMap(currentValue, newValue);
currentValues.addFont(newValue);
// update all java LookAndFeel fonts affected by this changed // update all java LookAndFeel fonts affected by this changed
String id = newValue.getId(); String id = newValue.getId();
Set<String> changedFontIds = findChangedJavaFontIds(id); Set<String> changedFontIds = findChangedJavaFontIds(id);
lookAndFeelManager.fontsChanged(changedFontIds); lookAndFeelManager.fontsChanged(changedFontIds);
notifyThemeChanged(new FontChangedThemeEvent(currentValues, newValue)); notifyThemeChanged(new FontChangedThemeEvent(currentValues, newValue));
});
} }
@Override @Override
@ -224,10 +239,13 @@ public class ApplicationThemeManager extends ThemeManager {
if (newValue.equals(currentValue)) { if (newValue.equals(currentValue)) {
return; return;
} }
updateChangedValuesMap(currentValue, newValue);
currentValues.addColor(newValue); update(() -> {
notifyThemeChanged(new ColorChangedThemeEvent(currentValues, newValue)); updateChangedValuesMap(currentValue, newValue);
lookAndFeelManager.colorsChanged(); currentValues.addColor(newValue);
notifyThemeChanged(new ColorChangedThemeEvent(currentValues, newValue));
lookAndFeelManager.colorsChanged();
});
} }
@Override @Override
@ -236,17 +254,18 @@ public class ApplicationThemeManager extends ThemeManager {
if (newValue.equals(currentValue)) { if (newValue.equals(currentValue)) {
return; return;
} }
updateChangedValuesMap(currentValue, newValue);
currentValues.addIcon(newValue); update(() -> {
updateChangedValuesMap(currentValue, newValue);
currentValues.addIcon(newValue);
// now update the ui // update all java LookAndFeel icons affected by this changed
// update all java LookAndFeel icons affected by this changed String id = newValue.getId();
String id = newValue.getId(); Set<String> changedIconIds = findChangedJavaIconIds(id);
Set<String> changedIconIds = findChangedJavaIconIds(id); Icon newIcon = newValue.get(currentValues);
Icon newIcon = newValue.get(currentValues); lookAndFeelManager.iconsChanged(changedIconIds, newIcon);
lookAndFeelManager.iconsChanged(changedIconIds, newIcon); notifyThemeChanged(new IconChangedThemeEvent(currentValues, newValue));
notifyThemeChanged(new IconChangedThemeEvent(currentValues, newValue)); });
} }
/** /**

View file

@ -198,6 +198,14 @@ public class Gui {
return themeManager.isDarkTheme(); return themeManager.isDarkTheme();
} }
/**
* Returns true if the theme system is in the process of updating
* @return true if the theme system is in the process of updating
*/
public static boolean isUpdatingTheme() {
return themeManager.isUpdatingTheme();
}
/** /**
* Returns true if the given id is a system-defined id, such as those starting with * Returns true if the given id is a system-defined id, such as those starting with
* {@code laf.color} or {@code system.color}. * {@code laf.color} or {@code system.color}.

View file

@ -31,6 +31,7 @@ import ghidra.util.datastruct.WeakDataStructureFactory;
import ghidra.util.datastruct.WeakSet; import ghidra.util.datastruct.WeakSet;
import resources.ResourceManager; import resources.ResourceManager;
import utilities.util.reflection.ReflectionUtilities; import utilities.util.reflection.ReflectionUtilities;
import utility.function.Callback;
/** /**
* This class manages application themes and their values. The ThemeManager is an abstract * This class manages application themes and their values. The ThemeManager is an abstract
@ -81,6 +82,8 @@ public abstract class ThemeManager {
private WeakSet<ThemeListener> themeListeners = private WeakSet<ThemeListener> themeListeners =
WeakDataStructureFactory.createCopyOnReadWeakSet(); WeakDataStructureFactory.createCopyOnReadWeakSet();
private boolean isUpdating;
public static ThemeManager getInstance() { public static ThemeManager getInstance() {
return INSTANCE; return INSTANCE;
} }
@ -616,6 +619,24 @@ public abstract class ThemeManager {
} }
} }
/**
* Returns true if the theme system is in the process of updating
* @return true if the theme system is in the process of updating
*/
public boolean isUpdatingTheme() {
return isUpdating;
}
protected void update(Callback callback) {
isUpdating = true;
try {
callback.call();
}
finally {
isUpdating = false;
}
}
protected void notifyThemeChanged(ThemeEvent event) { protected void notifyThemeChanged(ThemeEvent event) {
for (ThemeListener listener : themeListeners) { for (ThemeListener listener : themeListeners) {
listener.themeChanged(event); listener.themeChanged(event);

View file

@ -236,11 +236,9 @@ public class ReflectionUtilities {
StackTraceElement[] trace = t.getStackTrace(); StackTraceElement[] trace = t.getStackTrace();
int lastIgnoreIndex = -1; int lastIgnoreIndex = -1;
for (int i = 0; i < trace.length; i++) { for (int i = 0; i < trace.length; i++) {
StackTraceElement element = trace[i]; StackTraceElement element = trace[i];
String className = element.getClassName(); String text = element.getClassName() + " " + element.getMethodName();
int nameIndex = patterns.indexOf(className); if (containsAny(text, patterns)) {
if (nameIndex != -1) {
lastIgnoreIndex = i; lastIgnoreIndex = i;
} }
else { else {
@ -269,6 +267,15 @@ public class ReflectionUtilities {
return t; return t;
} }
private static boolean containsAny(String text, List<String> patterns) {
for (String pattern : patterns) {
if (text.contains(pattern)) {
return true;
}
}
return false;
}
/** /**
* Creates a throwable whose stack trace is based upon the current call stack, with any * Creates a throwable whose stack trace is based upon the current call stack, with any
* information coming before, and including, the given classes removed. * information coming before, and including, the given classes removed.