Browse Source

Delay uri loading to icon resolve time.

Make IamgeIcon implementation derivable and lazily loaded.
pull/188/head
weisj 5 years ago
parent
commit
403e1a93f8
  1. 31
      property-loader/src/main/java/com/github/weisj/darklaf/icons/AbstractLazyIconSupplier.java
  2. 10
      property-loader/src/main/java/com/github/weisj/darklaf/icons/CustomThemedIcon.java
  3. 30
      property-loader/src/main/java/com/github/weisj/darklaf/icons/DarkSVGIcon.java
  4. 395
      property-loader/src/main/java/com/github/weisj/darklaf/icons/DerivableImageIcon.java
  5. 92
      property-loader/src/main/java/com/github/weisj/darklaf/icons/IconLoader.java
  6. 14
      property-loader/src/main/java/com/github/weisj/darklaf/icons/IconSupplier.java
  7. 50
      property-loader/src/main/java/com/github/weisj/darklaf/icons/LazyImageIconSupplier.java
  8. 6
      property-loader/src/main/java/com/github/weisj/darklaf/icons/ThemedSVGIcon.java

31
property-loader/src/main/java/com/github/weisj/darklaf/icons/LazyIcon.java → property-loader/src/main/java/com/github/weisj/darklaf/icons/AbstractLazyIconSupplier.java

@ -24,38 +24,27 @@
*/ */
package com.github.weisj.darklaf.icons; package com.github.weisj.darklaf.icons;
import java.awt.*;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.swing.*; import javax.swing.*;
import javax.swing.plaf.UIResource;
import com.github.weisj.darklaf.util.LogUtil; import com.github.weisj.darklaf.util.LogUtil;
/** public abstract class AbstractLazyIconSupplier<T extends Icon> implements IconSupplier<T> {
* @author Jannis Weis
*/
public abstract class LazyIcon implements Icon, UIResource {
private static final Logger LOGGER = LogUtil.getLogger(LazyIcon.class); private static final Logger LOGGER = LogUtil.getLogger(AbstractLazyIconSupplier.class);
protected final String path; protected final String path;
protected final IconLoader.IconKey key; protected final IconLoader.IconKey key;
protected final Class<?> parentClass; protected final Class<?> parentClass;
private boolean loaded; private boolean loaded;
private Icon icon; private T icon;
public LazyIcon(final String path, final IconLoader.IconKey key, final Class<?> parentClass) { public AbstractLazyIconSupplier(final String path, final IconLoader.IconKey key, final Class<?> parentClass) {
this.path = path; this.path = path;
this.key = key; this.key = key;
this.parentClass = parentClass; this.parentClass = parentClass;
} }
@Override
public void paintIcon(final Component c, final Graphics g, final int x, final int y) {
ensureLoaded();
icon.paintIcon(c, g, x, y);
}
private void ensureLoaded() { private void ensureLoaded() {
if (!loaded) { if (!loaded) {
LOGGER.fine(() -> "Loading icon '" + path + "'. Resolving from " + parentClass); LOGGER.fine(() -> "Loading icon '" + path + "'. Resolving from " + parentClass);
@ -69,17 +58,11 @@ public abstract class LazyIcon implements Icon, UIResource {
} }
} }
protected abstract Icon loadIcon(); protected abstract T loadIcon();
@Override
public int getIconWidth() {
ensureLoaded();
return icon.getIconWidth();
}
@Override @Override
public int getIconHeight() { public T getIcon() {
ensureLoaded(); ensureLoaded();
return icon.getIconHeight(); return icon;
} }
} }

10
property-loader/src/main/java/com/github/weisj/darklaf/icons/CustomThemedIcon.java

