Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Enhance utiLITI icon loading. #410

Open
nightm4re94 opened this issue Aug 2, 2021 · 0 comments
Open

Enhance utiLITI icon loading. #410

nightm4re94 opened this issue Aug 2, 2021 · 0 comments

Comments

@nightm4re94
Copy link
Member

nightm4re94 commented Aug 2, 2021

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 current AwareIconStyle which is managed by the IconLader. 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) the width and height 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) using

IconLoader.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 and EmptyIcon darklaf-property-loader needs to be included as a dependency.

# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

No branches or pull requests

1 participant