/* This file is part of Thingamablog. ( http://thingamablog.sf.net ) * * Copyright (c) 2004, Bob Tantlinger All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ package net.sf.thingamablog.gui; import java.awt.Dimension; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Rectangle; import java.awt.geom.AffineTransform; import javax.swing.JPanel; import javax.swing.Scrollable; /** * * Panel for viewing and manipulating Images * @author Bob Tantlinger 7/20/2002 * */ public class ImagePanel extends JPanel implements Scrollable { /** * */ private static final long serialVersionUID = 1L; public final static int ZOOM_IN = 50; public final static int ZOOM_OUT = 100; public final static int ZOOM_ACTUAL = 150; public static final int MAX_ZOOM = 32; public final static int ROTATE_CW = 25; public final static int ROTATE_CCW = 75; private Image image; private int imageWidth, imageHeight; private double scaleFactor = 1.0; private double angle; private boolean bestFit = true; private boolean displayable; private int scrollInc = 10; private int zInc = 1; private boolean isShowNoPreview; public ImagePanel(){} /*public void setImage(Image img) { if(img == null) return; image = img; imageWidth = image.getWidth(this); // Get image width imageHeight = image.getHeight(this); // and its height angle = 0; scaleBestFit(); repaint(); } */ public void setImage(Image img) { image = img; if(image != null) { imageWidth = image.getWidth(this); // Get image width imageHeight = image.getHeight(this); // and its height } else imageWidth = imageHeight = 0; displayable = ((imageWidth < 1 || imageHeight < 1) ? false : true); angle = 0; scaleBestFit(); //repaint(); } public Image getImage() { return image; } public Dimension getImageSize() { if(image == null) return null; return new Dimension(image.getWidth(this), image.getHeight(this)); } public boolean isImageDisplayed() { return displayable; } public boolean isBestFit() { return bestFit; } public void scaleBestFit() { bestFit = true; setPreferredSize(null); revalidate(); repaint(); } public void zoom(int z) { if(isBestFit()) zInc = Math.round(1/(float)scaleFactor) * -1; if(z == ZOOM_IN) { if(zInc < MAX_ZOOM) zInc++; if(zInc == 0) zInc = 2; } else if(z == ZOOM_OUT) { if(zInc > -MAX_ZOOM) zInc--; if(zInc == 0) zInc = -2; } else if(z == ZOOM_ACTUAL) zInc = 1; else return; double temp; if(zInc >= 1) temp = (double)Math.abs(zInc)/1; else temp = (double)1/Math.abs(zInc); if(Math.min(imageWidth * temp, imageHeight * temp) <= 0) return; else scaleFactor = temp; bestFit = false; resizePanelToImage(); repaint(); } public void rotate90deg(int dir) { if(image == null) return; if(dir == ROTATE_CW) angle += 90; else if(dir == ROTATE_CCW) angle -= 90; if(angle > 360) angle = 90; else if(angle < 0) angle = 270; if((int)angle == 90 || (int)angle == 270) { imageWidth = image.getHeight(this); imageHeight = image.getWidth(this); } else { imageWidth = image.getWidth(this); imageHeight = image.getHeight(this); } scaleBestFit(); } public void paintComponent(Graphics g) { super.paintComponent(g); drawImage(g); } protected void drawImage(Graphics g) { if(!displayable) { drawNoPreviewMessage(g); return; } Graphics2D g2D = (Graphics2D)g; if(isBestFit()) scaleFactor = bestFitScaleFactor(); //absolute image width/height int iwidth = image.getWidth(this); int iheight = image.getHeight(this); // Create a transform to translate and scale the image AffineTransform at = new AffineTransform(); at.setToTranslation((getSize().width - iwidth*scaleFactor)/2, (getSize().height - iheight*scaleFactor)/2); at.scale(scaleFactor, scaleFactor); g2D.transform(at); //scale and translate g2D.rotate(angle * Math.PI/180, iwidth/2.0, iheight/2.0); g2D.drawImage(image, 0, 0, this); } private void drawNoPreviewMessage(Graphics g) { String message = " "; if(isShowNoPreview) message = "No preview available"; FontMetrics fm = g.getFontMetrics(); int swidth = fm.stringWidth(message); int sheight = fm.getHeight(); g.drawString(message, (getWidth()/2 - swidth/2), (getHeight()/2 - sheight/2)); } private double bestFitScaleFactor() { int padding = 5; //padding around image double h = 1.0, v = 1.0; //horizontal and vertical //default scale factor of 100% if(getSize().width - padding < imageWidth) h = (double)(getSize().width - padding)/imageWidth; if(getSize().height - padding < imageHeight) v = (double)(getSize().height - padding)/imageHeight; return Math.min(h, v); } private void resizePanelToImage() { int w = (int)(imageWidth * scaleFactor); int h = (int)(imageHeight * scaleFactor); setPreferredSize(new Dimension(w, h)); revalidate(); } /* Scrollable interface implementation so the panel can be * properly used in a JScrollPane, etc... */ public Dimension getPreferredScrollableViewportSize() { return getPreferredSize(); } public int getScrollableUnitIncrement(Rectangle vr, int o, int d) { return scrollInc; //scroll by scrollInc pixels at a time } public int getScrollableBlockIncrement(Rectangle vr, int o, int d) { return scrollInc * 5; } public boolean getScrollableTracksViewportWidth() { return getPreferredSize() == null || getPreferredSize().width <= getVisibleRect().width; } public boolean getScrollableTracksViewportHeight() { return getPreferredSize() == null || getPreferredSize().height <= getVisibleRect().height; } /** * @return */ public boolean isShowNoPreview() { return isShowNoPreview; } /** * @param b */ public void setShowNoPreview(boolean b) { isShowNoPreview = b; } }