Description
We should implement the official darklaf-compliant icon loading procedure for utiLITI.
In this discussion, Jannis has suggested a better way to load our icons for different themes:
From what I can see you only differentiate between light and dark icons (correct me if I am wrong here). In this case there is a simple mechanism build into darklaf to handle different icons. Here are some possible approaches:
* Using the `IconLoader`: For this you will need change up your folder structure as light/dark resource paths are handled differently in darklaf. Instead of using a suffix a folder prefix is used, so `some/path/icon_dark.png` and `some/path/icon_light.png` become `dark/some/path/icon.png` and `light/some/path/icon.png`. ```java Icon icon = IconLoader.get(resourceClass).getUIAwareIcon(path, width, height); // Here resourceClass is the class to which the icons will be resolved. In your case this can be null or simply IconLoader.get() with no argument. // The path is relative to the light/, dark/ folders. ``` * Using `DarkUIAwareIcon`: This is basically the implementation used by the `IconLoader` but you have more control over the resource path. ```java Icon icon = new DarkUIAwareIcon(dark_icon_path, light_icon_path, resourceClass, width, height); // Again resourceClass can be null in your case ```
DarkUIAwareIcon
holds a reference the the currentAwareIconStyle
which is managed by theIconLader
. When a darklaf theme is loaded it sets this key appropriately. Both versions above the icons will be loaded lazily as needed. As long as you load.png
files (or any other image based file) thewidth
andheight
parameters will actually have no effect as they are only a suggestion.If you want to be independent of darklaf in terms of when which icon is used you can (with the next release of darklaf) subclass
DarkUIAwareIcon
:public class CustomAwareIcon extends DarkUIAwareIcon { private Theme theme: public CustomAwareIcon(...) { super(....); theme = null; } @Override protected void updateStyle() { theme = Editor.preferences().getTheme(); } @Override protected boolean isLoaded() { return theme == Editor.preferences().getTheme(); } @Override public boolean isDark() { return theme == Theme.DARK; } }Generally the
IconLoader
will cache already loaded icons to avoid reloading them. This can be changed (int the next darklaf release) usingIconLoader.get().setCacheEnabled(false); // Caching is toggled on a per IconLoader basis. for your case this would be the default loader.Alternatively here is a darklaf independent implementation (without caching):
public class AwareIcon implements Icon { private final String identifier; private Icon icon; private Theme theme; public AwareIcon(final String identifier) { this.identifier = identifier; } private boolean isLoaded() { return icon != null && theme == Editor.preferences().getTheme(); } private void ensureLoaded() { if (!isLoaded()) { loadIcon(); } } private void loadIcon() { theme = Editor.preferences().getTheme(); try { icon = new ImageIcon(Resources.images().get(String.format("%s_%s.png", identifier, theme.name().toLowerCase()))); } catch (ResourceLoadException rle1) { icon = EmptyIcon.create(0); // This is a class in darklaf. Icon stub that doesn't paint anything and is of size 0. } } @Override public void paintIcon(final Component c, final Graphics g, final int x, final int y) { ensureLoaded(); icon.paintIcon(c, g, x, y); } @Override public int getIconWidth() { ensureLoaded(); return icon.getIconWidth(); } @Override public int getIconHeight() { ensureLoaded(); return icon.getIconHeight(); } }I would advocate against deciding whether an icon has a light/dark variant based on whether the resource could be loaded. It should be made explicit.
Note: To use
IconLoader
,DarkUIAwareIcon
andEmptyIcon
darklaf-property-loader
needs to be included as a dependency.