Browse Source

Move frame icon api from ImageUtil to IconLoader

Move ImageUtil to darklaf-utils.
pull/188/head
weisj 4 years ago
parent
commit
4e89843999
  1. 3
      change_notes.md
  2. 2
      core/src/main/java/com/github/weisj/darklaf/components/border/DropShadowBorder.java
  3. 4
      core/src/main/java/com/github/weisj/darklaf/settings/ThemeSettings.java
  4. 5
      core/src/main/java/com/github/weisj/darklaf/task/UtilityDefaultsInitTask.java
  5. 4
      core/src/main/java/com/github/weisj/darklaf/ui/tabbedpane/TabbedPaneTransferHandler.java
  6. 4
      core/src/main/java/com/github/weisj/darklaf/ui/tabframe/TabFrameTransferHandler.java
  7. 49
      core/src/main/java/com/github/weisj/darklaf/util/DnDUtil.java
  8. 2
      core/src/test/java/documentation/CreateUITable.java
  9. 3
      core/src/test/java/test/AbstractImageTest.java
  10. 4
      core/src/test/java/ui/ComponentDemo.java
  11. 6
      property-loader/build.gradle.kts
  12. 29
      property-loader/src/main/java/com/github/weisj/darklaf/icons/DynamicIcon.java
  13. 21
      property-loader/src/main/java/com/github/weisj/darklaf/icons/IconLoader.java
  14. 110
      property-loader/src/main/java/com/github/weisj/darklaf/icons/IconUtil.java
  15. 2
      property-loader/src/main/java/com/github/weisj/darklaf/icons/ThemedIcon.java
  16. 2
      property-loader/src/main/java/com/github/weisj/darklaf/icons/UIAwareIcon.java
  17. 75
      property-loader/src/test/java/com/github/weisj/darklaf/icons/IconUtilTest.java
  18. 107
      utils/src/main/java/com/github/weisj/darklaf/util/ImageUtil.java

3
change_notes.md

@ -6,7 +6,7 @@
- Added utility method to create themed frame icons that change depending on the - Added utility method to create themed frame icons that change depending on the
current theme: current theme:
````java ````java
frame.setIconImage(ImageUtil.createFrameIcon(icon, frame)); window.setIconImage(IconLoader.createFrameIcon(icon, window));
```` ````
- The value of `ButtonConstants.KEY_SQUARE` no longer affects the arc size of buttons. - The value of `ButtonConstants.KEY_SQUARE` no longer affects the arc size of buttons.
- If a button specifies the `ButtonConstants.VARIANT_BORDERLESS` style it no longer has a default margin of the focus border size. - If a button specifies the `ButtonConstants.VARIANT_BORDERLESS` style it no longer has a default margin of the focus border size.
@ -34,3 +34,4 @@
- Popups show up at the wrong location after moving the frame to a screen with a different `GraphicsConfiguration`. 995da5a2325fad4e3873388a215bbb345a779658 - Popups show up at the wrong location after moving the frame to a screen with a different `GraphicsConfiguration`. 995da5a2325fad4e3873388a215bbb345a779658
- The value of `ComboBox.selectionBackground` isn't respected. 6b9fa9f1596bbf90914d7008c4d49fc43f3efb94 - The value of `ComboBox.selectionBackground` isn't respected. 6b9fa9f1596bbf90914d7008c4d49fc43f3efb94
- `JTree` doesn't paint the full background if repainted area lies outside of the row bounds. 4e5fe2a6faea05e9315bc1e9b30d7cec92ce9e6b - `JTree` doesn't paint the full background if repainted area lies outside of the row bounds. 4e5fe2a6faea05e9315bc1e9b30d7cec92ce9e6b
- Tooltips have an incorrect position in some scenarios. a42f4bbbaa1c8d245efc1b95ad56e3c9aec6701d

2
core/src/main/java/com/github/weisj/darklaf/components/border/DropShadowBorder.java

