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 docking.action.*;
import generic.theme.Gui;
import generic.theme.ThemeManager;
import generic.theme.*;
import ghidra.util.*;
import ghidra.util.exception.AssertException;
import help.HelpDescriptor;
@ -117,6 +116,8 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
private String registeredFontId;
private ThemeListener themeListener = this::themeChanged;
/**
* Creates a new component provider with a default location of {@link WindowPosition#WINDOW}.
* @param tool The tool will manage and show this provider
@ -145,6 +146,8 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
this.contextType = contextType;
recordInception();
Gui.addThemeListener(themeListener);
}
/**
@ -171,6 +174,24 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
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
* @return the component to be displayed

View file

@ -32,7 +32,7 @@ import docking.event.mouse.GMouseListenerAdapter;
import docking.menu.DialogToolbarButton;
import docking.util.AnimationUtils;
import docking.widgets.label.GDHtmlLabel;
import generic.theme.GColor;
import generic.theme.*;
import generic.theme.GThemeDefaults.Colors.Messages;
import ghidra.util.*;
import ghidra.util.exception.AssertException;
@ -103,6 +103,7 @@ public class DialogComponentProvider
private boolean isTransient = false;
private Dimension defaultSize;
private ThemeListener themeListener = this::themeChanged;
/**
* Constructor for a DialogComponentProvider that will be modal and will include a status line and
@ -177,6 +178,8 @@ public class DialogComponentProvider
installEscapeAction();
doInitialize();
Gui.addThemeListener(themeListener);
}
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) {
if (comp instanceof CellRendererPane) {
return;
@ -888,6 +905,7 @@ public class DialogComponentProvider
}
public void dispose() {
Gui.removeThemeListener(themeListener);
cancelCurrentTask();
close();
popupManager.dispose();

View file

@ -495,6 +495,13 @@ public class GTable extends JTable {
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 preferredHeight = calculatePreferredRowHeight();
int newHeight = linesPerRow * preferredHeight;
@ -694,7 +701,7 @@ public class GTable extends JTable {
addColumn(newColumn);
}
for (int i = 0; i < columnCount; i++ ) {
for (int i = 0; i < columnCount; i++) {
TableCellRenderer headerRenderer = getHeaderRendererOverride(i);
if (headerRenderer != null) {
tableColumnModel.getColumn(i).setHeaderRenderer(headerRenderer);

View file

@ -28,8 +28,7 @@ import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
import docking.widgets.AbstractGCellRenderer;
import generic.theme.GColor;
import generic.theme.Gui;
import generic.theme.*;
import ghidra.docking.settings.*;
import ghidra.util.*;
import ghidra.util.exception.AssertException;
@ -53,6 +52,11 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe
private static DecimalFormat decimalFormat;
private static Map<Integer, DecimalFormat> decimalFormatCache;
private ThemeListener themeListener = e -> {
if (e.isLookAndFeelChanged()) {
updateUI();
}
};
/**
* Constructs a new GTableCellRenderer.
@ -60,11 +64,7 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe
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();
}
});
Gui.addThemeListener(themeListener);
}
/**

View file

@ -130,12 +130,12 @@ public class ApplicationThemeManager extends ThemeManager {
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);
}
themePreferences.save(theme);
}
currentValues.checkForUnresolvedReferences();
}
@ -192,12 +192,12 @@ public class ApplicationThemeManager extends ThemeManager {
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);
notifyThemeChanged(new FontChangedThemeEvent(currentValues, newValue));
}
@Override
@ -208,12 +208,8 @@ public class ApplicationThemeManager extends ThemeManager {
}
updateChangedValuesMap(currentValue, newValue);
currentValues.addColor(newValue);
lookAndFeelManager.colorsChanged();
notifyThemeChanged(new ColorChangedThemeEvent(currentValues, newValue));
// now update the ui
if (lookAndFeelManager != null) {
lookAndFeelManager.colorsChanged();
}
}
@Override
@ -225,7 +221,6 @@ public class ApplicationThemeManager extends ThemeManager {
updateChangedValuesMap(currentValue, newValue);
currentValues.addIcon(newValue);
notifyThemeChanged(new IconChangedThemeEvent(currentValues, newValue));
// now update the ui
// update all java LookAndFeel icons affected by this changed
@ -233,6 +228,7 @@ public class ApplicationThemeManager extends ThemeManager {
Set<String> changedIconIds = findChangedJavaIconIds(id);
Icon newIcon = newValue.get(currentValues);
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 resources.ResourceManager;
import utilities.util.reflection.ReflectionUtilities;
import utility.function.Callback;
/**
* This class manages application themes and their values. The ThemeManager is an abstract