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 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 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 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 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 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 private int realMaxWidth = -1;
176
177 /**
178 * @see UploadPolicy
179 */
180 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 super(juploadContext);
205
206 // Creation of the PictureFileDataPolicy, from parameters given to the
207 // applet, or from default values.
208 setFileChooserImagePreview(juploadContext.getParameter(PROP_FILE_CHOOSER_IMAGE_PREVIEW,
209 DEFAULT_FILE_CHOOSER_IMAGE_PREVIEW));
210 setHighQualityPreview(juploadContext.getParameter(PROP_HIGH_QUALITY_PREVIEW, DEFAULT_HIGH_QUALITY_PREVIEW));
211 setMaxHeight(juploadContext.getParameter(PROP_MAX_HEIGHT, DEFAULT_MAX_HEIGHT));
212 setMaxWidth(juploadContext.getParameter(PROP_MAX_WIDTH, DEFAULT_MAX_WIDTH));
213 setPictureCompressionQuality(juploadContext.getParameter(PROP_PICTURE_COMPRESSION_QUALITY,
214 DEFAULT_PICTURE_COMPRESSION_QUALITY));
215 setPictureTransmitMetadata(juploadContext.getParameter(PROP_PICTURE_TRANSMIT_METADATA,
216 DEFAULT_PICTURE_TRANSMIT_METADATA));
217 setRealMaxHeight(juploadContext.getParameter(PROP_REAL_MAX_HEIGHT, DEFAULT_REAL_MAX_HEIGHT));
218 setRealMaxWidth(juploadContext.getParameter(PROP_REAL_MAX_WIDTH, DEFAULT_REAL_MAX_WIDTH));
219 setTargetPictureFormat(juploadContext.getParameter(PROP_TARGET_PICTURE_FORMAT, DEFAULT_TARGET_PICTURE_FORMAT));
220
221 setKeepOrigExtension(juploadContext.getParameter(PROP_KEEP_ORIG_EXTENSION, DEFAULT_KEEP_ORIG_EXTENSION));
222
223 displayDebug("[PictureUploadPolicy] end of constructor", 30);
224 }
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 FileData defaultFileData = super.createFileData(file);
238
239 if (defaultFileData == null) {
240 // The file is not allowed.
241 return null;
242 } else {
243 // Ok, the file is to be accepted. Is it a picture?
244 PictureFileData pfd = null;
245 try {
246 pfd = new PictureFileData(file, this);
247 } catch (JUploadIOException e) {
248 displayErr(e);
249 }
250
251 // If we get a pfd, let' check that it's a picture.
252 if (pfd != null && pfd.isPicture()) {
253 return pfd;
254 } 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 return defaultFileData;
259 } else {
260 // We now use the JUploadExceptionStopAddingFiles exception, to
261 // allow the user to stop adding files.
262 String msg = getLocalizedString("notAPicture", file.getName());
263
264 // Alert only once, when several files are not pictures... hum,
265 displayWarn(msg);
266 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 throw new JUploadExceptionStopAddingFiles("Stopped by the user");
273 }
274 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 this.rotateLeftButton = new JButton(getLocalizedString("buttonRotateLeft"));
296 this.rotateLeftButton.setIcon(new ImageIcon(getClass().getResource("/images/rotateLeft.gif")));
297 this.rotateLeftButton.addActionListener(this);
298 this.rotateLeftButton.addMouseListener(jUploadPanel.getMouseListener());
299 this.rotateLeftButton.setEnabled(false);
300
301 this.rotateRightButton = new JButton(getLocalizedString("buttonRotateRight"));
302 this.rotateRightButton.setIcon(new ImageIcon(getClass().getResource("/images/rotateRight.gif")));
303 this.rotateRightButton.addActionListener(this);
304 this.rotateRightButton.addMouseListener(jUploadPanel.getMouseListener());
305 this.rotateRightButton.setEnabled(false);
306
307 // The button bar
308 JPanel buttonPanel = new JPanel();
309 buttonPanel.setLayout(new GridLayout(5, 1, 5, 5));
310 buttonPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 5));
311 buttonPanel.add(browse);
312 buttonPanel.add(this.rotateLeftButton);
313 buttonPanel.add(this.rotateRightButton);
314 buttonPanel.add(removeAll);
315 buttonPanel.add(remove);
316
317 // The preview PicturePanel
318 JPanel pPanel = new JPanel();
319 pPanel.setLayout(new GridLayout(1, 1));
320 pPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 10));
321
322 this.picturePanel = new PicturePanel(true, this);
323 this.picturePanel.addMouseListener(jUploadPanel.getMouseListener());
324 pPanel.add(this.picturePanel);
325 // Setting specific cursor for this panel, default for other parts of
326 // the applet.
327 setCursor(null);
328
329 // And last but not least ... creation of the top panel:
330 JPanel topPanel = new JPanel();
331 topPanel.setLayout(new GridLayout(1, 2));
332 topPanel.add(buttonPanel);
333 topPanel.add(pPanel);
334
335 jUploadPanel.getJComponent().setBorder(BorderFactory.createLineBorder(SystemColor.controlDkShadow));
336
337 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 displayInfo("Action : " + e.getActionCommand());
348 if (e.getActionCommand() == this.rotateLeftButton.getActionCommand()) {
349 this.picturePanel.rotate(-1);
350 } else if (e.getActionCommand() == this.rotateRightButton.getActionCommand()) {
351 this.picturePanel.rotate(1);
352 }
353 }// actionPerformed
354
355 /**
356 * @see wjhk.jupload2.policies.UploadPolicy#onFileSelected(wjhk.jupload2.filedata.FileData)
357 */
358 @Override
359 public void onFileSelected(FileData fileData) {
360 if (fileData != null) {
361 displayDebug("File selected: " + fileData.getFileName(), 30);
362 }
363 if (this.picturePanel != null) {
364 // If this file is a picture, we display it.
365 if (fileData instanceof PictureFileData) {
366 Cursor previousCursor = setWaitCursor();
367 this.picturePanel.setPictureFile((PictureFileData) fileData, this.rotateLeftButton,
368 this.rotateRightButton);
369 setCursor(previousCursor);
370 } else {
371 this.picturePanel.setPictureFile(null, this.rotateLeftButton, this.rotateRightButton);
372 }
373 }
374 }
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 if (pictureFileData == null) {
385 // No action
386 } else if (!(pictureFileData instanceof PictureFileData)) {
387 displayWarn("PictureUploadPolicy: received a non PictureFileData in onFileDoubleClicked");
388 } else {
389 new PictureDialog(null, (PictureFileData) pictureFileData, this);
390 }
391 }
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 getContext().getUploadPanel().getFilePanel().clearSelection();
400 if (this.picturePanel != null) {
401 this.picturePanel.setPictureFile(null, this.rotateLeftButton, this.rotateRightButton);
402 }
403
404 // Then, we call the standard action, if any.
405 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 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 this.fileChooserImagePreview = fileChooserImagePreview;
431 }
432
433 /** @return the applet parameter <I>highQualityPreview</I>. */
434 public boolean getHighQualityPreview() {
435 return this.highQualityPreview;
436 }
437
438 /** @param highQualityPreview the highQualityPreview to set */
439 void setHighQualityPreview(boolean highQualityPreview) {
440 this.highQualityPreview = highQualityPreview;
441 }
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 return this.maxHeight;
448 }
449
450 /** @param maxHeight the maxHeight to set */
451 void setMaxHeight(int maxHeight) {
452 if (maxHeight <= 0) {
453 this.maxHeight = Integer.MAX_VALUE;
454 displayWarn("[setMaxHeight] maxHeight switched from " + maxHeight + " to " + this.maxHeight);
455 } else {
456 this.maxHeight = maxHeight;
457 }
458 }
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 return this.maxWidth;
465 }
466
467 /** @param maxWidth the maxWidth to set */
468 void setMaxWidth(int maxWidth) {
469 if (maxWidth <= 0) {
470 this.maxWidth = Integer.MAX_VALUE;
471 displayWarn("[setMaxWidth] maxWidth switched from " + maxWidth + " to " + this.maxWidth);
472 } else {
473 this.maxWidth = maxWidth;
474 }
475 }
476
477 /**
478 * @return The current value for picture compression.
479 */
480 public float getPictureCompressionQuality() {
481 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 this.pictureCompressionQuality = pictureCompressionQuality;
490 }
491
492 /**
493 * @return The current value for transmission (or no transmission) of picture metadata.
494 */
495 public boolean getPictureTransmitMetadata() {
496 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 this.pictureTransmitMetadata = pictureTransmitMetadata;
505 }
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 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 this.realMaxHeight = realMaxHeight;
517 }
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 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 this.realMaxWidth = realMaxWidth;
529 }
530
531 /** @return Returns the targetPictureFormat. */
532 public String getTargetPictureFormat() {
533 return this.targetPictureFormat;
534 }
535
536 /**
537 * @return The current ImageFileConversionInfo
538 */
539 public ImageFileConversionInfo getImageFileConversionInfo() {
540 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 this.targetPictureFormat = targetPictureFormat;
551 this.imageFileConversionInfo = new ImageFileConversionInfo(targetPictureFormat);
552 }
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 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 this.keepOrigExtension = keepOrigExtension;
571 }
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 if (prop.equals(PROP_FILE_CHOOSER_IMAGE_PREVIEW)) {
585 setFileChooserImagePreview(getContext().parseBoolean(value, getFileChooserImagePreview()));
586 } else if (prop.equals(PROP_HIGH_QUALITY_PREVIEW)) {
587 setHighQualityPreview(getContext().parseBoolean(value, this.highQualityPreview));
588 } else if (prop.equals(PROP_MAX_HEIGHT)) {
589 setMaxHeight(getContext().parseInt(value, this.maxHeight));
590 } else if (prop.equals(PROP_MAX_WIDTH)) {
591 setMaxWidth(getContext().parseInt(value, this.maxWidth));
592 } else if (prop.equals(PROP_PICTURE_COMPRESSION_QUALITY)) {
593 setPictureCompressionQuality(getContext().parseFloat(value, this.pictureCompressionQuality));
594 } else if (prop.equals(PROP_PICTURE_TRANSMIT_METADATA)) {
595 setPictureTransmitMetadata(getContext().parseBoolean(value, this.pictureTransmitMetadata));
596 } else if (prop.equals(PROP_REAL_MAX_HEIGHT)) {
597 setRealMaxHeight(getContext().parseInt(value, this.realMaxHeight));
598 } else if (prop.equals(PROP_REAL_MAX_WIDTH)) {
599 setRealMaxWidth(getContext().parseInt(value, this.realMaxWidth));
600 } else if (prop.equals(PROP_TARGET_PICTURE_FORMAT)) {
601 setTargetPictureFormat(value);
602 } else if (prop.equals(PROP_KEEP_ORIG_EXTENSION)) {
603 setKeepOrigExtension(getContext().parseBoolean(value, this.keepOrigExtension));
604 } else {
605 // Otherwise, transmission to the mother class.
606 super.setProperty(prop, value);
607 }
608 }
609
610 /** @see DefaultUploadPolicy#displayParameterStatus() */
611 @Override
612 public void displayParameterStatus() {
613 super.displayParameterStatus();
614
615 displayDebug("======= Parameters managed by PictureUploadPolicy", 30);
616 displayDebug(PROP_FILE_CHOOSER_IMAGE_PREVIEW + ": " + getFileChooserImagePreview(), 30);
617 displayDebug(PROP_HIGH_QUALITY_PREVIEW + " : " + this.highQualityPreview, 30);
618 displayDebug(PROP_PICTURE_COMPRESSION_QUALITY + " : " + getPictureCompressionQuality(), 30);
619 displayDebug(PROP_PICTURE_TRANSMIT_METADATA + " : " + getPictureTransmitMetadata(), 30);
620 displayDebug(PROP_MAX_WIDTH + " : " + this.maxWidth + ", " + PROP_MAX_HEIGHT + " : " + this.maxHeight, 30);
621 displayDebug(PROP_REAL_MAX_WIDTH + " : " + this.realMaxWidth + ", " + PROP_REAL_MAX_HEIGHT + " : "
622 + this.realMaxHeight, 30);
623 displayDebug(PROP_STORE_BUFFERED_IMAGE + " : " + this.storeBufferedImage, 30);
624 displayDebug(PROP_TARGET_PICTURE_FORMAT + " : " + this.targetPictureFormat, 30);
625 displayDebug("Format conversions : " + getImageFileConversionInfo(), 40);
626 displayDebug("", 30);
627 }
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 Cursor previousCursor = super.setWaitCursor();
637 this.picturePanel.setCursor(null);
638 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 Cursor oldCursor = super.setCursor(null);
649 this.picturePanel.setCursor(new Cursor(Cursor.HAND_CURSOR));
650 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 JUploadFileChooser jufc = super.createFileChooser();
661 if (getFileChooserImagePreview()) {
662 jufc.setAccessory(new JUploadImagePreview(jufc, this));
663 }
664 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 return PictureFileData.getImageIcon(file, getFileChooserIconSize(), getFileChooserIconSize(), this);
681 } catch (JUploadException e) {
682 displayErr(e);
683 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 String fileName = fileData.getFileName();
693 if (!this.keepOrigExtension) {
694 String targetFormatOrNull = this.imageFileConversionInfo.getTargetFormatOrNull(fileData.getFileExtension());
695 if (targetFormatOrNull != null) {
696
697 int endIndex = fileName.length() - fileData.getFileExtension().length();
698 StringBuilder newFilename = new StringBuilder(fileName.substring(0, endIndex));
699 newFilename.append(targetFormatOrNull);
700 fileName = newFilename.toString();
701 }
702 }
703
704 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 return true;
720 }
721 }