@ -36,8 +36,8 @@ import java.util.Map;
import javax.swing.border.Border; import javax.swing.border.Border;
import com.github.weisj.darklaf.graphics.ImageUtil;
import com.github.weisj.darklaf.util.Disposable; import com.github.weisj.darklaf.util.Disposable;
import com.github.weisj.darklaf.util.ImageUtil;
/** /**
* Implements a DropShadow for components. In general, the DropShadowBorder will work with any rectangular components * Implements a DropShadow for components. In general, the DropShadowBorder will work with any rectangular components

4
core/src/main/java/com/github/weisj/darklaf/settings/ThemeSettings.java

@ -32,7 +32,7 @@ import javax.swing.*;
import com.github.weisj.darklaf.LafManager; import com.github.weisj.darklaf.LafManager;
import com.github.weisj.darklaf.components.DefaultButton; import com.github.weisj.darklaf.components.DefaultButton;
import com.github.weisj.darklaf.graphics.ImageUtil; import com.github.weisj.darklaf.icons.IconLoader;
import com.github.weisj.darklaf.theme.Theme; import com.github.weisj.darklaf.theme.Theme;
import com.github.weisj.darklaf.theme.event.ThemePreferenceChangeEvent; import com.github.weisj.darklaf.theme.event.ThemePreferenceChangeEvent;
import com.github.weisj.darklaf.theme.event.ThemePreferenceListener; import com.github.weisj.darklaf.theme.event.ThemePreferenceListener;
@ -91,7 +91,7 @@ public class ThemeSettings implements ThemePreferenceListener {
protected JDialog createDialog(final Window parent) { protected JDialog createDialog(final Window parent) {
JDialog dialog = new JDialog(parent); JDialog dialog = new JDialog(parent);
dialog.setIconImage(ImageUtil.createFrameIcon(getIcon(), dialog)); dialog.setIconImage(IconLoader.createFrameIcon(getIcon(), dialog));
dialog.setTitle(settingsPanel.getTitle()); dialog.setTitle(settingsPanel.getTitle());
dialog.setContentPane(contentPane); dialog.setContentPane(contentPane);
dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

5
core/src/main/java/com/github/weisj/darklaf/task/UtilityDefaultsInitTask.java

@ -53,10 +53,11 @@ public class UtilityDefaultsInitTask implements DefaultsInitTask {
PaintUtil.setFocusInactiveGlow(defaults.getColor("glowFocusInactive")); PaintUtil.setFocusInactiveGlow(defaults.getColor("glowFocusInactive"));
PaintUtil.setWarningGlow(defaults.getColor("glowWarning")); PaintUtil.setWarningGlow(defaults.getColor("glowWarning"));
CellUtil.updateColors(defaults);
IconLoader.updateAwareStyle(Theme.isDark(currentTheme) ? AwareIconStyle.DARK : AwareIconStyle.LIGHT); IconLoader.updateAwareStyle(Theme.isDark(currentTheme) ? AwareIconStyle.DARK : AwareIconStyle.LIGHT);
IconLoader.updateThemeStatus(currentTheme); IconLoader.updateThemeStatus(currentTheme);
IconLoader.reloadFrameIcons();
CellUtil.updateColors(defaults);
} }
private float getOpacity(final UIDefaults defaults, final String key) { private float getOpacity(final UIDefaults defaults, final String key) {

4
core/src/main/java/com/github/weisj/darklaf/ui/tabbedpane/TabbedPaneTransferHandler.java

@ -35,7 +35,7 @@ import java.awt.event.MouseEvent;
import javax.swing.*; import javax.swing.*;
import javax.swing.plaf.TabbedPaneUI; import javax.swing.plaf.TabbedPaneUI;
import com.github.weisj.darklaf.graphics.ImageUtil; import com.github.weisj.darklaf.util.DnDUtil;
/** /**
* @author Robert Futrell * @author Robert Futrell
@ -166,7 +166,7 @@ public class TabbedPaneTransferHandler extends TransferHandler implements DropTa
protected void createDragImage(final JTabbedPane tabbedPane, final DarkTabbedPaneUI ui) { protected void createDragImage(final JTabbedPane tabbedPane, final DarkTabbedPaneUI ui) {
Color color = ui != null ? ui.getDragBorderColor() Color color = ui != null ? ui.getDragBorderColor()
: tabbedPane.getBackgroundAt(currentTransferable.transferData.tabIndex); : tabbedPane.getBackgroundAt(currentTransferable.transferData.tabIndex);
Image tabImage = ImageUtil.createDragImage(tabbedPane, currentTransferable.transferData.tabBounds, 2, color); Image tabImage = DnDUtil.createDragImage(tabbedPane, currentTransferable.transferData.tabBounds, 2, color);
int w = tabImage.getWidth(null); int w = tabImage.getWidth(null);
int h = tabImage.getHeight(null); int h = tabImage.getHeight(null);
setDragImageOffset(new Point(w / 2, h / 2)); setDragImageOffset(new Point(w / 2, h / 2));

4
core/src/main/java/com/github/weisj/darklaf/ui/tabframe/TabFrameTransferHandler.java

@ -38,8 +38,8 @@ import com.github.weisj.darklaf.components.tabframe.JTabFrame;
import com.github.weisj.darklaf.components.tabframe.TabFramePopup; import com.github.weisj.darklaf.components.tabframe.TabFramePopup;
import com.github.weisj.darklaf.components.tabframe.TabFrameTab; import com.github.weisj.darklaf.components.tabframe.TabFrameTab;
import com.github.weisj.darklaf.components.tabframe.TabFrameUI; import com.github.weisj.darklaf.components.tabframe.TabFrameUI;
import com.github.weisj.darklaf.graphics.ImageUtil;
import com.github.weisj.darklaf.util.Alignment; import com.github.weisj.darklaf.util.Alignment;
import com.github.weisj.darklaf.util.DnDUtil;
/** /**
* @author Jannis Weis * @author Jannis Weis
@ -298,7 +298,7 @@ public class TabFrameTransferHandler extends TransferHandler implements DropTarg
protected void createDragImage(final TabFrameUI ui) { protected void createDragImage(final TabFrameUI ui) {
Component comp = currentTransferable.transferData.tab.getComponent(); Component comp = currentTransferable.transferData.tab.getComponent();
Image tabImage = ImageUtil.createDragImage(comp, 2, ui.getDragBorderColor()); Image tabImage = DnDUtil.createDragImage(comp, 2, ui.getDragBorderColor());
int w = tabImage.getWidth(null); int w = tabImage.getWidth(null);
int h = tabImage.getHeight(null); int h = tabImage.getHeight(null);
setDragImageOffset(new Point(w / 2, h / 2)); setDragImageOffset(new Point(w / 2, h / 2));

49
core/src/main/java/com/github/weisj/darklaf/util/DnDUtil.java

@ -0,0 +1,49 @@
/*
* 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.util;
import java.awt.*;
import com.github.weisj.darklaf.graphics.PaintUtil;
public class DnDUtil {
public static Image createDragImage(final Component c, final int lw, final Color borderColor) {
return createDragImage(c, new Rectangle(0, 0, c.getWidth(), c.getHeight()), lw, borderColor);
}
public static Image createDragImage(final Component c, final Rectangle bounds,
final int lw, final Color borderColor) {
Image tabImage = ImageUtil.scaledImageFromComponent(c, bounds);
int w = tabImage.getWidth(null);
int h = tabImage.getHeight(null);
Graphics g = tabImage.getGraphics();
g.setColor(borderColor);
PaintUtil.drawRect(g, 0, 0, w, h, lw);
g.dispose();
return tabImage;
}
}

2
core/src/test/java/documentation/CreateUITable.java

@ -45,11 +45,11 @@ import com.github.weisj.darklaf.DarkLaf;
import com.github.weisj.darklaf.LafManager; import com.github.weisj.darklaf.LafManager;
import com.github.weisj.darklaf.PropertyLoader; import com.github.weisj.darklaf.PropertyLoader;
import com.github.weisj.darklaf.components.border.DropShadowBorder; import com.github.weisj.darklaf.components.border.DropShadowBorder;
import com.github.weisj.darklaf.graphics.ImageUtil;
import com.github.weisj.darklaf.icons.DarkSVGIcon; import com.github.weisj.darklaf.icons.DarkSVGIcon;
import com.github.weisj.darklaf.icons.EmptyIcon; import com.github.weisj.darklaf.icons.EmptyIcon;
import com.github.weisj.darklaf.theme.Theme; import com.github.weisj.darklaf.theme.Theme;
import com.github.weisj.darklaf.util.*; import com.github.weisj.darklaf.util.*;
import com.github.weisj.darklaf.util.ImageUtil;
import com.kitfox.svg.app.beans.SVGIcon; import com.kitfox.svg.app.beans.SVGIcon;
import defaults.SampleRenderer; import defaults.SampleRenderer;

3
core/src/test/java/test/AbstractImageTest.java

@ -31,9 +31,8 @@ import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import javax.swing.*;
import com.github.weisj.darklaf.graphics.ImageUtil; import com.github.weisj.darklaf.util.ImageUtil;
public abstract class AbstractImageTest { public abstract class AbstractImageTest {
private static final int SCALING_FACTOR = 3; private static final int SCALING_FACTOR = 3;

4
core/src/test/java/ui/ComponentDemo.java

@ -38,8 +38,8 @@ import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener; import javax.swing.event.MenuListener;
import com.github.weisj.darklaf.LafManager; import com.github.weisj.darklaf.LafManager;
import com.github.weisj.darklaf.graphics.ImageUtil;
import com.github.weisj.darklaf.graphics.StringPainter; import com.github.weisj.darklaf.graphics.StringPainter;
import com.github.weisj.darklaf.icons.IconLoader;
import com.github.weisj.darklaf.settings.ThemeSettingsMenuItem; import com.github.weisj.darklaf.settings.ThemeSettingsMenuItem;
import com.github.weisj.darklaf.theme.Theme; import com.github.weisj.darklaf.theme.Theme;
import com.github.weisj.darklaf.theme.info.PreferredThemeStyle; import com.github.weisj.darklaf.theme.info.PreferredThemeStyle;
@ -90,7 +90,7 @@ public interface ComponentDemo {
Icon icon = demo.getFrameIcon(); Icon icon = demo.getFrameIcon();
if (icon != null) { if (icon != null) {
window.setIconImage(ImageUtil.createFrameIcon(icon, window)); window.setIconImage(IconLoader.createFrameIcon(icon, window));
} }
window.pack(); window.pack();

6
property-loader/build.gradle.kts

@ -5,4 +5,10 @@ plugins {
dependencies { dependencies {
api(project(":darklaf-utils")) api(project(":darklaf-utils"))
implementation("com.formdev:svgSalamander") implementation("com.formdev:svgSalamander")
testImplementation("org.junit.jupiter:junit-jupiter-api")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
}
tasks.test {
useJUnitPlatform()
} }

29
property-loader/src/main/java/com/github/weisj/darklaf/icons/DynamicIcon.java

@ -0,0 +1,29 @@
/*
* 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 javax.swing.*;
public interface DynamicIcon extends Icon {}

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

@ -24,6 +24,7 @@
*/ */
package com.github.weisj.darklaf.icons; package com.github.weisj.darklaf.icons;
import java.awt.*;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
@ -126,6 +127,13 @@ public final class IconLoader {
currentThemeKey.set(theme); currentThemeKey.set(theme);
} }
/**
* Reload all created frame icons if necessary.
*/
public static void reloadFrameIcons() {
IconUtil.reloadDynamicFrameIcons();
}
/** /**
* Get the current aware icon style. * Get the current aware icon style.
* *
@ -365,6 +373,19 @@ public final class IconLoader {
} }
} }
/**
* Create an {@link Image} from an {@link Icon} suitable for a window icon.
* If the window is moved to a screen with a different scaling factor or
* the theme changes the icon automatically gets updated.
*
* @param icon the icon.
* @param window the window.
* @return the converted {@link Image}.
*/
public static Image createFrameIcon(final Icon icon, final Window window) {
return IconUtil.createFrameIcon(icon, window);
}
protected URL getResource(final String name) { protected URL getResource(final String name) {
if (parentClass != null) { if (parentClass != null) {
return parentClass.getResource(name); return parentClass.getResource(name);

110
property-loader/src/main/java/com/github/weisj/darklaf/icons/IconUtil.java

@ -0,0 +1,110 @@
/*
* 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.awt.image.BufferedImage;
import java.beans.PropertyChangeListener;
import java.util.Map;
import java.util.WeakHashMap;
import javax.swing.*;
import com.github.weisj.darklaf.util.ImageUtil;
import com.github.weisj.darklaf.util.PropertyKey;
import com.github.weisj.darklaf.util.Scale;
public class IconUtil {
private static final int FRAME_ICON_SIZE = 32;
private static final Map<Window, Icon> windowIconSet = new WeakHashMap<>();
/**
* Reload all created frame icons if necessary.
*/
public static void reloadDynamicFrameIcons() {
SwingUtilities.invokeLater(() -> {
windowIconSet.forEach((window, icon) -> window.setIconImage(iconToImage(icon, window)));
});
}
static int getDynamicFrameIconCount() {
return windowIconSet.size();
}
public static Image createFrameIcon(final Icon icon, final Window c) {
if (icon == null) return null;
if (c != null) {
if (isDynamic(icon)) {
windowIconSet.put(c, icon);
}
PropertyChangeListener propertyChangeListener = e -> c.setIconImage(iconToImage(icon, c));
c.addPropertyChangeListener(PropertyKey.GRAPHICS_CONFIGURATION, propertyChangeListener);
}
return createScaledFrameIcon(icon, c);
}
private static boolean isDynamic(final Icon icon) {
return icon instanceof DynamicIcon;
}
private static Image createScaledFrameIcon(final Icon icon, final Window c) {
if (c != null && !c.isVisible()) {
Component parent = c.getParent();
if (parent != null) {
return iconToImage(icon, c);
}
}
return iconToImage(icon, c);
}
public static Image iconToImage(final Icon icon, final Component c) {
if (icon == null) return null;
int w = icon.getIconWidth();
int h = icon.getIconHeight();
GraphicsConfiguration gc = c.getGraphicsConfiguration();
double sx = Scale.getScaleX(gc);
double sy = Scale.getScaleY(gc);
double scaleX = sx * (((double) FRAME_ICON_SIZE) / w);
double scaleY = sy * (((double) FRAME_ICON_SIZE) / h);
return createScaledImage(icon, scaleX, scaleY);
}
public static Image createScaledImage(final Icon icon, final double scalex, final double scaley) {
if (icon == null) return null;
int w = (int) (scalex * icon.getIconWidth());
int h = (int) (scaley * icon.getIconHeight());
if (icon instanceof ImageSource) {
return ((ImageSource) icon).createImage(w, h);
} else {
BufferedImage image = ImageUtil.createCompatibleTransparentImage(w, h);
Graphics2D g = (Graphics2D) image.getGraphics();
g.scale(scalex, scaley);
icon.paintIcon(null, g, 0, 0);
g.dispose();
return image;
}
}
}

2
property-loader/src/main/java/com/github/weisj/darklaf/icons/ThemedIcon.java

@ -26,4 +26,4 @@ package com.github.weisj.darklaf.icons;
import javax.swing.*; import javax.swing.*;
public interface ThemedIcon extends Icon {} public interface ThemedIcon extends DynamicIcon {}

2
property-loader/src/main/java/com/github/weisj/darklaf/icons/UIAwareIcon.java

@ -29,7 +29,7 @@ import javax.swing.*;
/** /**
* @author Jannis Weis * @author Jannis Weis
*/ */
public interface UIAwareIcon extends Icon { public interface UIAwareIcon extends DynamicIcon {
UIAwareIcon getDual(); UIAwareIcon getDual();
} }

75
property-loader/src/test/java/com/github/weisj/darklaf/icons/IconUtilTest.java

@ -0,0 +1,75 @@
/*
* 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.lang.ref.WeakReference;
import javax.swing.*;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class IconUtilTest {
@Test
public void testWeakFrameCache() {
Object obj = new Object();
WeakReference<Object> ref = new WeakReference<>(obj);
int count = 100;
Icon icon = new TestIcon();
JFrame[] frames = new JFrame[count];
for (int i = 0; i < count; i++) {
JFrame frame = new JFrame();
frame.setIconImage(IconUtil.createFrameIcon(icon, frame));
frames[i] = frame;
}
Assertions.assertEquals(count, IconUtil.getDynamicFrameIconCount());
for (int i = 0; i < count; i++) {
frames[i].dispose();
frames[i] = null;
}
while (IconUtil.getDynamicFrameIconCount() != 0) {
System.gc();
}
Assertions.assertEquals(0, IconUtil.getDynamicFrameIconCount());
}
private static class TestIcon implements DynamicIcon {
@Override
public void paintIcon(final Component c, final Graphics g, final int x, final int y) {}
@Override
public int getIconWidth() {
return 10;
}
@Override
public int getIconHeight() {
return 10;
}
}
}

107
core/src/main/java/com/github/weisj/darklaf/graphics/ImageUtil.java → utils/src/main/java/com/github/weisj/darklaf/util/ImageUtil.java

@ -22,22 +22,10 @@
* SOFTWARE. * SOFTWARE.
* *
*/ */
package com.github.weisj.darklaf.graphics; package com.github.weisj.darklaf.util;
import java.awt.*; import java.awt.*;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.beans.PropertyChangeListener;
import java.util.function.BiConsumer;
import javax.swing.*;
import com.github.weisj.darklaf.LafManager;
import com.github.weisj.darklaf.icons.ImageSource;
import com.github.weisj.darklaf.icons.ThemedIcon;
import com.github.weisj.darklaf.icons.UIAwareIcon;
import com.github.weisj.darklaf.theme.event.ThemeInstalledListener;
import com.github.weisj.darklaf.util.PropertyKey;
import com.github.weisj.darklaf.util.Scale;
/** /**
* @author Jannis Weis * @author Jannis Weis
@ -46,99 +34,6 @@ public final class ImageUtil {
private ImageUtil() {} private ImageUtil() {}
private static final int FRAME_ICON_SIZE = 32;
public static Image createFrameIcon(final Icon icon, final Window c) {
if (c instanceof JFrame) {
return createFrameIcon(icon, (JFrame) c);
} else if (c instanceof JDialog) {
return createFrameIcon(icon, (JDialog) c);
} else {
return createScaledFrameIcon(icon, c);
}
}
public static Image createFrameIcon(final Icon icon, final JFrame c) {
return createWindowIcon(icon, c, JFrame::setIconImage);
}
public static Image createFrameIcon(final Icon icon, final JDialog c) {
return createWindowIcon(icon, c, JDialog::setIconImage);
}
private static <T extends Window> Image createWindowIcon(final Icon icon, final T c,
final BiConsumer<T, Image> iconSetter) {
if (icon == null) return null;
if (c != null) {
if (iconNeedUpdates(icon)) {
ThemeInstalledListener listener = e -> iconSetter.accept(c, iconToImage(icon, c));
LafManager.addThemeChangeListener(listener);
}
PropertyChangeListener propertyChangeListener = e -> iconSetter.accept(c, iconToImage(icon, c));
c.addPropertyChangeListener(PropertyKey.GRAPHICS_CONFIGURATION, propertyChangeListener);
}
return createScaledFrameIcon(icon, c);
}
private static boolean iconNeedUpdates(final Icon icon) {
return icon instanceof UIAwareIcon || icon instanceof ThemedIcon;
}
private static Image createScaledFrameIcon(final Icon icon, final Window c) {
if (c != null && !c.isVisible()) {
Component parent = c.getParent();
if (parent != null) {
return iconToImage(icon, c);
}
}
return iconToImage(icon, c);
}
public static Image iconToImage(final Icon icon, final Component c) {
if (icon == null) return null;
int w = icon.getIconWidth();
int h = icon.getIconHeight();
GraphicsConfiguration gc = c.getGraphicsConfiguration();
double sx = Scale.getScaleX(gc);
double sy = Scale.getScaleY(gc);
double scaleX = sx * (((double) FRAME_ICON_SIZE) / w);
double scaleY = sy * (((double) FRAME_ICON_SIZE) / h);
return createScaledImage(icon, scaleX, scaleY);
}
public static Image createScaledImage(final Icon icon, final double scalex, final double scaley) {
if (icon == null) return null;
int w = (int) (scalex * icon.getIconWidth());
int h = (int) (scaley * icon.getIconHeight());
if (icon instanceof ImageSource) {
return ((ImageSource) icon).createImage(w, h);
} else {
BufferedImage image = createCompatibleTransparentImage(w, h);
Graphics2D g = (Graphics2D) image.getGraphics();
g.scale(scalex, scaley);
icon.paintIcon(null, g, 0, 0);
g.dispose();
return image;
}
}
public static Image createDragImage(final Component c, final int lw, final Color borderColor) {
return createDragImage(c, new Rectangle(0, 0, c.getWidth(), c.getHeight()), lw, borderColor);
}
public static Image createDragImage(final Component c, final Rectangle bounds,
final int lw, final Color borderColor) {
Image tabImage = ImageUtil.scaledImageFromComponent(c, bounds);
int w = tabImage.getWidth(null);
int h = tabImage.getHeight(null);
Graphics g = tabImage.getGraphics();
g.setColor(borderColor);
PaintUtil.drawRect(g, 0, 0, w, h, lw);
g.dispose();
return tabImage;
}
/** /**
* Create image from component. * Create image from component.
* *
Loading…
Cancel
Save