// // $Id: PicturePanel.java 95 2007-05-02 03:27:05 +0000 (mer., 02 mai 2007) // /C=DE/ST=Baden-Wuerttemberg/O=ISDN4Linux/OU=Fritz // Elfert/CN=svn-felfert@isdn4linux.de/emailAddress=fritz@fritz-elfert.de $ // // jupload - A file upload applet. // Copyright 2007 The JUpload Team // Copyright 2002 Guillaume Chamberland-Larose // // Created: ? // Creator: William JinHua Kwong // Last modified: $Date: 2009-07-15 11:45:06 -0300 (Qua, 15 Jul 2009) $ // // 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., // 675 Mass Ave, Cambridge, MA 02139, USA. package wjhk.jupload2.gui.image; import java.awt.Canvas; import java.awt.Cursor; import java.awt.Graphics; import java.awt.Image; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import javax.swing.AbstractButton; import wjhk.jupload2.exception.JUploadException; import wjhk.jupload2.filedata.PictureFileData; import wjhk.jupload2.policies.UploadPolicy; /** * This panel is used to preview picture, when PictureUploadPolicy (or one of * its inherited policy) is used. Manages the panel where pictures are * displayed.
* Each time a user selects a file in the panel file, the PictureUploadPolicy * calls * {@link #setPictureFile(PictureFileData, AbstractButton, AbstractButton)}. I * did an attempt to store the Image generated for the Panel size into the * PictureFileData, to avoid to calculate the offscreenPicture each time the * user select the same file again. But it doesn't work: the applet quickly runs * out of memory, even after numerous calls of System.gc and finalize.
*
* This file is taken from the PictureApplet ((C) 2002 Guillaume * Chamberland-Larose), available here: To contact Guillaume Chamberland-Larose * for bugs, patches, suggestions: Please use the forums on the sourceforge web * page for this project, located at: * http://sourceforge.net/projects/picture-applet/ Updated : 2006 etienne_sf
* 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. */ public class PicturePanel extends Canvas implements MouseListener, ComponentListener { /** A generated serialVersionUID, to avoid warning during compilation */ private static final long serialVersionUID = -3439340009940699981L; private PictureFileData pictureFileData; /** * offscreenImage contains an image, that can be asked by * {@link PictureFileData#getImage(Canvas, boolean)}. It is used to preview * this picture. */ private Image offscreenImage = null; /** * Indicates if the offscreen image should be calculated once and stored, to * avoid to calculate it again.
* Indications: the offscreen image should be calculate only once for the * picturePanel on the applet, and for each display when the user ask to * display the fulscreen picture (by a click on the picturePanel). */ private boolean hasToStoreOffscreenPicture = false; /** * The current upload policy. */ protected UploadPolicy uploadPolicy; /** * Standard constructor. * * @param hasToStoreOffscreenPicture * @param uploadPolicy The current upload policy */ public PicturePanel(boolean hasToStoreOffscreenPicture, UploadPolicy uploadPolicy) { super(); this.hasToStoreOffscreenPicture = hasToStoreOffscreenPicture; this.uploadPolicy = uploadPolicy; // We want to trap the mouse actions on this picture. addMouseListener(this); // We want to know when a resize event occurs (to recalculate // offscreenImage) addComponentListener(this); } /** * This setter is called by {@link PictureFileData} to set the picture that * is to be previewed. * * @param pictureFileData The FileData for the image to be displayed. Null * if no picture should be displayed. * @param button1 A button that will be activated or not, depending of the * pictures was correctly set into the panel. May be null, if not * button is to be enabled. * @param button2 Another button that will be activated or not. May also be * null. */ public void setPictureFile(PictureFileData pictureFileData, AbstractButton button1, AbstractButton button2) { // First : reset current picture configuration. this.pictureFileData = null; if (this.offscreenImage != null) { this.offscreenImage.flush(); this.offscreenImage = null; } // Ask for an immediate repaint, to clear the panel (as offscreenImage // is now null). repaint(); // Then, we store the new picture data, get the offscreen picture and // ask for a repaint. boolean enableButton = false; if (pictureFileData != null && pictureFileData.canRead()) { this.pictureFileData = pictureFileData; // A picture has been selected. The buttons must be enabled. enableButton = true; // Now, we display this picture. calculateOffscreenImage(); repaint(); } // Let's activate the given button ... if any. if (button1 != null) { button1.setEnabled(enableButton); } if (button2 != null) { button2.setEnabled(enableButton); } } /** * @see java.awt.Canvas#paint(java.awt.Graphics) */ @Override public void paint(Graphics g) { // First : clear the panel area. g.clearRect(0, 0, getWidth(), getHeight()); /* * The picture is calculated outside of the paint() event. See: * calculateOffscreenImage() and componentResized. //Then, check if we * must calculate the picture. if (pictureFileData != null) { //Now, we * calculate the picture if we don't already have one. if * (offscreenImage == null) { calculateOffscreenImage(); } } */ // Then, display the picture, if any is defined. if (this.offscreenImage != null) { // Let's center this picture int hMargin = (getWidth() - this.offscreenImage.getWidth(this)) / 2; int vMargin = (getHeight() - this.offscreenImage.getHeight(this)) / 2; g.drawImage(this.offscreenImage, hMargin, vMargin, this); // Free the used memory. this.offscreenImage.flush(); } else { this.uploadPolicy.displayDebug( "PicturePanel.paint(): offscreenImage is null", 50); } } /** * This function adds a quarter rotation to the current picture. * * @param quarter Number of quarters (90�) the picture should rotate. 1 * means rotating of 90� clockwise (?). Can be negative * (counterclockwise), more than 1... */ public void rotate(int quarter) { if (this.pictureFileData != null) { Cursor previousCursor = this.uploadPolicy.setWaitCursor(); this.pictureFileData.addRotation(quarter); // The previously calculated picture is now wrong. this.offscreenImage.flush(); this.offscreenImage = null; calculateOffscreenImage(); repaint(); this.uploadPolicy.setCursor(previousCursor); } else { this.uploadPolicy .displayWarn("Hum, this is really strange: there is no pictureFileData in the PicturePanel! Command is ignored."); } } /** * This method get the offscreenImage from the current pictureFileData. This * image is null, if pictureFileData is null. In this case, the repaint will * only clear the panel rectangle, on the screen. */ private void calculateOffscreenImage() { if (this.pictureFileData == null) { // Nothing to do. offscreenImage should be null. if (this.offscreenImage != null) { this.offscreenImage = null; this.uploadPolicy .displayWarn("PicturePanel.calculateOffscreenImage(): pictureFileData is null (offscreenImage set to null"); } } else if (this.offscreenImage == null) { this.uploadPolicy .displayDebug( "PicturePanel.calculateOffscreenImage(): trying to calculate offscreenImage (PicturePanel.calculateOffscreenImage()", 30); try { this.offscreenImage = this.pictureFileData.getImage(this, this.hasToStoreOffscreenPicture); } catch (JUploadException e) { this.uploadPolicy.displayErr(e); // We won't try to display the picture for this file. this.pictureFileData = null; this.offscreenImage = null; } } } /** * Is it really useful ?? */ @Override protected void finalize() throws Throwable { // super.finalize(); this.uploadPolicy.displayDebug("Within PicturePanel.finalize()", 10); if (this.offscreenImage != null) { this.offscreenImage.flush(); } } // //////////////////////////////////////////////////////////////////////////////////////////////////// // /////////////////////// MouseListener interface // //////////////////////////////////////////////////////////////////////////////////////////////////// /** @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent) */ public void mouseClicked(MouseEvent arg0) { if (this.pictureFileData != null) { // Ok, we have a picture. Let's display it. this.uploadPolicy.onFileDoubleClicked(this.pictureFileData); } } /** @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent) */ public void mouseEntered(MouseEvent arg0) { // Nothing to do. } /** @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent) */ public void mouseExited(MouseEvent arg0) { // Nothing to do. } /** @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent) */ public void mousePressed(MouseEvent arg0) { // Nothing to do. } /** @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent) */ public void mouseReleased(MouseEvent arg0) { // Nothing to do. } // //////////////////////////////////////////////////////////////////////////////////////////////////// // /////////////////////// ComponentListener interface // //////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////////////////////////// /** * @see java.awt.event.ComponentListener#componentHidden(java.awt.event.ComponentEvent) */ public void componentHidden(ComponentEvent arg0) { // No action } /** * @see java.awt.event.ComponentListener#componentMoved(java.awt.event.ComponentEvent) */ public void componentMoved(ComponentEvent arg0) { // No action } /** * @see java.awt.event.ComponentListener#componentResized(java.awt.event.ComponentEvent) */ public void componentResized(ComponentEvent arg0) { this.uploadPolicy.displayDebug("Within componentResized", 10); if (this.offscreenImage != null) { this.offscreenImage.flush(); this.offscreenImage = null; } // Then we calculate a new image for this panel. calculateOffscreenImage(); repaint(); } /** * @see java.awt.event.ComponentListener#componentShown(java.awt.event.ComponentEvent) */ public void componentShown(ComponentEvent arg0) { // No action } }