/* This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV This program is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program; if not, see http://www.gnu.org/licenses or write to the Free Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 */ package com.servoy.j2db.util.gui; import java.awt.Component; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.geom.AffineTransform; import java.util.ArrayList; import java.util.List; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JComponent; import com.servoy.j2db.IApplication; import com.servoy.j2db.util.ImageLoader; import com.servoy.j2db.util.Utils; public class MyImageIcon implements Icon { private final JComponent comp; private byte[] iconArray; private Dimension succededScaledDimension; private ImageIcon original; private ImageIcon scaled; private final boolean reduce; private final boolean enlarge; private final boolean keepAspect; private final List images; private final IApplication application; public MyImageIcon(IApplication app, JComponent comp, ImageIcon icon, int mediaOption) { this(app, comp, mediaOption); this.original = icon; this.scaled = icon; this.iconWidth = icon.getIconWidth(); this.iconHeight = icon.getIconHeight(); } public MyImageIcon(IApplication app, JComponent comp, byte[] iconArray, int mediaOption) { this(app, comp, mediaOption); this.iconArray = iconArray; Dimension dim = ImageLoader.getSize(iconArray); this.iconWidth = dim.width; this.iconHeight = dim.height; } private MyImageIcon(IApplication app, JComponent comp, int mediaOption) { this.application = app; this.comp = comp; this.reduce = (mediaOption & 2) == 2; this.enlarge = (mediaOption & 4) == 4; this.keepAspect = (mediaOption & 8) == 8; images = new ArrayList(3); } public ImageIcon getScaledIcon(int width, int height) { if (width > 0 || height > 0) { return checkResize(this.scaled, new Dimension(width, height)); } else { return scaled; } } // for developer... figicon painting the original imageicon is going wrong second time boolean generated = false; private double iconWidth; private double iconHeight; public void generatedScaledIcon() { if (!generated && scaled != null) { Image image = scaled.getImage().getScaledInstance(scaled.getIconWidth(), scaled.getIconHeight(), Image.SCALE_SMOOTH); scaled = new ImageIcon(image); generated = true; } } public void addImageIcon(MyImageIcon other) { images.add(other); } public boolean removeImageIcon(MyImageIcon other) { return images.remove(other); } private ImageIcon checkResize(ImageIcon prevScaled, Dimension size) { boolean resize = succededScaledDimension == null ? true : !succededScaledDimension.equals(size); double widthChange = 0; double heightChange = 0; double width = size.getWidth(); double height = size.getHeight(); // if it doesn't fit then resize == true // check then if we have to,or can, resize the original. if (resize) { succededScaledDimension = size; widthChange = iconWidth / width; heightChange = iconHeight / height; resize = widthChange > 1.01 || heightChange > 1.01 || widthChange < 0.99 || heightChange < 0.99; if (resize) { if (!(reduce && enlarge)) { if (reduce) { if (widthChange <= 1 && heightChange <= 1) { // may only reduce, so no resize resize = false; } else if (widthChange > 1.01 && heightChange > 1.01) { if (keepAspect) { if (widthChange > heightChange) { width = (int)(iconWidth / widthChange); height = (int)(iconHeight / widthChange); } else { width = (int)(iconWidth / heightChange); height = (int)(iconHeight / heightChange); } } } else if (widthChange > 1.01) { width = (int)(iconWidth / widthChange); if (keepAspect) { height = (int)(iconHeight / widthChange); } } else if (heightChange > 1.01) { height = (int)(iconHeight / heightChange); if (keepAspect) { width = (int)(iconWidth / heightChange); } } } else if (enlarge) { if (widthChange >= 1 && heightChange >= 1) { // may only reduce, so no resize resize = false; } else if (widthChange < 0.99 && heightChange < 0.99) { if (keepAspect) { if (widthChange > heightChange) { width = (int)(iconWidth / widthChange); height = (int)(iconHeight / widthChange); } else { width = (int)(iconWidth / heightChange); height = (int)(iconHeight / heightChange); } } } else if (widthChange < 0.99) { width = (int)(iconWidth / widthChange); if (keepAspect) { height = (int)(iconHeight / widthChange); } } else if (heightChange < 0.99) { height = (int)(iconHeight / heightChange); if (keepAspect) { width = (int)(iconWidth / heightChange); } } } else { resize = false; } } else { if (keepAspect) { if (widthChange > heightChange) { width = (int)(iconWidth / widthChange); height = (int)(iconHeight / widthChange); } else { width = (int)(iconWidth / heightChange); height = (int)(iconHeight / heightChange); } // Recheck with aspect! Because component size can be bigger then the image with aspect if (prevScaled != null) { widthChange = prevScaled.getIconWidth() / width; heightChange = prevScaled.getIconHeight() / height; resize = !((widthChange > 0.99 && widthChange < 1.01) || (heightChange < 1.01 && heightChange > 0.99)); } } } } } if (resize) { if (iconArray != null) { prevScaled = ImageLoader.getIcon(iconArray, width <= 0 ? 1 : (int)width, height <= 0 ? 1 : (int)height, keepAspect); } else if (original != null) { prevScaled = new ImageIcon( original.getImage().getScaledInstance(width <= 0 ? 1 : (int)width, height <= 0 ? 1 : (int)height, Image.SCALE_SMOOTH)); } else { prevScaled = new ImageIcon(scaled.getImage().getScaledInstance(width <= 0 ? 1 : (int)width, height <= 0 ? 1 : (int)height, Image.SCALE_SMOOTH)); } } if (prevScaled == null) { prevScaled = ImageLoader.getIcon(iconArray, -1, -1, true); } return prevScaled; } /** * @see javax.swing.Icon#paintIcon(java.awt.Component, java.awt.Graphics, int, int) */ public void paintIcon(Component c, Graphics g, int x, int y) { if (scaled == null) { scaled = ImageLoader.getIcon(iconArray, c.getWidth(), c.getHeight(), keepAspect); } ImageIcon paint = null; boolean isPrinting = Utils.getAsBoolean(application.getRuntimeProperties().get("isPrinting")); if (isPrinting && iconArray != null) { paint = ImageLoader.getIcon(iconArray, -1, -1, keepAspect); } else { if (isPrinting && original != null) { paint = original; } else { paint = scaled; } } if (paint == null) return; AffineTransform at = ((Graphics2D)g).getTransform(); AffineTransform save = (AffineTransform)at.clone(); try { if (isPrinting && scaled != null) { double sx = (double)scaled.getIconWidth() / (double)paint.getIconWidth(); double sy = (double)scaled.getIconHeight() / (double)paint.getIconHeight(); x = (int)(x * ((double)paint.getIconWidth() / (double)scaled.getIconWidth())); y = (int)(y * ((double)paint.getIconHeight() / (double)scaled.getIconHeight())); at.scale(sx, sy); ((Graphics2D)g).setTransform(at); } paint.paintIcon(c, g, x, y); } finally { ((Graphics2D)g).setTransform(save); } } /** * @see javax.swing.Icon#getIconWidth() */ public int getIconWidth() { Dimension dim = comp.getSize(); if (dim.height == 0 || dim.width == 0) { return 1; } for (int i = 0; i < images.size(); i++) { ((MyImageIcon)images.get(i)).getIconWidth(); } scaled = checkResize(scaled, dim); if (scaled == null) { return 1; } return scaled.getIconWidth(); } /** * @see javax.swing.Icon#getIconHeight() */ public int getIconHeight() { Dimension dim = comp.getSize(); if (dim.height == 0 || dim.width == 0) { return 1; } if (scaled == null) { return 1; } return scaled.getIconHeight(); } /** * @param newImage * */ public void flush() { if (scaled instanceof ImageIcon) { ImageIcon imageIcon = scaled; imageIcon.getImage().flush(); imageIcon.setImageObserver(null); } if (original instanceof ImageIcon) { ImageIcon imageIcon = original; imageIcon.getImage().flush(); imageIcon.setImageObserver(null); } for (int i = 0; i < images.size(); i++) { MyImageIcon icon = (MyImageIcon)images.get(i); icon.flush(); } } public ImageIcon getOriginal() { return original; } public Image getImage() { if (scaled != null) return scaled.getImage(); else if (original != null) return original.getImage(); return null; } }