GP-2909 Fixing update issues when changing themes

This commit is contained in:
ghidragon 2022-12-01 18:15:29 -05:00
parent 1a6c9be8e3
commit c9670ed4ef
6 changed files with 62 additions and 19 deletions

View file

@ -22,8 +22,7 @@ import java.util.*;
import javax.swing.*; import javax.swing.*;
import docking.action.*; import docking.action.*;
import generic.theme.Gui; import generic.theme.*;
import generic.theme.ThemeManager;
import ghidra.util.*; import ghidra.util.*;
import ghidra.util.exception.AssertException; import ghidra.util.exception.AssertException;
import help.HelpDescriptor; import help.HelpDescriptor;
@ -117,6 +116,8 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
private String registeredFontId; private String registeredFontId;
private ThemeListener themeListener = this::themeChanged;
/** /**
* Creates a new component provider with a default location of {@link WindowPosition#WINDOW}. * Creates a new component provider with a default location of {@link WindowPosition#WINDOW}.
* @param tool The tool will manage and show this provider * @param tool The tool will manage and show this provider
@ -145,6 +146,8 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
this.contextType = contextType; this.contextType = contextType;
recordInception(); recordInception();
Gui.addThemeListener(themeListener);
} }
/** /**
@ -171,6 +174,24 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
showProviderAction = new ShowProviderAction(supportsKeyBindings); showProviderAction = new ShowProviderAction(supportsKeyBindings);
} }
private void themeChanged(ThemeEvent e) {
if (!e.isLookAndFeelChanged()) {
return; // we only care if the Look and Feel changes
}
if (isVisible()) {
// if we are visible, then we don't need to update as the system updates all
// visible components
return;
}
// update this providers components ui for the new Look and Feel
JComponent component = getComponent();
if (component != null) {
SwingUtilities.updateComponentTreeUI(component);
}
}
/** /**
* Returns the component to be displayed * Returns the component to be displayed
* @return the component to be displayed * @return the component to be displayed

View file

@ -32,7 +32,7 @@ import docking.event.mouse.GMouseListenerAdapter;
import docking.menu.DialogToolbarButton; import docking.menu.DialogToolbarButton;
import docking.util.AnimationUtils; import docking.util.AnimationUtils;
import docking.widgets.label.GDHtmlLabel; import docking.widgets.label.GDHtmlLabel;
import generic.theme.GColor; import generic.theme.*;
import generic.theme.GThemeDefaults.Colors.Messages; import generic.theme.GThemeDefaults.Colors.Messages;
import ghidra.util.*; import ghidra.util.*;
import ghidra.util.exception.AssertException; import ghidra.util.exception.AssertException;
@ -103,6 +103,7 @@ public class DialogComponentProvider
private boolean isTransient = false; private boolean isTransient = false;
private Dimension defaultSize; private Dimension defaultSize;
private ThemeListener themeListener = this::themeChanged;
/** /**
* Constructor for a DialogComponentProvider that will be modal and will include a status line and * Constructor for a DialogComponentProvider that will be modal and will include a status line and
@ -177,6 +178,8 @@ public class DialogComponentProvider
installEscapeAction(); installEscapeAction();
doInitialize(); doInitialize();
Gui.addThemeListener(themeListener);
} }
private void installEscapeAction() { private void installEscapeAction() {
@ -341,6 +344,20 @@ public class DialogComponentProvider
} }
} }
private void themeChanged(ThemeEvent ev) {
if (!ev.isLookAndFeelChanged()) {
return; // we only care if the Look and Feel changes
}
// if we are visible, then we don't need to update as the system updates all
// visible components
if (isVisible()) {
return;
}
Component component = dialog != null ? dialog : rootPanel;
SwingUtilities.updateComponentTreeUI(component);
}
private void uninstallMouseListener(Component comp) { private void uninstallMouseListener(Component comp) {
if (comp instanceof CellRendererPane) { if (comp instanceof CellRendererPane) {
return; return;
@ -888,6 +905,7 @@ public class DialogComponentProvider
} }
public void dispose() { public void dispose() {
Gui.removeThemeListener(themeListener);
cancelCurrentTask(); cancelCurrentTask();
close(); close();
popupManager.dispose(); popupManager.dispose();

View file

@ -495,6 +495,13 @@ public class GTable extends JTable {
return; // must be initializing return; // must be initializing
} }
// don't try to update if we are not in window hierarchy
// as this will cause look and feel issues
Window window = SwingUtilities.windowForComponent(this);
if (window == null) {
return;
}
int linesPerRow = getLinesPerRow(); int linesPerRow = getLinesPerRow();
int preferredHeight = calculatePreferredRowHeight(); int preferredHeight = calculatePreferredRowHeight();
int newHeight = linesPerRow * preferredHeight; int newHeight = linesPerRow * preferredHeight;

View file

@ -28,8 +28,7 @@ import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel; import javax.swing.table.TableModel;
import docking.widgets.AbstractGCellRenderer; import docking.widgets.AbstractGCellRenderer;
import generic.theme.GColor; import generic.theme.*;
import generic.theme.Gui;
import ghidra.docking.settings.*; import ghidra.docking.settings.*;
import ghidra.util.*; import ghidra.util.*;
import ghidra.util.exception.AssertException; import ghidra.util.exception.AssertException;
@ -53,6 +52,11 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe
private static DecimalFormat decimalFormat; private static DecimalFormat decimalFormat;
private static Map<Integer, DecimalFormat> decimalFormatCache; private static Map<Integer, DecimalFormat> decimalFormatCache;
private ThemeListener themeListener = e -> {
if (e.isLookAndFeelChanged()) {
updateUI();
}
};
/** /**
* Constructs a new GTableCellRenderer. * Constructs a new GTableCellRenderer.
@ -60,11 +64,7 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe
public GTableCellRenderer() { public GTableCellRenderer() {
// When the Look And Feel changes, renderers are not auto updated because they // 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. // are not part of the component tree. So listen for a change to the Look And Feel.
Gui.addThemeListener(e -> { Gui.addThemeListener(themeListener);
if (e.isLookAndFeelChanged()) {
updateUI();
}
});
} }
/** /**

View file

@ -130,12 +130,12 @@ public class ApplicationThemeManager extends ThemeManager {
lookAndFeelManager = lafType.getLookAndFeelManager(this); lookAndFeelManager = lafType.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 LookAndFeel: " + lafType.getName(), e); Msg.error(this, "Error setting LookAndFeel: " + lafType.getName(), e);
} }
themePreferences.save(theme);
} }
currentValues.checkForUnresolvedReferences(); currentValues.checkForUnresolvedReferences();
} }
@ -192,12 +192,12 @@ public class ApplicationThemeManager extends ThemeManager {
updateChangedValuesMap(currentValue, newValue); updateChangedValuesMap(currentValue, newValue);
currentValues.addFont(newValue); currentValues.addFont(newValue);
notifyThemeChanged(new FontChangedThemeEvent(currentValues, 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));
} }
@Override @Override
@ -208,12 +208,8 @@ public class ApplicationThemeManager extends ThemeManager {
} }
updateChangedValuesMap(currentValue, newValue); updateChangedValuesMap(currentValue, newValue);
currentValues.addColor(newValue); currentValues.addColor(newValue);
notifyThemeChanged(new ColorChangedThemeEvent(currentValues, newValue));
// now update the ui
if (lookAndFeelManager != null) {
lookAndFeelManager.colorsChanged(); lookAndFeelManager.colorsChanged();
} notifyThemeChanged(new ColorChangedThemeEvent(currentValues, newValue));
} }
@Override @Override
@ -225,7 +221,6 @@ public class ApplicationThemeManager extends ThemeManager {
updateChangedValuesMap(currentValue, newValue); updateChangedValuesMap(currentValue, newValue);
currentValues.addIcon(newValue); currentValues.addIcon(newValue);
notifyThemeChanged(new IconChangedThemeEvent(currentValues, newValue));
// now update the ui // now update the ui
// update all java LookAndFeel icons affected by this changed // update all java LookAndFeel icons affected by this changed
@ -233,6 +228,7 @@ public class ApplicationThemeManager extends ThemeManager {
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));
} }
/** /**

View file

@ -30,6 +30,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