6670a9317328c835143088d9d867d42f7dfe5efa
[debian/openrocket] / src / net / sf / openrocket / gui / dialogs / SwingWorkerDialog.java
1 package net.sf.openrocket.gui.dialogs;
2
3 import java.awt.Window;
4 import java.beans.PropertyChangeEvent;
5 import java.beans.PropertyChangeListener;
6
7 import javax.swing.JButton;
8 import javax.swing.JDialog;
9 import javax.swing.JLabel;
10 import javax.swing.JPanel;
11 import javax.swing.JProgressBar;
12 import javax.swing.SwingWorker;
13
14 import net.miginfocom.swing.MigLayout;
15 import net.sf.openrocket.util.Pair;
16
17
18 /**
19  * A modal dialog that runs specific SwingWorkers and waits until they complete.
20  * A message and progress bar is provided and a cancel button.  If the cancel button
21  * is pressed, the currently running worker is interrupted and the later workers are not
22  * executed.
23  * 
24  * @author Sampo Niskanen <sampo.niskanen@iki.fi>
25  */
26 public class SwingWorkerDialog extends JDialog implements PropertyChangeListener {
27
28         private final JLabel label;
29         private final JProgressBar progressBar;
30         
31         private int position;
32         private Pair<String, SwingWorker<?,?>>[] workers;
33         
34         private boolean cancelled = false;
35         
36         public SwingWorkerDialog(Window parent, String title) {
37                 super(parent, title, ModalityType.APPLICATION_MODAL);
38
39                 JPanel panel = new JPanel(new MigLayout("fill"));
40                 
41                 label = new JLabel("");
42                 panel.add(label, "wrap para");
43                 
44                 progressBar = new JProgressBar();
45                 panel.add(progressBar, "growx, wrap para");
46                 
47                 JButton cancel = new JButton("Cancel");
48                 // TODO: CRITICAL: Implement cancel
49                 panel.add(cancel, "right");
50                 
51                 this.add(panel);
52                 this.pack();
53                 this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
54         }
55
56         
57         /**
58          * Execute the provided workers one after another.  When this call returns
59          * the workers will all have completed.
60          *   
61          * @param workers       pairs of description texts and workers to run.
62          */
63         public void runWorkers(Pair<String, SwingWorker<?,?>> ... workers) {
64                 if (workers.length == 0) {
65                         throw new IllegalArgumentException("No workers provided.");
66                 }
67                 
68                 this.workers = workers;
69                 position = -1;
70                 
71                 for (int i=0; i < workers.length; i++) {
72                         workers[i].getV().addPropertyChangeListener(this);
73                 }
74                 
75                 nextWorker();
76                 this.setVisible(true);  // Waits until all have ended
77         }
78
79         
80         
81         /**
82          * Starts the execution of the next worker in the queue.  If the last worker
83          * has completed or the operation has been cancelled, closes the dialog.
84          */
85         private void nextWorker() {
86                 if ((position >= workers.length-1) || cancelled) {
87                         close();
88                         return;
89                 }
90                 
91                 position++;
92                 
93                 label.setText(workers[position].getU());
94                 workers[position].getV().execute();
95         }
96         
97         
98
99         @Override
100         public void propertyChange(PropertyChangeEvent evt) {
101                 if (workers[position].getV().getState() == SwingWorker.StateValue.DONE) {
102                         nextWorker();
103                 }
104                 
105                 int value = workers[position].getV().getProgress();
106                 value = (value + position*100 ) / workers.length;
107                 progressBar.setValue(value);
108         }
109         
110         
111         
112         private void close() {
113                 for (int i=0; i < workers.length; i++) {
114                         workers[i].getV().removePropertyChangeListener(this);
115                 }
116                 this.setVisible(false);
117         }
118 }