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) {
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
// rendering), we created setBaseFontId() to allow external clients to set the base font in
// a way that is consistent with theming. Ignore any request to use one of our existing
// fonts, as some clients may do that from the getTableCellRendererComponent() method.
//
if (defaultFont != null &&
!CollectionUtils.isOneOf(f, defaultFont, fixedWidthFont, boldFont)) {
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 (defaultFont == null ||
CollectionUtils.isOneOf(f, defaultFont, fixedWidthFont, boldFont)) {
return;
}
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
public void restoreThemeValues() {
applicationDefaults = loadApplicationDefaults();
buildCurrentValues();
lookAndFeelManager.resetAll(javaDefaults);
notifyThemeChanged(new AllValuesChangedThemeEvent(false));
update(() -> {
applicationDefaults = loadApplicationDefaults();
buildCurrentValues();
lookAndFeelManager.resetAll(javaDefaults);
notifyThemeChanged(new AllValuesChangedThemeEvent(false));
});
}
@Override
@ -117,22 +119,30 @@ public class ApplicationThemeManager extends ThemeManager {
@Override
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;
activeLafType = theme.getLookAndFeelType();
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);
try {
lookAndFeelManager.installLookAndFeel();
themePreferences.save(theme);
notifyThemeChanged(new AllValuesChangedThemeEvent(true));
}
catch (Exception e) {
Msg.error(this, "Error setting Look and Feel: " + activeLafType.getName(), e);
}
themePreferences.save(theme);
}
});
currentValues.checkForUnresolvedReferences();
}
@ -146,15 +156,18 @@ public class ApplicationThemeManager extends ThemeManager {
this.activeLafType = lafType;
this.useDarkDefaults = useDarkDefaults;
cleanUiDefaults();
lookAndFeelManager = lafType.getLookAndFeelManager(this);
try {
lookAndFeelManager.installLookAndFeel();
notifyThemeChanged(new AllValuesChangedThemeEvent(true));
}
catch (Exception e) {
Msg.error(this, "Error setting Look and Feel: " + lafType.getName(), e);
}
update(() -> {
cleanUiDefaults(); // clear out any values previous themes may have installed
lookAndFeelManager = lafType.getLookAndFeelManager(this);
try {
lookAndFeelManager.installLookAndFeel();
notifyThemeChanged(new AllValuesChangedThemeEvent(true));
}
catch (Exception e) {
Msg.error(this, "Error setting Look and Feel: " + lafType.getName(), e);
}
});
}
@Override
@ -207,15 +220,17 @@ public class ApplicationThemeManager extends ThemeManager {
if (newValue.equals(currentValue)) {
return;
}
updateChangedValuesMap(currentValue, newValue);
currentValues.addFont(newValue);
update(() -> {
updateChangedValuesMap(currentValue, newValue);
currentValues.addFont(newValue);
// update all java LookAndFeel fonts affected by this changed
String id = newValue.getId();
Set<String> changedFontIds = findChangedJavaFontIds(id);
lookAndFeelManager.fontsChanged(changedFontIds);
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);
notifyThemeChanged(new FontChangedThemeEvent(currentValues, newValue));
});
}
@Override
@ -224,10 +239,13 @@ public class ApplicationThemeManager extends ThemeManager {
if (newValue.equals(currentValue)) {
return;
}
updateChangedValuesMap(currentValue, newValue);
currentValues.addColor(newValue);
notifyThemeChanged(new ColorChangedThemeEvent(currentValues, newValue));
lookAndFeelManager.colorsChanged();
update(() -> {
updateChangedValuesMap(currentValue, newValue);
currentValues.addColor(newValue);
notifyThemeChanged(new ColorChangedThemeEvent(currentValues, newValue));
lookAndFeelManager.colorsChanged();
});
}
@Override
@ -236,17 +254,18 @@ public class ApplicationThemeManager extends ThemeManager {
if (newValue.equals(currentValue)) {
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
String id = newValue.getId();
Set<String> changedIconIds = findChangedJavaIconIds(id);
Icon newIcon = newValue.get(currentValues);
lookAndFeelManager.iconsChanged(changedIconIds, newIcon);
notifyThemeChanged(new IconChangedThemeEvent(currentValues, newValue));
// 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);
notifyThemeChanged(new IconChangedThemeEvent(currentValues, newValue));
});
}
/**

View file

@ -198,6 +198,14 @@ public class Gui {
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
* {@code laf.color} or {@code system.color}.

View file

@ -31,6 +31,7 @@ import ghidra.util.datastruct.WeakDataStructureFactory;
import ghidra.util.datastruct.WeakSet;
import resources.ResourceManager;
import utilities.util.reflection.ReflectionUtilities;
import utility.function.Callback;
/**
* 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 =
WeakDataStructureFactory.createCopyOnReadWeakSet();
private boolean isUpdating;
public static ThemeManager getInstance() {
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) {
for (ThemeListener listener : themeListeners) {
listener.themeChanged(event);

View file

@ -236,11 +236,9 @@ public class ReflectionUtilities {
StackTraceElement[] trace = t.getStackTrace();
int lastIgnoreIndex = -1;
for (int i = 0; i < trace.length; i++) {
StackTraceElement element = trace[i];
String className = element.getClassName();
int nameIndex = patterns.indexOf(className);
if (nameIndex != -1) {
String text = element.getClassName() + " " + element.getMethodName();
if (containsAny(text, patterns)) {
lastIgnoreIndex = i;
}
else {
@ -269,6 +267,15 @@ public class ReflectionUtilities {
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
* information coming before, and including, the given classes removed.