@ -26,6 +26,7 @@ package com.github.weisj.darklaf.icons;
import java.net.URI; import java.net.URI;
import java.util.Map; import java.util.Map;
import java.util.function.Supplier;
import javax.swing.*; import javax.swing.*;
@ -36,6 +37,15 @@ public class CustomThemedIcon extends ThemedSVGIcon {
private final UIDefaults defaults; private final UIDefaults defaults;
public CustomThemedIcon(final Supplier<URI> uriSupplier, final int displayWidth, final int displayHeight,
final Map<Object, Object> colors) {
super(uriSupplier, displayWidth, displayHeight);
defaults = new UIDefaults(colors.size(), 1f);
for (Map.Entry<Object, Object> entry : colors.entrySet()) {
defaults.put(entry.getKey(), entry.getValue());
}
}
public CustomThemedIcon(final URI uri, final int displayWidth, final int displayHeight, public CustomThemedIcon(final URI uri, final int displayWidth, final int displayHeight,
final Map<Object, Object> colors) { final Map<Object, Object> colors) {
super(uri, displayWidth, displayHeight); super(uri, displayWidth, displayHeight);

30
property-loader/src/main/java/com/github/weisj/darklaf/icons/DarkSVGIcon.java

@ -29,6 +29,7 @@ import java.awt.geom.AffineTransform;
import java.io.Serializable; import java.io.Serializable;
import java.net.URI; import java.net.URI;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;
import java.util.logging.Logger; import java.util.logging.Logger;
import com.github.weisj.darklaf.util.LogUtil; import com.github.weisj.darklaf.util.LogUtil;
@ -54,16 +55,35 @@ public class DarkSVGIcon implements DerivableIcon<DarkSVGIcon>, RotateIcon, Seri
*/ */
private static final double extraScale = 1.5; private static final double extraScale = 1.5;
private final AtomicBoolean loaded;
private final Dimension size; private final Dimension size;
private final SVGIcon icon; private final SVGIcon icon;
private final URI uri;
private final AtomicBoolean loaded; private Supplier<URI> uriSupplier;
private URI uri;
private boolean loadedWithExtraScale; private boolean loadedWithExtraScale;
private double scaleX; private double scaleX;
private double scaleY; private double scaleY;
private Image image; private Image image;
/**
* Method to fetch the SVG icon from a url.
*
* @param uriSupplier supplier for the uri from which to fetch the SVG icon.
* @param displayWidth display width of icon.
* @param displayHeight display height of icon.
*/
public DarkSVGIcon(final Supplier<URI> uriSupplier, final int displayWidth, final int displayHeight) {
this.uri = null;
this.uriSupplier = uriSupplier;
size = new Dimension(displayWidth, displayHeight);
icon = createSVGIcon();
icon.setAutosize(SVGIcon.AUTOSIZE_STRETCH);
icon.setAntiAlias(true);
loaded = new AtomicBoolean(false);
}
/** /**
* Method to fetch the SVG icon from a url. * Method to fetch the SVG icon from a url.
* *
@ -73,6 +93,7 @@ public class DarkSVGIcon implements DerivableIcon<DarkSVGIcon>, RotateIcon, Seri
*/ */
public DarkSVGIcon(final URI uri, final int displayWidth, final int displayHeight) { public DarkSVGIcon(final URI uri, final int displayWidth, final int displayHeight) {
this.uri = uri; this.uri = uri;
uriSupplier = null;
size = new Dimension(displayWidth, displayHeight); size = new Dimension(displayWidth, displayHeight);
icon = createSVGIcon(); icon = createSVGIcon();
icon.setAutosize(SVGIcon.AUTOSIZE_STRETCH); icon.setAutosize(SVGIcon.AUTOSIZE_STRETCH);
@ -84,6 +105,7 @@ public class DarkSVGIcon implements DerivableIcon<DarkSVGIcon>, RotateIcon, Seri
this.size = new Dimension(width, height); this.size = new Dimension(width, height);
this.icon = icon.icon; this.icon = icon.icon;
this.uri = icon.uri; this.uri = icon.uri;
this.uriSupplier = icon.uriSupplier;
this.loaded = icon.loaded; this.loaded = icon.loaded;
} }
@ -107,6 +129,10 @@ public class DarkSVGIcon implements DerivableIcon<DarkSVGIcon>, RotateIcon, Seri
private boolean ensureSVGLoaded() { private boolean ensureSVGLoaded() {
if (!loaded.get()) { if (!loaded.get()) {
if (uri == null && uriSupplier != null) {
uri = uriSupplier.get();
uriSupplier = null;
}
LOGGER.fine(() -> "Loading icon '" + uri.toASCIIString() + "'."); LOGGER.fine(() -> "Loading icon '" + uri.toASCIIString() + "'.");
icon.setSvgURI(uri); icon.setSvgURI(uri);
loaded.set(true); loaded.set(true);

395
property-loader/src/main/java/com/github/weisj/darklaf/icons/DerivableImageIcon.java

@ -0,0 +1,395 @@
/*
* MIT License
*
* Copyright (c) 2020 Jannis Weis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package com.github.weisj.darklaf.icons;
import java.awt.*;
import java.net.URL;
import java.util.Locale;
import java.util.function.Supplier;
import javax.accessibility.*;
import javax.swing.*;
public class DerivableImageIcon implements DerivableIcon<DerivableImageIcon>, Accessible {
private static final int DEFAULT_SCALING_MODE = Image.SCALE_SMOOTH;
private final int scalingMode;
private int width;
private int height;
private Supplier<Image> imageSupplier;
private Image original;
private Image img;
private String description;
private AccessibleContext accessibleContext;
/**
* Create a new derivable image icon.
*
* @param imagePath the image path.
*/
public DerivableImageIcon(final String imagePath) {
this(() -> Toolkit.getDefaultToolkit().getImage(imagePath), -1, -1);
}
/**
* Create a new derivable image icon.
*
* @param imagePath the image path.
* @param width the icon width.
* @param height the icon height.
*/
public DerivableImageIcon(final String imagePath, final int width, final int height) {
this(imagePath, width, height, DEFAULT_SCALING_MODE);
}
/**
* Create a new derivable image icon.
*
* @param imagePath the image path.
* @param width the icon width.
* @param height the icon height.
* @param scalingMode One of {@link Image#SCALE_DEFAULT}, {@link Image#SCALE_FAST}, {@link Image#SCALE_REPLICATE},
* {@link Image#SCALE_AREA_AVERAGING}, {@link Image#SCALE_SMOOTH}
*/
public DerivableImageIcon(final String imagePath, final int width, final int height, final int scalingMode) {
this(() -> Toolkit.getDefaultToolkit().getImage(imagePath), width, height, scalingMode);
}
/**
* Create a new derivable image icon.
*
* @param url the url to load the image from.
*/
public DerivableImageIcon(final URL url) {
this(url, -1, -1, DEFAULT_SCALING_MODE);
}
/**
* Create a new derivable image icon.
*
* @param url the url to load the image from.
* @param width the icon width.
* @param height the icon height.
*/
public DerivableImageIcon(final URL url, final int width, final int height) {
this(url, width, height, DEFAULT_SCALING_MODE);
}
/**
* Create a new derivable image icon.
*
* @param url the url to load the image from.
* @param width the icon width.
* @param height the icon height.
* @param scalingMode One of {@link Image#SCALE_DEFAULT}, {@link Image#SCALE_FAST}, {@link Image#SCALE_REPLICATE},
* {@link Image#SCALE_AREA_AVERAGING}, {@link Image#SCALE_SMOOTH}
*/
public DerivableImageIcon(final URL url, final int width, final int height, final int scalingMode) {
this(() -> Toolkit.getDefaultToolkit().getImage(url), width, height, scalingMode);
}
public DerivableImageIcon(final Supplier<Image> imageSupplier) {
this(imageSupplier, -1, -1, DEFAULT_SCALING_MODE);
}
public DerivableImageIcon(final Supplier<Image> imageSupplier, final int width, final int height) {
this(imageSupplier, width, height, DEFAULT_SCALING_MODE);
}
public DerivableImageIcon(final Supplier<Image> imageSupplier, final int width, final int height,
final int scalingMode) {
this.width = width;
this.height = height;
this.scalingMode = scalingMode;
this.imageSupplier = imageSupplier;
}
/**
* Create a new derivable image icon.
*
* @param icon the source image icon.
*/
public DerivableImageIcon(final ImageIcon icon) {
this(icon, DEFAULT_SCALING_MODE);
}
/**
* Create a new derivable image icon with specified scalingMode.
*
* @param icon the source icon.
* @param scalingMode One of {@link Image#SCALE_DEFAULT}, {@link Image#SCALE_FAST}, {@link Image#SCALE_REPLICATE},
* {@link Image#SCALE_AREA_AVERAGING}, {@link Image#SCALE_SMOOTH}
*/
public DerivableImageIcon(final ImageIcon icon, final int scalingMode) {
this(icon != null ? icon.getImage() : null, scalingMode);
}
/**
* Create a new derivable image icon with specified scalingMode.
*
* @param icon the source icon.
* @param width the icon width.
* @param height the icon height.
*/
public DerivableImageIcon(final ImageIcon icon, final int width, final int height) {
this(icon, width, height, DEFAULT_SCALING_MODE);
}
/**
* Create a new derivable image icon with specified scalingMode. If the source image doesnt match the specified
* dimensions it will be scaled accordingly.
*
* @param icon the source icon.
* @param width the icon width.
* @param height the icon height.
* @param scalingMode One of {@link Image#SCALE_DEFAULT}, {@link Image#SCALE_FAST}, {@link Image#SCALE_REPLICATE},
* {@link Image#SCALE_AREA_AVERAGING}, {@link Image#SCALE_SMOOTH}
*/
public DerivableImageIcon(final ImageIcon icon, final int width, final int height, final int scalingMode) {
this(icon != null ? icon.getImage() : null, width, height, scalingMode);
if (icon != null) setDescription(icon.getDescription());
}
/**
* Create a new derivable image.
*
* @param img the source image.
*/
public DerivableImageIcon(final Image img) {
this(img, DEFAULT_SCALING_MODE);
}
/**
* Create a new derivable image icon with specified scalingMode.
*
* @param img the source image.
* @param scalingMode One of {@link Image#SCALE_DEFAULT}, {@link Image#SCALE_FAST}, {@link Image#SCALE_REPLICATE},
* {@link Image#SCALE_AREA_AVERAGING}, {@link Image#SCALE_SMOOTH}
*/
public DerivableImageIcon(final Image img, final int scalingMode) {
this(img, img != null ? img.getWidth(null) : 0, img != null ? img.getHeight(null) : 0, scalingMode);
}
/**
* Create a new derivable image icon with default scalingMode. If the source image doesnt match the specified
* dimensions it will be scaled accordingly.
*
* @param img the source image.
* @param width the icon width.
* @param height the icon height.
*/
public DerivableImageIcon(final Image img, final int width, final int height) {
this(img, width, height, DEFAULT_SCALING_MODE);
}
/**
* Create a new derivable image icon with specified scalingMode. If the source image doesnt match the specified
* dimensions it will be scaled accordingly.
*
* @param img the source image.
* @param width the icon width.
* @param height the icon height.
* @param scalingMode One of {@link Image#SCALE_DEFAULT}, {@link Image#SCALE_FAST}, {@link Image#SCALE_REPLICATE},
* {@link Image#SCALE_AREA_AVERAGING}, {@link Image#SCALE_SMOOTH}
*/
public DerivableImageIcon(final Image img, final int width, final int height, final int scalingMode) {
this.width = width;
this.height = height;
this.scalingMode = scalingMode;
this.original = img;
if (img != null && img.getWidth(null) == width && img.getHeight(null) == height) {
this.img = img;
}
}
protected DerivableImageIcon(final DerivableImageIcon parent, final int width, final int height) {
this.width = width;
this.height = height;
this.scalingMode = parent.scalingMode;
this.original = parent.original;
this.description = parent.description;
this.imageSupplier = parent.imageSupplier;
if (this.original != null
&& this.original.getWidth(null) == width
&& this.original.getHeight(null) == height) {
this.img = this.original;
} else if (parent.img != null
&& parent.img.getWidth(null) == width
&& parent.img.getHeight(null) == height) {
this.img = parent.img;
}
}
@Override
public DerivableImageIcon derive(final int width, final int height) {
return new DerivableImageIcon(this, width, height);
}
protected void ensureOriginalLoaded() {
if (original == null && imageSupplier != null) {
original = imageSupplier.get();
imageSupplier = null;
}
}
protected void ensureLoaded() {
ensureOriginalLoaded();
if (original != null && (width < 0 || height < 0)) {
if (width < 0) width = original.getWidth(null);
if (height < 0) height = original.getHeight(null);
}
if (img == null && original != null && width > 0 && height > 0) {
if (original.getWidth(null) != width || original.getHeight(null) != height) {
img = original.getScaledInstance(width, height, scalingMode);
} else {
img = original;
}
}
}
@Override
public void paintIcon(final Component c, final Graphics g, final int x, final int y) {
ensureLoaded();
if (img != null) {
g.drawImage(img, x, y, width, height, null);
}
}
/**
* Get the underlying {@link Image}.
*
* @return the image.
*/
public Image getImage() {
ensureLoaded();
return img;
}
@Override
public int getIconWidth() {
if (width < 0) ensureLoaded();
return width;
}
@Override
public int getIconHeight() {
if (height < 0) ensureLoaded();
return height;
}
@Override
public AccessibleContext getAccessibleContext() {
if (accessibleContext == null) {
accessibleContext = new AccessibleDerivableImageIcon(this);
}
return accessibleContext;
}
/**
* Gets the description of the image. This is meant to be a brief
* textual description of the object. For example, it might be
* presented to a blind user to give an indication of the purpose
* of the image.
* The description may be null.
*
* @return a brief textual description of the image
*/
public String getDescription() {
return description;
}
/**
* Sets the description of the image. This is meant to be a brief
* textual description of the object. For example, it might be
* presented to a blind user to give an indication of the purpose
* of the image.
*
* @param description a brief textual description of the image
*/
public void setDescription(final String description) {
this.description = description;
}
protected static class AccessibleDerivableImageIcon extends AccessibleContext implements AccessibleIcon {
private final DerivableImageIcon icon;
public AccessibleDerivableImageIcon(final DerivableImageIcon icon) {
this.icon = icon;
}
@Override
public AccessibleRole getAccessibleRole() {
return AccessibleRole.ICON;
}
@Override
public AccessibleStateSet getAccessibleStateSet() {
return null;
}
@Override
public int getAccessibleIndexInParent() {
return -1;
}
@Override
public int getAccessibleChildrenCount() {
return 0;
}
@Override
public Accessible getAccessibleChild(final int i) {
return null;
}
@Override
public Locale getLocale() throws IllegalComponentStateException {
return null;
}
@Override
public String getAccessibleIconDescription() {
return icon.getDescription();
}
@Override
public void setAccessibleIconDescription(final String description) {
icon.setDescription(description);
}
@Override
public int getAccessibleIconWidth() {
return icon.getIconWidth();
}
@Override
public int getAccessibleIconHeight() {
return icon.getIconHeight();
}
}
}

92
property-loader/src/main/java/com/github/weisj/darklaf/icons/IconLoader.java

@ -32,6 +32,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -162,7 +163,7 @@ public final class IconLoader {
* @return the icon. * @return the icon.
*/ */
public DarkUIAwareIcon getUIAwareIcon(final String path) { public DarkUIAwareIcon getUIAwareIcon(final String path) {
return getUIAwareIcon(path, DEFAULT_W, DEFAULT_H); return getUIAwareIcon(path, getDefaultWidth(path), getDefaultHeight(path));
} }
/** /**
@ -203,7 +204,7 @@ public final class IconLoader {
* @return the icon. * @return the icon.
*/ */
public Icon getIcon(final String path) { public Icon getIcon(final String path) {
return getIcon(path, DEFAULT_W, DEFAULT_H); return getIcon(path, getDefaultWidth(path), getDefaultHeight(path));
} }
/** /**
@ -218,7 +219,7 @@ public final class IconLoader {
* @return the icon. * @return the icon.
*/ */
public Icon getIcon(final String path, final boolean themed) { public Icon getIcon(final String path, final boolean themed) {
return getIcon(path, DEFAULT_W, DEFAULT_H, themed); return getIcon(path, getDefaultWidth(path), getDefaultHeight(path), themed);
} }
/** /**
@ -257,34 +258,38 @@ public final class IconLoader {
} else if (awareIconMap.containsKey(key)) { } else if (awareIconMap.containsKey(key)) {
return awareIconMap.get(key); return awareIconMap.get(key);
} }
key.w = -1; // Enable wild card search. Find any icon that matches path. Icon icon = getWildcardIcon(iconMap, key, w, h);
if (iconMap.containsKey(key)) { if (icon != null) return icon;
Icon icon = iconMap.get(key);
if (icon instanceof DerivableIcon) {
// If the desired icon is an DarkSVGIcon we can create a view that shares the underlying svg with
// the existing icon.
Icon derived = ((DerivableIcon<Icon>) icon).derive(w, h);
key.w = w;
cache(iconMap, key, derived);
return derived;
}
}
} }
// Icon not found or caching is disabled. // Icon not found or caching is disabled.
key.w = w; // Restore key. key.w = w; // Restore key.
if (path.endsWith(".svg")) { if (isSVGIcon(path)) {
Icon icon = loadSVGIcon(path, w, h, themed); Icon icon = loadSVGIcon(path, w, h, themed);
cache(iconMap, key, icon); cache(iconMap, key, icon);
return icon; return icon;
} else { } else {
Icon icon = new LazyImageIcon(path, key, parentClass); Icon icon = new DerivableImageIcon(new LazyImageIconSupplier(path, key, parentClass), w, h);
cache(iconMap, key, icon); cache(iconMap, key, icon);
return icon; return icon;
} }
} }
private Icon getWildcardIcon(final Map<IconKey, Icon> iconMap,
final IconKey iconKey, final int w, final int h) {
iconKey.w = -1;
Icon icon = iconMap.get(iconKey);
if (icon instanceof DerivableIcon) {
@SuppressWarnings("unchecked")
Icon derived = ((DerivableIcon<Icon>) icon).derive(w, h);
iconKey.w = w;
cache(iconMap, iconKey, derived);
return derived;
}
return null;
}
private <T extends Icon> void cache(final Map<IconKey, T> iconMap, final IconKey key, final T icon) { private <T extends Icon> void cache(final Map<IconKey, T> iconMap, final IconKey key, final T icon) {
if (cacheEnabled) { if (cacheEnabled) {
iconMap.put(key, icon); iconMap.put(key, icon);
@ -337,22 +342,28 @@ public final class IconLoader {
*/ */
public Icon loadSVGIcon(final String path, final int w, final int h, final boolean themed, public Icon loadSVGIcon(final String path, final int w, final int h, final boolean themed,
final Map<Object, Object> propertyMap) { final Map<Object, Object> propertyMap) {
try { Supplier<URI> uriSupplier = createURISupplier(path);
if (themed) { if (themed) {
final URI uri = Objects.requireNonNull(getResource(path).toURI()); if (propertyMap != null) {
if (propertyMap != null) { return new CustomThemedIcon(uriSupplier, w, h, propertyMap);
return new CustomThemedIcon(uri, w, h, propertyMap);
} else {
return new ThemedSVGIcon(uri, w, h);
}
} else { } else {
return new DarkSVGIcon(Objects.requireNonNull(getResource(path).toURI()), w, h); return new ThemedSVGIcon(uriSupplier, w, h);
} }
} catch (NullPointerException | URISyntaxException e) { } else {
LOGGER.log(Level.SEVERE, "Exception while loading '" + path + "'" + ". Resolving from " + parentClass, return new DarkSVGIcon(createURISupplier(path), w, h);
e.getStackTrace());
} }
return EmptyIcon.create(0); }
private Supplier<URI> createURISupplier(final String path) {
return () -> {
try {
return Objects.requireNonNull(getResource(path).toURI());
} catch (NullPointerException | URISyntaxException e) {
LOGGER.log(Level.SEVERE, "Exception while loading '" + path + "'" + ". Resolving from " + parentClass,
e.getStackTrace());
}
return null;
};
} }
/** /**
@ -362,8 +373,7 @@ public final class IconLoader {
* @param description description of the icon as described in {@link ImageIcon#setDescription(String)} * @param description description of the icon as described in {@link ImageIcon#setDescription(String)}
* @return the ImageIcon. * @return the ImageIcon.
*/ */
public ImageIcon createImageIcon(final String path, ImageIcon createImageIcon(final String path, final String description) {
final String description) {
java.net.URL imgURL = getResource(path); java.net.URL imgURL = getResource(path);
if (imgURL != null) { if (imgURL != null) {
return new ImageIcon(imgURL, description); return new ImageIcon(imgURL, description);
@ -394,6 +404,20 @@ public final class IconLoader {
} }
} }
private int getDefaultWidth(final String path) {
if (!isSVGIcon(path)) return -1;
return DEFAULT_W;
}
private int getDefaultHeight(final String path) {
if (!isSVGIcon(path)) return -1;
return DEFAULT_H;
}
private boolean isSVGIcon(final String path) {
return path != null && path.endsWith(".svg");
}
protected static final class IconKey { protected static final class IconKey {
final String path; final String path;
int w; int w;
@ -407,7 +431,7 @@ public final class IconLoader {
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(path, w, h); return Objects.hash(path);
} }
@Override @Override
@ -417,7 +441,7 @@ public final class IconLoader {
IconKey iconKey = (IconKey) o; IconKey iconKey = (IconKey) o;
if (iconKey.w == -1 || iconKey.h == -1) { if (iconKey.w == -1 || iconKey.h == -1 || this.h == -1 || this.w == -1) {
// Math any size. // Math any size.
return Objects.equals(path, iconKey.path); return Objects.equals(path, iconKey.path);
} }

14
property-loader/src/main/java/com/github/weisj/darklaf/icons/LazyImageIcon.java → property-loader/src/main/java/com/github/weisj/darklaf/icons/IconSupplier.java

@ -26,17 +26,7 @@ package com.github.weisj.darklaf.icons;
import javax.swing.*; import javax.swing.*;
/** public interface IconSupplier<T extends Icon> {
* @author Jannis Weis
*/
public class LazyImageIcon extends LazyIcon {
public LazyImageIcon(final String path, final IconLoader.IconKey key, final Class<?> parentClass) {
super(path, key, parentClass);
}
@Override T getIcon();
protected Icon loadIcon() {
return IconLoader.get(parentClass).createImageIcon(path, path);
}
} }

50
property-loader/src/main/java/com/github/weisj/darklaf/icons/LazyImageIconSupplier.java

@ -0,0 +1,50 @@
/*
* MIT License
*
* Copyright (c) 2020 Jannis Weis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package com.github.weisj.darklaf.icons;
import java.awt.*;
import java.util.function.Supplier;
import javax.swing.*;
public class LazyImageIconSupplier extends AbstractLazyIconSupplier<ImageIcon>
implements Supplier<Image> {
public LazyImageIconSupplier(final String path, final IconLoader.IconKey key, final Class<?> parentClass) {
super(path, key, parentClass);
}
@Override
protected ImageIcon loadIcon() {
return IconLoader.get(parentClass).createImageIcon(path, path);
}
@Override
public Image get() {
ImageIcon imageIcon = getIcon();
if (imageIcon != null) return imageIcon.getImage();
return null;
}
}

6
property-loader/src/main/java/com/github/weisj/darklaf/icons/ThemedSVGIcon.java

@ -25,6 +25,7 @@
package com.github.weisj.darklaf.icons; package com.github.weisj.darklaf.icons;
import java.net.URI; import java.net.URI;
import java.util.function.Supplier;
/** /**
* @author Jannis Weis * @author Jannis Weis
@ -34,6 +35,11 @@ public class ThemedSVGIcon extends DarkSVGIcon implements ThemedIcon {
private Object currentTheme; private Object currentTheme;
private boolean updatedNotDuringPaint; private boolean updatedNotDuringPaint;
public ThemedSVGIcon(final Supplier<URI> uriSupplier, final int displayWidth, final int displayHeight) {
super(uriSupplier, displayWidth, displayHeight);
currentTheme = new Object();
}
public ThemedSVGIcon(final URI uri, final int displayWidth, final int displayHeight) { public ThemedSVGIcon(final URI uri, final int displayWidth, final int displayHeight) {
super(uri, displayWidth, displayHeight); super(uri, displayWidth, displayHeight);
currentTheme = new Object(); currentTheme = new Object();

Loading…
Cancel
Save