Coverage Report - wjhk.jupload2.policies.PictureUploadPolicy
 
Classes in this File Line Coverage Branch Coverage Complexity
PictureUploadPolicy
26 %
50/190
6 %
4/60
2,028
 
 1  
 //
 2  
 // $Id: PictureUploadPolicy.java 295 2007-06-27 08:43:25 +0000 (mer., 27 juin
 3  
 // 2007) etienne_sf $
 4  
 //
 5  
 // jupload - A file upload applet.
 6  
 // Copyright 2007 The JUpload Team
 7  
 //
 8  
 // Created: 2006-05-06
 9  
 // Creator: etienne_sf
 10  
 // Last modified: $Date: 2015-03-10 20:59:42 +0100 (mar., 10 mars 2015) $
 11  
 //
 12  
 // This program is free software; you can redistribute it and/or modify it under
 13  
 // the terms of the GNU General Public License as published by the Free Software
 14  
 // Foundation; either version 2 of the License, or (at your option) any later
 15  
 // version. This program is distributed in the hope that it will be useful, but
 16  
 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 17  
 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 18  
 // details. You should have received a copy of the GNU General Public License
 19  
 // along with this program; if not, write to the Free Software Foundation, Inc.,
 20  
 // 675 Mass Ave, Cambridge, MA 02139, USA.
 21  
 
 22  
 package wjhk.jupload2.policies;
 23  
 
 24  
 import java.awt.Cursor;
 25  
 import java.awt.GridLayout;
 26  
 import java.awt.Image;
 27  
 import java.awt.SystemColor;
 28  
 import java.awt.event.ActionEvent;
 29  
 import java.awt.event.ActionListener;
 30  
 import java.awt.image.ImageObserver;
 31  
 import java.io.File;
 32  
 
 33  
 import javax.swing.BorderFactory;
 34  
 import javax.swing.Icon;
 35  
 import javax.swing.ImageIcon;
 36  
 import javax.swing.JButton;
 37  
 import javax.swing.JOptionPane;
 38  
 import javax.swing.JPanel;
 39  
 
 40  
 import wjhk.jupload2.context.JUploadContext;
 41  
 import wjhk.jupload2.exception.JUploadException;
 42  
 import wjhk.jupload2.exception.JUploadExceptionStopAddingFiles;
 43  
 import wjhk.jupload2.exception.JUploadIOException;
 44  
 import wjhk.jupload2.filedata.FileData;
 45  
 import wjhk.jupload2.filedata.PictureFileData;
 46  
 import wjhk.jupload2.filedata.helper.ImageFileConversionInfo;
 47  
 import wjhk.jupload2.gui.JUploadFileChooser;
 48  
 import wjhk.jupload2.gui.JUploadPanel;
 49  
 import wjhk.jupload2.gui.image.JUploadImagePreview;
 50  
 import wjhk.jupload2.gui.image.PictureDialog;
 51  
 import wjhk.jupload2.gui.image.PicturePanel;
 52  
 
 53  
 /**
 54  
  * This class add handling of pictures to upload. <BR>
 55  
  * <BR>
 56  
  * <H4>Functionalities:</H4>
 57  
  * <UL>
 58  
  * <LI>The top panel (upper part of the applet display) is modified, by using UploadPolicy.
 59  
  * {@link wjhk.jupload2.policies.UploadPolicy#createTopPanel(JButton, JButton, JButton, JUploadPanel)} . It contains a
 60  
  * <B>preview</B> picture panel, and two additional buttons to rotate the selected picture in one direction or the
 61  
  * other.
 62  
  * <LI>Ability to set maximum width or height to a picture (with maxPicWidth and maxPicHeight applet parameters, see the
 63  
  * global explanation on the <a href="UploadPolicy.html#parameters">parameters</a> section) of the UploadPolicy API
 64  
  * page.
 65  
  * <LI>Rotation of pictures, by quarter of turn.
 66  
  * <LI><I>(To be implemented)</I> A target picture format can be used, to force all uploaded pictures to be in one
 67  
  * picture format, jpeg for instance. All details are in the UploadPolicy <a
 68  
  * href="UploadPolicy.html#parameters">parameters</a> section.
 69  
  * </UL>
 70  
  * <BR>
 71  
  * <BR>
 72  
  * See an example of HTML that calls this applet, just below. <H4>Parameters</H4> The description for all parameters of
 73  
  * all polices has been grouped in the UploadPolicy <a href="UploadPolicy.html#parameters">parameters</a> section. <BR>
 74  
  * The parameters implemented in this class are:
 75  
  * <UL>
 76  
  * <LI>maxPicWidth: Maximum width for the uploaded picture.
 77  
  * <LI>maxPicHeight: Maximum height for the uploaded picture.
 78  
  * <LI>targetPictureFormat : Define picture format conversions.
 79  
  * <LI>keepOriginalFileExtensionForConvertedImages : handling of file extensions for image conversions.
 80  
  * </UL>
 81  
  * <A NAME="example"> <H4>HTML call example</H4> </A> You'll find below an example of how to put the applet into a PHP
 82  
  * page: <BR>
 83  
  * <XMP> <APPLET NAME="JUpload" CODE="wjhk.jupload2.JUploadApplet" ARCHIVE="plugins/jupload/wjhk.jupload.jar" <!--
 84  
  * Applet display size, on the navigator page --> WIDTH="500" HEIGHT="700" <!-- The applet call some javascript
 85  
  * function, so we must allow it : --> MAYSCRIPT > <!-- First, mandatory parameters --> <PARAM NAME="postURL"
 86  
  * VALUE="http://some.host.com/youruploadpage.php"> <PARAM NAME="uploadPolicy" VALUE="PictureUploadPolicy"> <!-- Then,
 87  
  * optional parameters --> <PARAM NAME="lang" VALUE="fr"> <PARAM NAME="maxPicHeight" VALUE="768"> <PARAM
 88  
  * NAME="maxPicWidth" VALUE="1024"> <PARAM NAME="debugLevel" VALUE="0"> Java 1.4 or higher plugin required. </APPLET>
 89  
  * </XMP>
 90  
  * 
 91  
  * @author etienne_sf
 92  
  * @version $Revision: 1715 $
 93  
  */
 94  
 
 95  
 public class PictureUploadPolicy extends DefaultUploadPolicy implements ActionListener, ImageObserver {
 96  
 
 97  
     /**
 98  
      * Indicates that a BufferedImage is to be created when the user selects the file. <BR>
 99  
      * If true : the Image is loaded once from the hard drive. This consumes memory, but is interesting for big
 100  
      * pictures, when they are resized (see {@link #maxWidth} and {@link #maxHeight}). <BR>
 101  
      * If false : it is loaded for each display on the applet, then once for the upload. <BR>
 102  
      * <BR>
 103  
      * Default : false, because the applet, while in the navigator, runs too quickly out of memory.
 104  
      * 
 105  
      * @see wjhk.jupload2.policies.UploadPolicy#DEFAULT_STORE_BUFFERED_IMAGE
 106  
      */
 107  
     private boolean storeBufferedImage;
 108  
 
 109  
     /**
 110  
      * This parameter can contain a list to convert image formats. <br />
 111  
      * see class description of {@link UploadPolicy} for details
 112  
      * 
 113  
      * @see wjhk.jupload2.policies.UploadPolicy#DEFAULT_TARGET_PICTURE_FORMAT
 114  
      */
 115  
     private String targetPictureFormat;
 116  
 
 117  
     /**
 118  
      * see class description of {@link UploadPolicy} for details
 119  
      * 
 120  
      * @see wjhk.jupload2.policies.UploadPolicy#DEFAULT_KEEP_ORIG_EXTENSION
 121  
      */
 122  
     private boolean keepOrigExtension;
 123  
 
 124  
     /**
 125  
      * the parsed {@link #targetPictureFormat} list
 126  
      */
 127  25
     private ImageFileConversionInfo imageFileConversionInfo = new ImageFileConversionInfo("");
 128  
 
 129  
     /**
 130  
      * Stored value for the fileChooserIconFromFileContent applet property.
 131  
      * 
 132  
      * @see UploadPolicy#PROP_FILE_CHOOSER_IMAGE_PREVIEW
 133  
      */
 134  25
     private boolean fileChooserImagePreview = UploadPolicy.DEFAULT_FILE_CHOOSER_IMAGE_PREVIEW;
 135  
 
 136  
     /**
 137  
      * Indicates wether or not the preview pictures must be calculated by the BufferedImage.getScaledInstance() method.
 138  
      */
 139  
     private boolean highQualityPreview;
 140  
 
 141  
     /**
 142  
      * Maximal width for the uploaded picture. If the actual width for the picture is more than maxWidth, the picture is
 143  
      * resized. The proportion between widht and height are maintained. Negative if no maximum width (no resizing). <BR>
 144  
      * Default: -1.
 145  
      * 
 146  
      * @see wjhk.jupload2.policies.UploadPolicy#DEFAULT_MAX_WIDTH
 147  
      */
 148  25
     private int maxWidth = -1;
 149  
 
 150  
     /**
 151  
      * Maximal height for the uploaded picture. If the actual height for the picture is more than maxHeight, the picture
 152  
      * is resized. The proportion between width and height are maintained. Negative if no maximum height (no resizing). <BR>
 153  
      * Default: -1.
 154  
      * 
 155  
      * @see wjhk.jupload2.policies.UploadPolicy#DEFAULT_MAX_HEIGHT
 156  
      */
 157  25
     private int maxHeight = -1;
 158  
 
 159  
     /**
 160  
      * Used to control the compression of a jpeg written file, after transforming a picture.
 161  
      * 
 162  
      * @see UploadPolicy#PROP_PICTURE_COMPRESSION_QUALITY
 163  
      */
 164  25
     private float pictureCompressionQuality = UploadPolicy.DEFAULT_PICTURE_COMPRESSION_QUALITY;
 165  
 
 166  
     /**
 167  
      * Used to control whether PictureFileData should add metadata to transformed picture files, before upload (or
 168  
      * remove metadata from normally untransformed picture files).
 169  
      */
 170  
     private boolean pictureTransmitMetadata;
 171  
 
 172  
     /**
 173  
      * @see UploadPolicy
 174  
      */
 175  25
     private int realMaxWidth = -1;
 176  
 
 177  
     /**
 178  
      * @see UploadPolicy
 179  
      */
 180  25
     private int realMaxHeight = -1;
 181  
 
 182  
     /**
 183  
      * Button to allow the user to rotate the picture one quarter counter-clockwise.
 184  
      */
 185  
     private JButton rotateLeftButton;
 186  
 
 187  
     /**
 188  
      * Button to allow the user to rotate the picture one quarter clockwise.
 189  
      */
 190  
     private JButton rotateRightButton;
 191  
 
 192  
     /**
 193  
      * The picture panel, where the selected picture is displayed.
 194  
      */
 195  
     private PicturePanel picturePanel;
 196  
 
 197  
     /**
 198  
      * The standard constructor, which transmit most informations to the super.Constructor().
 199  
      * 
 200  
      * @param juploadContext Reference to the current applet. Allows access to javascript functions.
 201  
      * @throws JUploadException
 202  
      */
 203  
     public PictureUploadPolicy(JUploadContext juploadContext) throws JUploadException {
 204  25
         super(juploadContext);
 205  
 
 206  
         // Creation of the PictureFileDataPolicy, from parameters given to the
 207  
         // applet, or from default values.
 208  25
         setFileChooserImagePreview(juploadContext.getParameter(PROP_FILE_CHOOSER_IMAGE_PREVIEW,
 209  
                 DEFAULT_FILE_CHOOSER_IMAGE_PREVIEW));
 210  25
         setHighQualityPreview(juploadContext.getParameter(PROP_HIGH_QUALITY_PREVIEW, DEFAULT_HIGH_QUALITY_PREVIEW));
 211  25
         setMaxHeight(juploadContext.getParameter(PROP_MAX_HEIGHT, DEFAULT_MAX_HEIGHT));
 212  25
         setMaxWidth(juploadContext.getParameter(PROP_MAX_WIDTH, DEFAULT_MAX_WIDTH));
 213  25
         setPictureCompressionQuality(juploadContext.getParameter(PROP_PICTURE_COMPRESSION_QUALITY,
 214  
                 DEFAULT_PICTURE_COMPRESSION_QUALITY));
 215  25
         setPictureTransmitMetadata(juploadContext.getParameter(PROP_PICTURE_TRANSMIT_METADATA,
 216  
                 DEFAULT_PICTURE_TRANSMIT_METADATA));
 217  25
         setRealMaxHeight(juploadContext.getParameter(PROP_REAL_MAX_HEIGHT, DEFAULT_REAL_MAX_HEIGHT));
 218  25
         setRealMaxWidth(juploadContext.getParameter(PROP_REAL_MAX_WIDTH, DEFAULT_REAL_MAX_WIDTH));
 219  25
         setTargetPictureFormat(juploadContext.getParameter(PROP_TARGET_PICTURE_FORMAT, DEFAULT_TARGET_PICTURE_FORMAT));
 220  
 
 221  25
         setKeepOrigExtension(juploadContext.getParameter(PROP_KEEP_ORIG_EXTENSION, DEFAULT_KEEP_ORIG_EXTENSION));
 222  
 
 223  25
         displayDebug("[PictureUploadPolicy] end of constructor", 30);
 224  25
     }
 225  
 
 226  
     /**
 227  
      * This methods actually returns a {@link PictureFileData} instance. It allows only pictures: if the file is not a
 228  
      * picture, this method returns null, thus preventing the file to be added to the list of files to be uploaded.
 229  
      * 
 230  
      * @param file The file selected by the user (called once for each added file).
 231  
      * @return An instance of {@link PictureFileData} or null if file is not a picture.
 232  
      * @see wjhk.jupload2.policies.UploadPolicy#createFileData(File,File)
 233  
      */
 234  
     @Override
 235  
     public FileData createFileData(File file) throws JUploadExceptionStopAddingFiles {
 236  
         // Do standard rules accept this file ?
 237  0
         FileData defaultFileData = super.createFileData(file);
 238  
 
 239  0
         if (defaultFileData == null) {
 240  
             // The file is not allowed.
 241  0
             return null;
 242  
         } else {
 243  
             // Ok, the file is to be accepted. Is it a picture?
 244  0
             PictureFileData pfd = null;
 245  
             try {
 246  0
                 pfd = new PictureFileData(file, this);
 247  0
             } catch (JUploadIOException e) {
 248  0
                 displayErr(e);
 249  0
             }
 250  
 
 251  
             // If we get a pfd, let' check that it's a picture.
 252  0
             if (pfd != null && pfd.isPicture()) {
 253  0
                 return pfd;
 254  0
             } else if (getAllowedFileExtensions() != null) {
 255  
                 // A list of allowed extensions has been given, and, as we got
 256  
                 // here, defaultFileData is not null, that is: this files match
 257  
                 // the allowedFileEXtensions parameter. We return it.
 258  0
                 return defaultFileData;
 259  
             } else {
 260  
                 // We now use the JUploadExceptionStopAddingFiles exception, to
 261  
                 // allow the user to stop adding files.
 262  0
                 String msg = getLocalizedString("notAPicture", file.getName());
 263  
 
 264  
                 // Alert only once, when several files are not pictures... hum,
 265  0
                 displayWarn(msg);
 266  0
                 if (JOptionPane.showConfirmDialog(null, msg, "alert", JOptionPane.OK_CANCEL_OPTION,
 267  
                         JOptionPane.WARNING_MESSAGE) == JOptionPane.CANCEL_OPTION) {
 268  
                     // The user want to stop to add files to the list. For
 269  
                     // instance, when he/she added a whole directory, and it
 270  
                     // contains a lot of files that don't match the allowed file
 271  
                     // extension.
 272  0
                     throw new JUploadExceptionStopAddingFiles("Stopped by the user");
 273  
                 }
 274  0
                 return null;
 275  
             }
 276  
         }
 277  
     }
 278  
 
 279  
     /**
 280  
      * This method override the default topPanel, and adds:<BR>
 281  
      * <UL>
 282  
      * <LI>Two rotation buttons, to rotate the currently selected picture.
 283  
      * <LI>A Preview area, to view the selected picture
 284  
      * </UL>
 285  
      * 
 286  
      * @see wjhk.jupload2.policies.UploadPolicy#createTopPanel(JButton, JButton, JButton, JUploadPanel)
 287  
      */
 288  
     @Override
 289  
     public JPanel createTopPanel(JButton browse, JButton remove, JButton removeAll, JUploadPanel jUploadPanel) {
 290  
         // The top panel is verticaly divided in :
 291  
         // - On the left, the button bar (buttons one above another)
 292  
         // - On the right, the preview PicturePanel.
 293  
 
 294  
         // Creation of specific buttons
 295  0
         this.rotateLeftButton = new JButton(getLocalizedString("buttonRotateLeft"));
 296  0
         this.rotateLeftButton.setIcon(new ImageIcon(getClass().getResource("/images/rotateLeft.gif")));
 297  0
         this.rotateLeftButton.addActionListener(this);
 298  0
         this.rotateLeftButton.addMouseListener(jUploadPanel.getMouseListener());
 299  0
         this.rotateLeftButton.setEnabled(false);
 300  
 
 301  0
         this.rotateRightButton = new JButton(getLocalizedString("buttonRotateRight"));
 302  0
         this.rotateRightButton.setIcon(new ImageIcon(getClass().getResource("/images/rotateRight.gif")));
 303  0
         this.rotateRightButton.addActionListener(this);
 304  0
         this.rotateRightButton.addMouseListener(jUploadPanel.getMouseListener());
 305  0
         this.rotateRightButton.setEnabled(false);
 306  
 
 307  
         // The button bar
 308  0
         JPanel buttonPanel = new JPanel();
 309  0
         buttonPanel.setLayout(new GridLayout(5, 1, 5, 5));
 310  0
         buttonPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 5));
 311  0
         buttonPanel.add(browse);
 312  0
         buttonPanel.add(this.rotateLeftButton);
 313  0
         buttonPanel.add(this.rotateRightButton);
 314  0
         buttonPanel.add(removeAll);
 315  0
         buttonPanel.add(remove);
 316  
 
 317  
         // The preview PicturePanel
 318  0
         JPanel pPanel = new JPanel();
 319  0
         pPanel.setLayout(new GridLayout(1, 1));
 320  0
         pPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 10));
 321  
 
 322  0
         this.picturePanel = new PicturePanel(true, this);
 323  0
         this.picturePanel.addMouseListener(jUploadPanel.getMouseListener());
 324  0
         pPanel.add(this.picturePanel);
 325  
         // Setting specific cursor for this panel, default for other parts of
 326  
         // the applet.
 327  0
         setCursor(null);
 328  
 
 329  
         // And last but not least ... creation of the top panel:
 330  0
         JPanel topPanel = new JPanel();
 331  0
         topPanel.setLayout(new GridLayout(1, 2));
 332  0
         topPanel.add(buttonPanel);
 333  0
         topPanel.add(pPanel);
 334  
 
 335  0
         jUploadPanel.getJComponent().setBorder(BorderFactory.createLineBorder(SystemColor.controlDkShadow));
 336  
 
 337  0
         return topPanel;
 338  
     }// createTopPanel
 339  
 
 340  
     /**
 341  
      * This method handles the clicks on the rotation buttons. All other actions are managed by the
 342  
      * {@link DefaultUploadPolicy}.
 343  
      * 
 344  
      * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
 345  
      */
 346  
     public void actionPerformed(ActionEvent e) {
 347  0
         displayInfo("Action : " + e.getActionCommand());
 348  0
         if (e.getActionCommand() == this.rotateLeftButton.getActionCommand()) {
 349  0
             this.picturePanel.rotate(-1);
 350  0
         } else if (e.getActionCommand() == this.rotateRightButton.getActionCommand()) {
 351  0
             this.picturePanel.rotate(1);
 352  
         }
 353  0
     }// actionPerformed
 354  
 
 355  
     /**
 356  
      * @see wjhk.jupload2.policies.UploadPolicy#onFileSelected(wjhk.jupload2.filedata.FileData)
 357  
      */
 358  
     @Override
 359  
     public void onFileSelected(FileData fileData) {
 360  0
         if (fileData != null) {
 361  0
             displayDebug("File selected: " + fileData.getFileName(), 30);
 362  
         }
 363  0
         if (this.picturePanel != null) {
 364  
             // If this file is a picture, we display it.
 365  0
             if (fileData instanceof PictureFileData) {
 366  0
                 Cursor previousCursor = setWaitCursor();
 367  0
                 this.picturePanel.setPictureFile((PictureFileData) fileData, this.rotateLeftButton,
 368  
                         this.rotateRightButton);
 369  0
                 setCursor(previousCursor);
 370  0
             } else {
 371  0
                 this.picturePanel.setPictureFile(null, this.rotateLeftButton, this.rotateRightButton);
 372  
             }
 373  
         }
 374  0
     }
 375  
 
 376  
     /**
 377  
      * Open the 'big' preview dialog box. It allows the user to see a full screen preview of the choosen picture.<BR>
 378  
      * This method does nothing if the panel has no selected picture, that is when pictureFileData is null.
 379  
      * 
 380  
      * @see UploadPolicy#onFileDoubleClicked(FileData)
 381  
      */
 382  
     @Override
 383  
     public void onFileDoubleClicked(FileData pictureFileData) {
 384  0
         if (pictureFileData == null) {
 385  
             // No action
 386  0
         } else if (!(pictureFileData instanceof PictureFileData)) {
 387  0
             displayWarn("PictureUploadPolicy: received a non PictureFileData in onFileDoubleClicked");
 388  
         } else {
 389  0
             new PictureDialog(null, (PictureFileData) pictureFileData, this);
 390  
         }
 391  0
     }
 392  
 
 393  
     /** @see UploadPolicy#beforeUpload() */
 394  
     @Override
 395  
     public boolean beforeUpload() {
 396  
         // We clear the current picture selection. This insures a correct
 397  
         // managing of enabling/disabling of
 398  
         // buttons, even if the user stops the upload.
 399  0
         getContext().getUploadPanel().getFilePanel().clearSelection();
 400  0
         if (this.picturePanel != null) {
 401  0
             this.picturePanel.setPictureFile(null, this.rotateLeftButton, this.rotateRightButton);
 402  
         }
 403  
 
 404  
         // Then, we call the standard action, if any.
 405  0
         return super.beforeUpload();
 406  
     }
 407  
 
 408  
     // ////////////////////////////////////////////////////////////////////////////////////////////////////
 409  
     // /////////////////////// Getters and Setters
 410  
     // ////////////////////////////////////////////////
 411  
     // ////////////////////////////////////////////////////////////////////////////////////////////////////
 412  
 
 413  
     /**
 414  
      * Getter for fileChooserImagePreview.
 415  
      * 
 416  
      * @return Current value for the applet parameter: fileChooserImagePreview
 417  
      * @see UploadPolicy#PROP_FILE_CHOOSER_IMAGE_PREVIEW
 418  
      */
 419  
     public boolean getFileChooserImagePreview() {
 420  0
         return this.fileChooserImagePreview;
 421  
     }
 422  
 
 423  
     /**
 424  
      * Setter for fileChooserIconFromFileContent. Current allowed values are: -1, 0, 1. Default value is 0.
 425  
      * 
 426  
      * @param fileChooserImagePreview new value to store, for the applet parameter: fileChooserImagePreview.
 427  
      * @see UploadPolicy#PROP_FILE_CHOOSER_IMAGE_PREVIEW
 428  
      */
 429  
     public void setFileChooserImagePreview(boolean fileChooserImagePreview) {
 430  25
         this.fileChooserImagePreview = fileChooserImagePreview;
 431  25
     }
 432  
 
 433  
     /** @return the applet parameter <I>highQualityPreview</I>. */
 434  
     public boolean getHighQualityPreview() {
 435  2
         return this.highQualityPreview;
 436  
     }
 437  
 
 438  
     /** @param highQualityPreview the highQualityPreview to set */
 439  
     void setHighQualityPreview(boolean highQualityPreview) {
 440  25
         this.highQualityPreview = highQualityPreview;
 441  25
     }
 442  
 
 443  
     /**
 444  
      * @return Returns the maxHeight, that should be used by pictures non transformed (rotated...) by the applet.
 445  
      */
 446  
     public int getMaxHeight() {
 447  6
         return this.maxHeight;
 448  
     }
 449  
 
 450  
     /** @param maxHeight the maxHeight to set */
 451  
     void setMaxHeight(int maxHeight) {
 452  25
         if (maxHeight <= 0) {
 453  0
             this.maxHeight = Integer.MAX_VALUE;
 454  0
             displayWarn("[setMaxHeight] maxHeight switched from " + maxHeight + " to " + this.maxHeight);
 455  
         } else {
 456  25
             this.maxHeight = maxHeight;
 457  
         }
 458  25
     }
 459  
 
 460  
     /**
 461  
      * @return Returns the maxWidth, that should be used by pictures non transformed (rotated...) by the applet.
 462  
      */
 463  
     public int getMaxWidth() {
 464  6
         return this.maxWidth;
 465  
     }
 466  
 
 467  
     /** @param maxWidth the maxWidth to set */
 468  
     void setMaxWidth(int maxWidth) {
 469  25
         if (maxWidth <= 0) {
 470  0
             this.maxWidth = Integer.MAX_VALUE;
 471  0
             displayWarn("[setMaxWidth] maxWidth switched from " + maxWidth + " to " + this.maxWidth);
 472  
         } else {
 473  25
             this.maxWidth = maxWidth;
 474  
         }
 475  25
     }
 476  
 
 477  
     /**
 478  
      * @return The current value for picture compression.
 479  
      */
 480  
     public float getPictureCompressionQuality() {
 481  0
         return this.pictureCompressionQuality;
 482  
     }
 483  
 
 484  
     /**
 485  
      * @see #pictureCompressionQuality
 486  
      * @param pictureCompressionQuality The new value for picture compression.
 487  
      */
 488  
     void setPictureCompressionQuality(float pictureCompressionQuality) {
 489  25
         this.pictureCompressionQuality = pictureCompressionQuality;
 490  25
     }
 491  
 
 492  
     /**
 493  
      * @return The current value for transmission (or no transmission) of picture metadata.
 494  
      */
 495  
     public boolean getPictureTransmitMetadata() {
 496  13
         return this.pictureTransmitMetadata;
 497  
     }
 498  
 
 499  
     /**
 500  
      * @see #pictureTransmitMetadata
 501  
      * @param pictureTransmitMetadata The new value for this attribute.
 502  
      */
 503  
     void setPictureTransmitMetadata(boolean pictureTransmitMetadata) {
 504  25
         this.pictureTransmitMetadata = pictureTransmitMetadata;
 505  25
     }
 506  
 
 507  
     /**
 508  
      * @return Returns the maxHeight, that should be used by pictures that are transformed (rotated...) by the applet.
 509  
      */
 510  
     public int getRealMaxHeight() {
 511  3
         return (this.realMaxHeight == Integer.MAX_VALUE) ? this.maxHeight : this.realMaxHeight;
 512  
     }
 513  
 
 514  
     /** @param realMaxHeight the realMaxHeight to set */
 515  
     void setRealMaxHeight(int realMaxHeight) {
 516  25
         this.realMaxHeight = realMaxHeight;
 517  25
     }
 518  
 
 519  
     /**
 520  
      * @return Returns the maxWidth, that should be used by pictures that are transformed (rotated...) by the applet.
 521  
      */
 522  
     public int getRealMaxWidth() {
 523  3
         return (this.realMaxWidth == Integer.MAX_VALUE) ? this.maxWidth : this.realMaxWidth;
 524  
     }
 525  
 
 526  
     /** @param realMaxWidth the realMaxWidth to set */
 527  
     void setRealMaxWidth(int realMaxWidth) {
 528  25
         this.realMaxWidth = realMaxWidth;
 529  25
     }
 530  
 
 531  
     /** @return Returns the targetPictureFormat. */
 532  
     public String getTargetPictureFormat() {
 533  0
         return this.targetPictureFormat;
 534  
     }
 535  
 
 536  
     /**
 537  
      * @return The current ImageFileConversionInfo
 538  
      */
 539  
     public ImageFileConversionInfo getImageFileConversionInfo() {
 540  15
         return this.imageFileConversionInfo;
 541  
     }
 542  
 
 543  
     /**
 544  
      * we expect e.g. "png,bmp:jpg;gif:png;"
 545  
      * 
 546  
      * @param targetPictureFormat the targetPictureFormat to set
 547  
      * @throws JUploadException if the conversionList is erroneous
 548  
      */
 549  
     void setTargetPictureFormat(String targetPictureFormat) throws JUploadException {
 550  25
         this.targetPictureFormat = targetPictureFormat;
 551  25
         this.imageFileConversionInfo = new ImageFileConversionInfo(targetPictureFormat);
 552  25
     }
 553  
 
 554  
     /**
 555  
      * @return <ul>
 556  
      *         <li><code>true</code>, if the the original file extension should be kept</li>
 557  
      *         <li><code>false</code>, if the the original file extension should be changed to the target picture
 558  
      *         format, that the file has been converted to</li>
 559  
      *         </ul>
 560  
      */
 561  
     public boolean getKeepOrigExtension() {
 562  0
         return this.keepOrigExtension;
 563  
     }
 564  
 
 565  
     /**
 566  
      * @param keepOrigExtension if the original file extension should be kept ' <code>true</code>', or changed '
 567  
      *            <code>false</code>' (if the image was converted)
 568  
      */
 569  
     void setKeepOrigExtension(boolean keepOrigExtension) throws JUploadException {
 570  25
         this.keepOrigExtension = keepOrigExtension;
 571  25
     }
 572  
 
 573  
     /**
 574  
      * This method manages the applet parameters that are specific to this class. The super.setProperty method is called
 575  
      * for other properties.
 576  
      * 
 577  
      * @param prop The property which value should change
 578  
      * @param value The new value for this property. If invalid, the default value is used.
 579  
      * @see wjhk.jupload2.policies.UploadPolicy#setProperty(java.lang.String, java.lang.String)
 580  
      */
 581  
     @Override
 582  
     public void setProperty(String prop, String value) throws JUploadException {
 583  
         // The, we check the local properties.
 584  0
         if (prop.equals(PROP_FILE_CHOOSER_IMAGE_PREVIEW)) {
 585  0
             setFileChooserImagePreview(getContext().parseBoolean(value, getFileChooserImagePreview()));
 586  0
         } else if (prop.equals(PROP_HIGH_QUALITY_PREVIEW)) {
 587  0
             setHighQualityPreview(getContext().parseBoolean(value, this.highQualityPreview));
 588  0
         } else if (prop.equals(PROP_MAX_HEIGHT)) {
 589  0
             setMaxHeight(getContext().parseInt(value, this.maxHeight));
 590  0
         } else if (prop.equals(PROP_MAX_WIDTH)) {
 591  0
             setMaxWidth(getContext().parseInt(value, this.maxWidth));
 592  0
         } else if (prop.equals(PROP_PICTURE_COMPRESSION_QUALITY)) {
 593  0
             setPictureCompressionQuality(getContext().parseFloat(value, this.pictureCompressionQuality));
 594  0
         } else if (prop.equals(PROP_PICTURE_TRANSMIT_METADATA)) {
 595  0
             setPictureTransmitMetadata(getContext().parseBoolean(value, this.pictureTransmitMetadata));
 596  0
         } else if (prop.equals(PROP_REAL_MAX_HEIGHT)) {
 597  0
             setRealMaxHeight(getContext().parseInt(value, this.realMaxHeight));
 598  0
         } else if (prop.equals(PROP_REAL_MAX_WIDTH)) {
 599  0
             setRealMaxWidth(getContext().parseInt(value, this.realMaxWidth));
 600  0
         } else if (prop.equals(PROP_TARGET_PICTURE_FORMAT)) {
 601  0
             setTargetPictureFormat(value);
 602  0
         } else if (prop.equals(PROP_KEEP_ORIG_EXTENSION)) {
 603  0
             setKeepOrigExtension(getContext().parseBoolean(value, this.keepOrigExtension));
 604  
         } else {
 605  
             // Otherwise, transmission to the mother class.
 606  0
             super.setProperty(prop, value);
 607  
         }
 608  0
     }
 609  
 
 610  
     /** @see DefaultUploadPolicy#displayParameterStatus() */
 611  
     @Override
 612  
     public void displayParameterStatus() {
 613  0
         super.displayParameterStatus();
 614  
 
 615  0
         displayDebug("======= Parameters managed by PictureUploadPolicy", 30);
 616  0
         displayDebug(PROP_FILE_CHOOSER_IMAGE_PREVIEW + ": " + getFileChooserImagePreview(), 30);
 617  0
         displayDebug(PROP_HIGH_QUALITY_PREVIEW + " : " + this.highQualityPreview, 30);
 618  0
         displayDebug(PROP_PICTURE_COMPRESSION_QUALITY + " : " + getPictureCompressionQuality(), 30);
 619  0
         displayDebug(PROP_PICTURE_TRANSMIT_METADATA + " : " + getPictureTransmitMetadata(), 30);
 620  0
         displayDebug(PROP_MAX_WIDTH + " : " + this.maxWidth + ", " + PROP_MAX_HEIGHT + " : " + this.maxHeight, 30);
 621  0
         displayDebug(PROP_REAL_MAX_WIDTH + " : " + this.realMaxWidth + ", " + PROP_REAL_MAX_HEIGHT + " : "
 622  
                 + this.realMaxHeight, 30);
 623  0
         displayDebug(PROP_STORE_BUFFERED_IMAGE + " : " + this.storeBufferedImage, 30);
 624  0
         displayDebug(PROP_TARGET_PICTURE_FORMAT + " : " + this.targetPictureFormat, 30);
 625  0
         displayDebug("Format conversions : " + getImageFileConversionInfo(), 40);
 626  0
         displayDebug("", 30);
 627  0
     }
 628  
 
 629  
     /**
 630  
      * Calls the {@link DefaultUploadPolicy#setWaitCursor()} method, then erases the picture panel specific cursor.
 631  
      * 
 632  
      * @see DefaultUploadPolicy#setCursor(Cursor)
 633  
      */
 634  
     @Override
 635  
     public Cursor setWaitCursor() {
 636  0
         Cursor previousCursor = super.setWaitCursor();
 637  0
         this.picturePanel.setCursor(null);
 638  0
         return previousCursor;
 639  
     }
 640  
 
 641  
     /**
 642  
      * Calls the {@link DefaultUploadPolicy#setCursor(Cursor)} method, then set the picture panel specific cursor.
 643  
      * 
 644  
      * @see DefaultUploadPolicy#setCursor(Cursor)
 645  
      */
 646  
     @Override
 647  
     public Cursor setCursor(Cursor cursor) {
 648  0
         Cursor oldCursor = super.setCursor(null);
 649  0
         this.picturePanel.setCursor(new Cursor(Cursor.HAND_CURSOR));
 650  0
         return oldCursor;
 651  
     }
 652  
 
 653  
     /**
 654  
      * Creates the file chooser, from the default implementation, then add an accessory to preview pictures.
 655  
      * 
 656  
      * @see UploadPolicy#createFileChooser()
 657  
      */
 658  
     @Override
 659  
     public JUploadFileChooser createFileChooser() {
 660  0
         JUploadFileChooser jufc = super.createFileChooser();
 661  0
         if (getFileChooserImagePreview()) {
 662  0
             jufc.setAccessory(new JUploadImagePreview(jufc, this));
 663  
         }
 664  0
         return jufc;
 665  
     }
 666  
 
 667  
     /**
 668  
      * Returns an icon, calculated from the image content. Currently only pictures managed by ImageIO can be displayed.
 669  
      * Once upon a day, extracting the first picture of a video may become reality... ;-) <BR>
 670  
      * Note: this method is called in a dedicated thread by the JUploadFileChooser, to avoid to calculate the icon for
 671  
      * all pictures, when opening a new folder.
 672  
      * 
 673  
      * @return The calculated ImageIcon, or null if no picture can be extracted.
 674  
      * @see UploadPolicy#fileViewGetIcon(File)
 675  
      * @see UploadPolicy#PROP_FILE_CHOOSER_ICON_FROM_FILE_CONTENT
 676  
      */
 677  
     @Override
 678  
     public Icon fileViewGetIcon(File file) {
 679  
         try {
 680  0
             return PictureFileData.getImageIcon(file, getFileChooserIconSize(), getFileChooserIconSize(), this);
 681  0
         } catch (JUploadException e) {
 682  0
             displayErr(e);
 683  0
             return null;
 684  
         }
 685  
     }
 686  
 
 687  
     /**
 688  
      * @see wjhk.jupload2.policies.DefaultUploadPolicy#getUploadFilename(wjhk.jupload2.filedata.FileData, int)
 689  
      */
 690  
     @Override
 691  
     public String getUploadFilename(FileData fileData, int index) throws JUploadException {
 692  0
         String fileName = fileData.getFileName();
 693  0
         if (!this.keepOrigExtension) {
 694  0
             String targetFormatOrNull = this.imageFileConversionInfo.getTargetFormatOrNull(fileData.getFileExtension());
 695  0
             if (targetFormatOrNull != null) {
 696  
 
 697  0
                 int endIndex = fileName.length() - fileData.getFileExtension().length();
 698  0
                 StringBuilder newFilename = new StringBuilder(fileName.substring(0, endIndex));
 699  0
                 newFilename.append(targetFormatOrNull);
 700  0
                 fileName = newFilename.toString();
 701  
             }
 702  
         }
 703  
 
 704  0
         return getEncodedFilename(fileName);
 705  
     }
 706  
 
 707  
     /**
 708  
      * Implementation of the ImageObserver interface
 709  
      * 
 710  
      * @param arg0
 711  
      * @param arg1
 712  
      * @param arg2
 713  
      * @param arg3
 714  
      * @param arg4
 715  
      * @param arg5
 716  
      * @return true or false
 717  
      */
 718  
     public boolean imageUpdate(Image arg0, int arg1, int arg2, int arg3, int arg4, int arg5) {
 719  0
         return true;
 720  
     }
 721  
 }