View Javadoc
1   //
2   // $Id: DialogPicturePanel.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   //
9   // Created: 2006-07-11
10  // Creator: etienne_sf
11  // Last modified: $Date: 2009-02-16 12:42:50 +0100 (lun., 16 févr. 2009) $
12  //
13  // This program is free software; you can redistribute it and/or modify it under
14  // the terms of the GNU General Public License as published by the Free Software
15  // Foundation; either version 2 of the License, or (at your option) any later
16  // version. This program is distributed in the hope that it will be useful, but
17  // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
19  // details. You should have received a copy of the GNU General Public License
20  // along with this program; if not, write to the Free Software Foundation, Inc.,
21  // 675 Mass Ave, Cambridge, MA 02139, USA.
22  
23  package wjhk.jupload2.gui;
24  
25  import java.awt.BorderLayout;
26  import java.awt.Cursor;
27  import java.awt.Dimension;
28  import java.awt.Frame;
29  import java.awt.event.ActionEvent;
30  import java.awt.event.ActionListener;
31  import java.awt.event.ComponentEvent;
32  import java.awt.event.ComponentListener;
33  import java.lang.reflect.InvocationTargetException;
34  
35  import javax.swing.BorderFactory;
36  import javax.swing.Box;
37  import javax.swing.BoxLayout;
38  import javax.swing.JButton;
39  import javax.swing.JDialog;
40  import javax.swing.JPanel;
41  import javax.swing.JTextArea;
42  import javax.swing.Timer;
43  
44  import wjhk.jupload2.exception.JUploadException;
45  import wjhk.jupload2.policies.UploadPolicy;
46  
47  /**
48   * This JDialog displays a message to the user, to allow him to accept or refuse
49   * a retry of an upload, when a 'resumable upload error' occurs. The message is
50   * displayed, followed by a timer countdown. When the timer value falls to 0,
51   * the retry is automatically executed. This allows the user to quit is screen,
52   * and have automatic retries, even for long upload.
53   * 
54   * @author etienne_sf
55   */
56  @SuppressWarnings("serial")
57  public class DialogUploadRetry extends JDialog implements ActionListener,
58          ComponentListener {
59  
60      JButton buttonYes;
61  
62      JButton buttonNo;
63  
64      JButton buttonDetails;
65  
66      JTextArea jtextArea;
67  
68      JTextArea detailTestArea;
69  
70      JUploadException juploadException = null;
71  
72      UploadPolicy uploadPolicy = null;
73  
74      /**
75       * This timer allows the display of seconds countdown before automatic
76       * retry, to the user
77       */
78      Timer countdownTimer = null;
79  
80      /**
81       * How many seconds, before automatic validation (response=yes) of this
82       * dialog box
83       */
84      int countdownValue;
85  
86      /**
87       * Indicates whether the user choosed to accept or refuse the retry. If the
88       * countdown falls to 0, this boolean is switched to true, for an automatic
89       * retry.
90       */
91      boolean retryValidated = false;
92  
93      /**
94       * Creates a new instance.
95       * 
96       * @param owner The parent frame. Mandatory, as this is a modal dialog.
97       * @param juploadException The exception, which occurs. Used to present an
98       *            error message.
99       * @param numRetry number of the current retry
100      * @param uploadPolicy The upload policy which applies.
101      * @throws JUploadException
102      */
103     public DialogUploadRetry(Frame owner, JUploadException juploadException,
104             int numRetry, UploadPolicy uploadPolicy) throws JUploadException {
105         super(owner, uploadPolicy.getLocalizedString("dialogUploadRetryTitle"),
106                 true);
107 
108         this.uploadPolicy = uploadPolicy;
109         this.juploadException = juploadException;
110 
111         // Creation of the countdown timer.
112         // The number of seconds between two retries is exponentiel: as
113         // parameterized at the beginning, then more and more time between two
114         // uploads.
115         // The first retry should use the applet parameter value, so, we should
116         // have pow(1.5, 0) for this one. Actually, the first call to this
117         // dialog occurs after the first try, so numRetry is 0 then.
118         double retryDelayFactor = Math.pow(1.5, numRetry);
119         this.countdownValue = (int) (uploadPolicy.getRetryNbSecondsBetween() * retryDelayFactor);
120         this.countdownTimer = new Timer(1000, this);
121         this.countdownTimer.start();
122 
123         // Creates the components. This must be done in the AWT event
124         // dispatching thread.
125         try {
126             javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
127                 public void run() {
128                     createGUI();
129                 }
130             });
131         } catch (InterruptedException e) {
132             throw new JUploadException("Error while creating the "
133                     + this.getClass().getName(), e.getCause());
134         } catch (InvocationTargetException e) {
135             throw new JUploadException("Error while creating the "
136                     + this.getClass().getName(), e.getCause());
137         }
138 
139         // The dialog is modal: the next line will return when the DialogPicture
140         // is hidden (to be closed, in our case)
141         // But we want to know when it will becom visible, to clear the wait
142         // cursor.
143         setVisible(true);
144 
145         // We arrive here, when the dialog is closed.
146     }
147 
148     /**
149      * This method allows the caller, to know if the retry of the last upload
150      * should be executed.
151      * 
152      * @return the retryValidated
153      */
154     public boolean isRetryValidated() {
155         return this.retryValidated;
156     }
157 
158     /**
159      * Creation of the GUI, based on the current parameters
160      */
161     private void createGUI() {
162         // //////////////////////////////////////////////////////////
163         // //////////// 1) ERROR TEXT AREA (with countdown value)
164         // //////////////////////////////////////////////////////////
165         JPanel jPanelText = new JPanel();
166         this.jtextArea = new JTextArea(this.uploadPolicy.getLocalizedString(
167                 "dialogUploadRetryText", this.countdownValue));
168         this.jtextArea.setEditable(false);
169         this.jtextArea.setMinimumSize(new Dimension(400, 100));
170         this.jtextArea.setBackground(jPanelText.getBackground());
171         jPanelText.add(this.jtextArea);
172         getContentPane().add(jPanelText, BorderLayout.CENTER);
173 
174         // //////////////////////////////////////////////////////////
175         // //////////// 2) BUTTONS
176         // //////////////////////////////////////////////////////////
177         // Creation of the yes button
178         this.buttonYes = new JButton(this.uploadPolicy
179                 .getLocalizedString("buttonYes"));
180         this.buttonYes.setMinimumSize(new Dimension(80, 30));
181         this.buttonYes.setMaximumSize(new Dimension(100, 100));
182         this.buttonYes.addActionListener(this);
183         // Creation of the nobutton
184         this.buttonNo = new JButton(this.uploadPolicy
185                 .getLocalizedString("buttonNo"));
186         this.buttonNo.setMinimumSize(new Dimension(80, 30));
187         this.buttonNo.setMaximumSize(new Dimension(100, 100));
188         this.buttonNo.addActionListener(this);
189         // Creation of the nobutton
190         this.buttonDetails = new JButton(this.uploadPolicy
191                 .getLocalizedString("buttonDetails"));
192         this.buttonDetails.setMinimumSize(new Dimension(80, 30));
193         this.buttonDetails.setMaximumSize(new Dimension(100, 100));
194         this.buttonDetails.addActionListener(this);
195 
196         JPanel jPanelButton = new JPanel();
197         jPanelButton
198                 .setLayout(new BoxLayout(jPanelButton, BoxLayout.LINE_AXIS));
199         jPanelButton.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
200         jPanelButton.add(Box.createHorizontalGlue());
201         jPanelButton.add(this.buttonYes);
202         jPanelButton.add(Box.createRigidArea(new Dimension(10, 0)));
203         jPanelButton.add(this.buttonNo);
204         jPanelButton.add(Box.createRigidArea(new Dimension(10, 0)));
205         jPanelButton.add(this.buttonDetails);
206 
207         // //////////////////////////////////////////////////////////
208         // //////////// 3) DETAIL TEXT AREA
209         // //////////////////////////////////////////////////////////
210         JPanel jPanelDetail = new JPanel();
211         this.detailTestArea = new JTextArea(this.juploadException.getMessage());
212         this.detailTestArea.setEditable(false);
213         this.detailTestArea.setMinimumSize(new Dimension(400, 500));
214         this.detailTestArea.setBackground(jPanelDetail.getBackground());
215         jPanelDetail.add(this.detailTestArea);
216         getContentPane().add(jPanelDetail, BorderLayout.CENTER);
217 
218         // //////////////////////////////////////////////////////////
219         // //////////// 4) Agregation in the root pane
220         // //////////////////////////////////////////////////////////
221         JPanel mainPanel = new JPanel();
222         mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.PAGE_AXIS));
223         mainPanel.add(this.jtextArea);
224         mainPanel.add(jPanelButton);
225         mainPanel.add(jPanelDetail);
226 
227         getContentPane().add(mainPanel);
228         getRootPane().setDefaultButton(this.buttonYes);
229 
230         // Let's put all this together.
231         pack();
232 
233         // Details are hidden, at the beginning
234         this.detailTestArea.setVisible(false);
235     }
236 
237     /**
238      * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
239      */
240     public void actionPerformed(ActionEvent event) {
241         if (event.getSource() == this.countdownTimer) {
242             // One timer event every second.
243             this.countdownValue -= 1;
244             if (this.countdownValue <= 0) {
245                 disposeDialog(true);
246             } else {
247                 this.jtextArea.setText(this.uploadPolicy.getLocalizedString(
248                         "dialogUploadRetryText", this.countdownValue));
249             }
250         } else if (event.getActionCommand() == this.buttonDetails
251                 .getActionCommand()) {
252             this.uploadPolicy
253                     .displayDebug(
254                             "[DialogUploadRetry] User choose to display or hide details",
255                             10);
256             this.detailTestArea.setVisible(!this.detailTestArea.isVisible());
257             // Resizing of the components
258             if (this.detailTestArea.isVisible()) {
259                 this.detailTestArea.setMinimumSize(new Dimension(400, 500));
260                 this.detailTestArea.setMaximumSize(new Dimension(400, 500));
261             } else {
262                 this.detailTestArea.setMinimumSize(new Dimension(0, 0));
263                 this.detailTestArea.setMaximumSize(new Dimension(0, 0));
264             }
265         } else if (event.getActionCommand() == this.buttonNo.getActionCommand()) {
266             this.uploadPolicy.displayDebug(
267                     "[DialogUploadRetry] User choose buttonNo", 10);
268             disposeDialog(false);
269         } else if (event.getActionCommand() == this.buttonYes
270                 .getActionCommand()) {
271             this.uploadPolicy.displayDebug(
272                     "[DialogUploadRetry] User choose buttonYes", 10);
273             disposeDialog(true);
274         }
275     }
276 
277     /**
278      * Actually closes the dialog box, and set the retryValidated status
279      * 
280      * @param retryValidated
281      */
282     private void disposeDialog(boolean retryValidated) {
283         this.retryValidated = retryValidated;
284         this.countdownTimer.stop();
285         this.dispose();
286     }
287 
288     /** {@inheritDoc} */
289     public void componentHidden(ComponentEvent arg0) {
290         // No action
291     }
292 
293     /** {@inheritDoc} */
294     public void componentMoved(ComponentEvent arg0) {
295         // No action
296     }
297 
298     /** {@inheritDoc} */
299     public void componentResized(ComponentEvent arg0) {
300         // No action
301     }
302 
303     /** {@inheritDoc} */
304     public void componentShown(ComponentEvent arg0) {
305         // We set the cursor back to normal
306         setCursor(new Cursor(Cursor.HAND_CURSOR));
307     }
308 }