View Javadoc

1   /*
2    * Created on 4-Jun-2005
3    */
4   package ca.spaz.task;
5   
6   import java.awt.BorderLayout;
7   import java.awt.event.*;
8   import java.util.*;
9   
10  import javax.swing.*;
11  import javax.swing.Timer;
12  
13  /***
14   * A TaskBar is a Swing component that can safely run a Task in a background
15   * thread, display progress of the task, interact with the task control,
16   * and fire events to report task progress. 
17   * 
18   * @see Task
19   * @see TaskListener
20   * 
21   * @author Aaron Davidson
22   */
23  public class TaskBar extends JPanel {
24     
25     private Task curTask;
26     private JProgressBar progressBar;
27     private JButton abortBtn;
28     private Timer timer;
29     private boolean aborting;
30     private ArrayList listeners;
31     
32     public TaskBar() {      
33        setLayout(new BorderLayout(4,4));
34        add(getProgressBar(), BorderLayout.CENTER);
35        add(getAbortButton(), BorderLayout.EAST);
36     }
37       
38     private JProgressBar getProgressBar() {
39        if (progressBar == null) {
40           progressBar = new JProgressBar(JProgressBar.HORIZONTAL);         
41           progressBar.setValue(0);
42           progressBar.setMinimum(0);
43           progressBar.setMaximum(100);
44        }
45        return progressBar;
46     }
47     
48     public JButton getAbortButton() {
49        if (abortBtn == null) {
50           abortBtn = new JButton("Stop");
51           abortBtn.setEnabled(false);
52           abortBtn.addActionListener(new ActionListener() {
53              public void actionPerformed(ActionEvent e) {
54                 abortCurrentTask();
55              }
56           });
57        }
58        return abortBtn;
59     }
60     
61     public void abortCurrentTask() {
62        if (curTask != null) {
63           aborting = true;
64           curTask.abortTask();
65           progressBar.setString("Aborting...");                  
66        }
67     }    
68     private Timer getTimer() {
69        if (timer == null) {
70           timer = new Timer(50, new ActionListener() {
71              public void actionPerformed(ActionEvent e) {
72                 updateProgressBar();
73              }
74           });
75           timer.setCoalesce(true);
76           timer.setRepeats(true);
77        }
78        return timer;
79     }
80     
81     /***
82      * Start the given task. 
83      * 
84      * @param t a Task to execute
85      */
86     public void executeTask(Task t) {
87        abortCurrentTask();
88        this.curTask = t;
89        fireTaskStarted();
90        getProgressBar().setValue(0);
91        getProgressBar().setStringPainted(true);
92        getAbortButton().setVisible(curTask.canAbortTask());
93        getAbortButton().setEnabled(curTask.canAbortTask());
94        Thread taskThread = new Thread(new Runnable() {
95           public void run() {
96              aborting = false;
97              if (curTask != null) {
98                 curTask.run();
99              }
100             SwingUtilities.invokeLater(new Runnable() {
101                public void run() {
102                   getTimer().stop();
103                   getProgressBar().setStringPainted(false);
104                   if (aborting) {
105                      fireTaskAborted();
106                   } else {
107                      fireTaskFinished();
108                   }
109                   // Ensure that the progress bar gets set to the right value.
110                   if (getProgressBar().getValue() != 100) {
111                      getProgressBar().setValue(0);
112                   }
113                   getAbortButton().setEnabled(false);
114                   curTask = null;
115                   getProgressBar().setStringPainted(false);
116                }
117             });
118          }
119       }, "TaskBar");
120       taskThread.start();
121       getTimer().start();
122    }
123    
124    private void updateProgressBar() {
125       if (curTask != null && !aborting) {
126          getProgressBar().setValue(curTask.getTaskProgress());
127          getProgressBar().setString(curTask.getTaskDescription());
128       }
129    }
130 
131    /***
132     * Adds a task listener to this object to receive events on
133     * a task's progress.
134     * 
135     * @param tl a task listener 
136     */
137    public synchronized void addTaskListener(TaskListener tl) {
138       if (null == listeners) {
139          listeners = new ArrayList();
140       }
141       listeners.add(tl);
142    }
143 
144    /***
145     * Remove a task listener from the TaskBar
146     * 
147     * @param tl a task listener 
148     */
149    public synchronized void removeTaskListener(TaskListener tl) {
150       if (listeners != null) {
151          listeners.remove(tl);
152       }
153    }
154    
155    private synchronized void fireTaskStarted() {
156       if (listeners != null) {
157         Iterator iterator = listeners.iterator();
158         while (iterator.hasNext()) {
159            TaskListener tl = (TaskListener)iterator.next();
160            tl.taskStarted(curTask);
161         }
162       }
163    }
164 
165    private synchronized void fireTaskAborted() {
166       if (listeners != null) {
167         Iterator iterator = listeners.iterator();
168         while (iterator.hasNext()) {
169            TaskListener tl = (TaskListener)iterator.next();
170            tl.taskAborted(curTask);
171         }
172       }
173    }
174 
175    private synchronized void fireTaskFinished() {
176       // Ensure that the progress bar gets set to the right value.
177       if (getProgressBar().getValue() != 100) {
178          getProgressBar().setValue(100);
179       }
180       if (listeners != null) {
181         Iterator iterator = listeners.iterator();
182         while (iterator.hasNext()) {
183            TaskListener tl = (TaskListener)iterator.next();
184            tl.taskFinished(curTask);
185         }
186       }
187    }
188 
189 
190 }