1 | // |
---|
2 | // $Id: PicturePanel.java 95 2007-05-02 03:27:05 +0000 (mer., 02 mai 2007) |
---|
3 | // /C=DE/ST=Baden-Wuerttemberg/O=ISDN4Linux/OU=Fritz |
---|
4 | // Elfert/CN=svn-felfert@isdn4linux.de/emailAddress=fritz@fritz-elfert.de $ |
---|
5 | // |
---|
6 | // jupload - A file upload applet. |
---|
7 | // Copyright 2007 The JUpload Team |
---|
8 | // Copyright 2002 Guillaume Chamberland-Larose |
---|
9 | // |
---|
10 | // Created: ? |
---|
11 | // Creator: William JinHua Kwong |
---|
12 | // Last modified: $Date: 2009-07-15 11:45:06 -0300 (Qua, 15 Jul 2009) $ |
---|
13 | // |
---|
14 | // This program is free software; you can redistribute it and/or modify it under |
---|
15 | // the terms of the GNU General Public License as published by the Free Software |
---|
16 | // Foundation; either version 2 of the License, or (at your option) any later |
---|
17 | // version. This program is distributed in the hope that it will be useful, but |
---|
18 | // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
19 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
---|
20 | // details. You should have received a copy of the GNU General Public License |
---|
21 | // along with this program; if not, write to the Free Software Foundation, Inc., |
---|
22 | // 675 Mass Ave, Cambridge, MA 02139, USA. |
---|
23 | |
---|
24 | package wjhk.jupload2.gui.image; |
---|
25 | |
---|
26 | import java.awt.Canvas; |
---|
27 | import java.awt.Cursor; |
---|
28 | import java.awt.Graphics; |
---|
29 | import java.awt.Image; |
---|
30 | import java.awt.event.ComponentEvent; |
---|
31 | import java.awt.event.ComponentListener; |
---|
32 | import java.awt.event.MouseEvent; |
---|
33 | import java.awt.event.MouseListener; |
---|
34 | |
---|
35 | import javax.swing.AbstractButton; |
---|
36 | |
---|
37 | import wjhk.jupload2.exception.JUploadException; |
---|
38 | import wjhk.jupload2.filedata.PictureFileData; |
---|
39 | import wjhk.jupload2.policies.UploadPolicy; |
---|
40 | |
---|
41 | /** |
---|
42 | * This panel is used to preview picture, when PictureUploadPolicy (or one of |
---|
43 | * its inherited policy) is used. Manages the panel where pictures are |
---|
44 | * displayed. <BR> |
---|
45 | * Each time a user selects a file in the panel file, the PictureUploadPolicy |
---|
46 | * calls |
---|
47 | * {@link #setPictureFile(PictureFileData, AbstractButton, AbstractButton)}. I |
---|
48 | * did an attempt to store the Image generated for the Panel size into the |
---|
49 | * PictureFileData, to avoid to calculate the offscreenPicture each time the |
---|
50 | * user select the same file again. But it doesn't work: the applet quickly runs |
---|
51 | * out of memory, even after numerous calls of System.gc and finalize. <BR> |
---|
52 | * <BR> |
---|
53 | * This file is taken from the PictureApplet ((C) 2002 Guillaume |
---|
54 | * Chamberland-Larose), available here: To contact Guillaume Chamberland-Larose |
---|
55 | * for bugs, patches, suggestions: Please use the forums on the sourceforge web |
---|
56 | * page for this project, located at: |
---|
57 | * http://sourceforge.net/projects/picture-applet/ Updated : 2006 etienne_sf<BR> |
---|
58 | * This program is free software; you can redistribute it and/or modify it under |
---|
59 | * the terms of the GNU General Public License as published by the Free Software |
---|
60 | * Foundation; either version 2 of the License, or (at your option) any later |
---|
61 | * version. <BR> |
---|
62 | * This program is distributed in the hope that it will be useful, but WITHOUT |
---|
63 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
---|
64 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
---|
65 | * details. <BR> |
---|
66 | * You should have received a copy of the GNU General Public License along with |
---|
67 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
---|
68 | * Place - Suite 330, Boston, MA 02111-1307, USA. |
---|
69 | */ |
---|
70 | |
---|
71 | public class PicturePanel extends Canvas implements MouseListener, |
---|
72 | ComponentListener { |
---|
73 | |
---|
74 | /** A generated serialVersionUID, to avoid warning during compilation */ |
---|
75 | private static final long serialVersionUID = -3439340009940699981L; |
---|
76 | |
---|
77 | private PictureFileData pictureFileData; |
---|
78 | |
---|
79 | /** |
---|
80 | * offscreenImage contains an image, that can be asked by |
---|
81 | * {@link PictureFileData#getImage(Canvas, boolean)}. It is used to preview |
---|
82 | * this picture. |
---|
83 | */ |
---|
84 | private Image offscreenImage = null; |
---|
85 | |
---|
86 | /** |
---|
87 | * Indicates if the offscreen image should be calculated once and stored, to |
---|
88 | * avoid to calculate it again. <BR> |
---|
89 | * Indications: the offscreen image should be calculate only once for the |
---|
90 | * picturePanel on the applet, and for each display when the user ask to |
---|
91 | * display the fulscreen picture (by a click on the picturePanel). |
---|
92 | */ |
---|
93 | private boolean hasToStoreOffscreenPicture = false; |
---|
94 | |
---|
95 | /** |
---|
96 | * The current upload policy. |
---|
97 | */ |
---|
98 | protected UploadPolicy uploadPolicy; |
---|
99 | |
---|
100 | /** |
---|
101 | * Standard constructor. |
---|
102 | * |
---|
103 | * @param hasToStoreOffscreenPicture |
---|
104 | * @param uploadPolicy The current upload policy |
---|
105 | */ |
---|
106 | public PicturePanel(boolean hasToStoreOffscreenPicture, |
---|
107 | UploadPolicy uploadPolicy) { |
---|
108 | super(); |
---|
109 | |
---|
110 | this.hasToStoreOffscreenPicture = hasToStoreOffscreenPicture; |
---|
111 | this.uploadPolicy = uploadPolicy; |
---|
112 | |
---|
113 | // We want to trap the mouse actions on this picture. |
---|
114 | addMouseListener(this); |
---|
115 | |
---|
116 | // We want to know when a resize event occurs (to recalculate |
---|
117 | // offscreenImage) |
---|
118 | addComponentListener(this); |
---|
119 | } |
---|
120 | |
---|
121 | /** |
---|
122 | * This setter is called by {@link PictureFileData} to set the picture that |
---|
123 | * is to be previewed. |
---|
124 | * |
---|
125 | * @param pictureFileData The FileData for the image to be displayed. Null |
---|
126 | * if no picture should be displayed. |
---|
127 | * @param button1 A button that will be activated or not, depending of the |
---|
128 | * pictures was correctly set into the panel. May be null, if not |
---|
129 | * button is to be enabled. |
---|
130 | * @param button2 Another button that will be activated or not. May also be |
---|
131 | * null. |
---|
132 | */ |
---|
133 | public void setPictureFile(PictureFileData pictureFileData, |
---|
134 | AbstractButton button1, AbstractButton button2) { |
---|
135 | // First : reset current picture configuration. |
---|
136 | this.pictureFileData = null; |
---|
137 | if (this.offscreenImage != null) { |
---|
138 | this.offscreenImage.flush(); |
---|
139 | this.offscreenImage = null; |
---|
140 | } |
---|
141 | |
---|
142 | // Ask for an immediate repaint, to clear the panel (as offscreenImage |
---|
143 | // is now null). |
---|
144 | repaint(); |
---|
145 | |
---|
146 | // Then, we store the new picture data, get the offscreen picture and |
---|
147 | // ask for a repaint. |
---|
148 | boolean enableButton = false; |
---|
149 | if (pictureFileData != null && pictureFileData.canRead()) { |
---|
150 | this.pictureFileData = pictureFileData; |
---|
151 | |
---|
152 | // A picture has been selected. The buttons must be enabled. |
---|
153 | enableButton = true; |
---|
154 | |
---|
155 | // Now, we display this picture. |
---|
156 | calculateOffscreenImage(); |
---|
157 | repaint(); |
---|
158 | } |
---|
159 | |
---|
160 | // Let's activate the given button ... if any. |
---|
161 | if (button1 != null) { |
---|
162 | button1.setEnabled(enableButton); |
---|
163 | } |
---|
164 | if (button2 != null) { |
---|
165 | button2.setEnabled(enableButton); |
---|
166 | } |
---|
167 | } |
---|
168 | |
---|
169 | /** |
---|
170 | * @see java.awt.Canvas#paint(java.awt.Graphics) |
---|
171 | */ |
---|
172 | @Override |
---|
173 | public void paint(Graphics g) { |
---|
174 | // First : clear the panel area. |
---|
175 | g.clearRect(0, 0, getWidth(), getHeight()); |
---|
176 | |
---|
177 | /* |
---|
178 | * The picture is calculated outside of the paint() event. See: |
---|
179 | * calculateOffscreenImage() and componentResized. //Then, check if we |
---|
180 | * must calculate the picture. if (pictureFileData != null) { //Now, we |
---|
181 | * calculate the picture if we don't already have one. if |
---|
182 | * (offscreenImage == null) { calculateOffscreenImage(); } } |
---|
183 | */ |
---|
184 | |
---|
185 | // Then, display the picture, if any is defined. |
---|
186 | if (this.offscreenImage != null) { |
---|
187 | // Let's center this picture |
---|
188 | int hMargin = (getWidth() - this.offscreenImage.getWidth(this)) / 2; |
---|
189 | int vMargin = (getHeight() - this.offscreenImage.getHeight(this)) / 2; |
---|
190 | g.drawImage(this.offscreenImage, hMargin, vMargin, this); |
---|
191 | // Free the used memory. |
---|
192 | this.offscreenImage.flush(); |
---|
193 | } else { |
---|
194 | this.uploadPolicy.displayDebug( |
---|
195 | "PicturePanel.paint(): offscreenImage is null", 50); |
---|
196 | } |
---|
197 | } |
---|
198 | |
---|
199 | /** |
---|
200 | * This function adds a quarter rotation to the current picture. |
---|
201 | * |
---|
202 | * @param quarter Number of quarters (90ᅵ) the picture should rotate. 1 |
---|
203 | * means rotating of 90ᅵ clockwise (?). Can be negative |
---|
204 | * (counterclockwise), more than 1... |
---|
205 | */ |
---|
206 | public void rotate(int quarter) { |
---|
207 | if (this.pictureFileData != null) { |
---|
208 | Cursor previousCursor = this.uploadPolicy.setWaitCursor(); |
---|
209 | this.pictureFileData.addRotation(quarter); |
---|
210 | // The previously calculated picture is now wrong. |
---|
211 | this.offscreenImage.flush(); |
---|
212 | this.offscreenImage = null; |
---|
213 | calculateOffscreenImage(); |
---|
214 | |
---|
215 | repaint(); |
---|
216 | this.uploadPolicy.setCursor(previousCursor); |
---|
217 | } else { |
---|
218 | this.uploadPolicy |
---|
219 | .displayWarn("Hum, this is really strange: there is no pictureFileData in the PicturePanel! Command is ignored."); |
---|
220 | } |
---|
221 | } |
---|
222 | |
---|
223 | /** |
---|
224 | * This method get the offscreenImage from the current pictureFileData. This |
---|
225 | * image is null, if pictureFileData is null. In this case, the repaint will |
---|
226 | * only clear the panel rectangle, on the screen. |
---|
227 | */ |
---|
228 | private void calculateOffscreenImage() { |
---|
229 | if (this.pictureFileData == null) { |
---|
230 | // Nothing to do. offscreenImage should be null. |
---|
231 | if (this.offscreenImage != null) { |
---|
232 | this.offscreenImage = null; |
---|
233 | this.uploadPolicy |
---|
234 | .displayWarn("PicturePanel.calculateOffscreenImage(): pictureFileData is null (offscreenImage set to null"); |
---|
235 | } |
---|
236 | } else if (this.offscreenImage == null) { |
---|
237 | this.uploadPolicy |
---|
238 | .displayDebug( |
---|
239 | "PicturePanel.calculateOffscreenImage(): trying to calculate offscreenImage (PicturePanel.calculateOffscreenImage()", |
---|
240 | 30); |
---|
241 | try { |
---|
242 | this.offscreenImage = this.pictureFileData.getImage(this, |
---|
243 | this.hasToStoreOffscreenPicture); |
---|
244 | } catch (JUploadException e) { |
---|
245 | this.uploadPolicy.displayErr(e); |
---|
246 | // We won't try to display the picture for this file. |
---|
247 | this.pictureFileData = null; |
---|
248 | this.offscreenImage = null; |
---|
249 | } |
---|
250 | } |
---|
251 | } |
---|
252 | |
---|
253 | /** |
---|
254 | * Is it really useful ?? |
---|
255 | */ |
---|
256 | @Override |
---|
257 | protected void finalize() throws Throwable { |
---|
258 | // super.finalize(); |
---|
259 | this.uploadPolicy.displayDebug("Within PicturePanel.finalize()", 10); |
---|
260 | |
---|
261 | if (this.offscreenImage != null) { |
---|
262 | this.offscreenImage.flush(); |
---|
263 | } |
---|
264 | } |
---|
265 | |
---|
266 | // //////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
267 | // /////////////////////// MouseListener interface |
---|
268 | // //////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
269 | /** @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent) */ |
---|
270 | public void mouseClicked(MouseEvent arg0) { |
---|
271 | if (this.pictureFileData != null) { |
---|
272 | // Ok, we have a picture. Let's display it. |
---|
273 | this.uploadPolicy.onFileDoubleClicked(this.pictureFileData); |
---|
274 | } |
---|
275 | } |
---|
276 | |
---|
277 | /** @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent) */ |
---|
278 | public void mouseEntered(MouseEvent arg0) { |
---|
279 | // Nothing to do. |
---|
280 | } |
---|
281 | |
---|
282 | /** @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent) */ |
---|
283 | public void mouseExited(MouseEvent arg0) { |
---|
284 | // Nothing to do. |
---|
285 | } |
---|
286 | |
---|
287 | /** @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent) */ |
---|
288 | public void mousePressed(MouseEvent arg0) { |
---|
289 | // Nothing to do. |
---|
290 | } |
---|
291 | |
---|
292 | /** @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent) */ |
---|
293 | public void mouseReleased(MouseEvent arg0) { |
---|
294 | // Nothing to do. |
---|
295 | } |
---|
296 | |
---|
297 | // //////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
298 | // /////////////////////// ComponentListener interface |
---|
299 | // //////////////////////////////////////////// |
---|
300 | // //////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
301 | /** |
---|
302 | * @see java.awt.event.ComponentListener#componentHidden(java.awt.event.ComponentEvent) |
---|
303 | */ |
---|
304 | public void componentHidden(ComponentEvent arg0) { |
---|
305 | // No action |
---|
306 | } |
---|
307 | |
---|
308 | /** |
---|
309 | * @see java.awt.event.ComponentListener#componentMoved(java.awt.event.ComponentEvent) |
---|
310 | */ |
---|
311 | public void componentMoved(ComponentEvent arg0) { |
---|
312 | // No action |
---|
313 | } |
---|
314 | |
---|
315 | /** |
---|
316 | * @see java.awt.event.ComponentListener#componentResized(java.awt.event.ComponentEvent) |
---|
317 | */ |
---|
318 | public void componentResized(ComponentEvent arg0) { |
---|
319 | this.uploadPolicy.displayDebug("Within componentResized", 10); |
---|
320 | if (this.offscreenImage != null) { |
---|
321 | this.offscreenImage.flush(); |
---|
322 | this.offscreenImage = null; |
---|
323 | } |
---|
324 | |
---|
325 | // Then we calculate a new image for this panel. |
---|
326 | calculateOffscreenImage(); |
---|
327 | repaint(); |
---|
328 | } |
---|
329 | |
---|
330 | /** |
---|
331 | * @see java.awt.event.ComponentListener#componentShown(java.awt.event.ComponentEvent) |
---|
332 | */ |
---|
333 | public void componentShown(ComponentEvent arg0) { |
---|
334 | // No action |
---|
335 | } |
---|
336 | } |
---|