From a2a1c092cb10cd337835a9fc7b4220281d8c7646 Mon Sep 17 00:00:00 2001 From: nathan Date: Sun, 21 Feb 2016 00:56:30 +0100 Subject: [PATCH] Fixed issue with icon scaling in popup menu --- .../systemTray/swing/SwingMenuEntry.java | 129 +++++++++++++++++- 1 file changed, 122 insertions(+), 7 deletions(-) diff --git a/src/dorkbox/systemTray/swing/SwingMenuEntry.java b/src/dorkbox/systemTray/swing/SwingMenuEntry.java index f5d2fbc..02292a7 100644 --- a/src/dorkbox/systemTray/swing/SwingMenuEntry.java +++ b/src/dorkbox/systemTray/swing/SwingMenuEntry.java @@ -20,16 +20,28 @@ import dorkbox.systemTray.ImageUtil; import dorkbox.systemTray.MenuEntry; import dorkbox.systemTray.SystemTray; import dorkbox.systemTray.SystemTrayMenuAction; +import dorkbox.util.FileUtil; import dorkbox.util.SwingUtil; +import javax.imageio.ImageIO; +import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JMenuItem; +import javax.swing.UIManager; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Image; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.net.URL; class SwingMenuEntry implements MenuEntry { + private static final String tempDirPath = ImageUtil.TEMP_DIR.getAbsolutePath(); + private final SwingSystemTrayMenuPopup parent; private final SystemTray systemTray; private final JMenuItem menuItem; @@ -38,6 +50,11 @@ class SwingMenuEntry implements MenuEntry { private volatile String text; private volatile SystemTrayMenuAction callback; + private int iconHeight = -1; + + + + SwingMenuEntry(final SwingSystemTrayMenuPopup parentMenu, final String label, final String imagePath, final SystemTrayMenuAction callback, final SystemTray systemTray) { this.parent = parentMenu; @@ -58,7 +75,7 @@ class SwingMenuEntry implements MenuEntry { menuItem.addActionListener(swingCallback); if (imagePath != null && !imagePath.isEmpty()) { - menuItem.setIcon(new ImageIcon(imagePath)); + setImageIcon(imagePath); } parentMenu.add(menuItem); @@ -98,16 +115,70 @@ class SwingMenuEntry implements MenuEntry { @Override public void run() { - if (imagePath != null && !imagePath.isEmpty()) { - menuItem.setIcon(new ImageIcon(imagePath)); - } - else { - menuItem.setIcon(null); - } + setImageIcon(imagePath); } }); } + private + void setImageIcon(final String imagePath) { + if (imagePath != null && !imagePath.isEmpty()) { + + if (iconHeight != 0) { + // this will (and should) be the correct size for the system. On the systems tested, it was 16 + // see: http://en-human-begin.blogspot.de/2007/11/javas-icons-by-default.html + Icon icon = UIManager.getIcon("FileView.fileIcon"); + iconHeight = icon.getIconHeight(); + } + + ImageIcon origIcon = new ImageIcon(imagePath); + int origIconHeight = origIcon.getIconHeight(); + int origIconWidth = origIcon.getIconWidth(); + + int savedIconHeight = this.iconHeight; + + // it is necessary to resize this icon, so that it matches what our preferred size is for icons + if (origIconHeight != savedIconHeight && savedIconHeight != 0) { + //noinspection SuspiciousNameCombination + Dimension scaledDimension = getScaledDimension(origIconWidth, origIconHeight, savedIconHeight, savedIconHeight); + + Image image = origIcon.getImage(); + + // scale it the smoothly + Image newImage = image.getScaledInstance(scaledDimension.width, scaledDimension.height, java.awt.Image.SCALE_SMOOTH); + origIcon = new ImageIcon(newImage); + + // save it to temp spot on disk (so we don't have to KEEP on doing this). (but it MUST be the temp location, otherwise + // it's always 'on the fly') + if (imagePath.startsWith(tempDirPath)) { + // have to delete the old one + File file = new File(imagePath); + boolean delete = file.delete(); + + if (delete) { + // now write out the new one + String extension = FileUtil.getExtension(imagePath); + if (extension == null) { + extension = ".png"; // this is just made up + } + BufferedImage bufferedImage = getBufferedImage(image); + try { + ImageIO.write(bufferedImage, extension, file); + } catch (IOException e) { + // this shouldn't happen, but you never know... + e.printStackTrace(); + } + } + } + } + + menuItem.setIcon(origIcon); + } + else { + menuItem.setIcon(null); + } + } + @Override public void setImage(final String imagePath) { @@ -171,4 +242,48 @@ class SwingMenuEntry implements MenuEntry { } }); } + + private static + Dimension getScaledDimension(int originalWidth, int originalHeight, int boundWidth, int boundHeight) { + //this function comes from http://stackoverflow.com/questions/10245220/java-image-resize-maintain-aspect-ratio + + int newWidth = originalWidth; + int newHeight = originalHeight; + + // first check if we need to scale width + if (originalWidth > boundWidth) { + //scale width to fit + newWidth = boundWidth; + + //scale height to maintain aspect ratio + newHeight = (newWidth * originalHeight) / originalWidth; + } + + // then check if we need to scale even with the new height + if (newHeight > boundHeight) { + //scale height to fit instead + newHeight = boundHeight; + + //scale width to maintain aspect ratio + newWidth = (newHeight * originalWidth) / originalHeight; + } + + return new Dimension(newWidth, newHeight); + } + + private static + BufferedImage getBufferedImage(Image image) { + if (image instanceof BufferedImage) { + return (BufferedImage) image; + } + + BufferedImage bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB); + + Graphics2D bGr = bimage.createGraphics(); + bGr.drawImage(image, 0, 0, null); + bGr.dispose(); + + // Return the buffered image + return bimage; + } }