1 package coras.client;
2
3 import java.util.Observable;
4
5 import javax.swing.SwingUtilities;
6
7 /***
8 * This is the 3rd version of SwingWorker (also known as
9 * SwingWorker 3), an abstract class that you subclass to
10 * perform GUI-related work in a dedicated thread. For
11 * instructions on using this class, see:
12 *
13 * http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html
14 *
15 * Note that the API changed slightly in the 3rd version:
16 * You must now invoke start() on the SwingWorker after
17 * creating it.
18 */
19 public abstract class SwingWorker extends Observable {
20 private Object value;
21 private Thread thread;
22
23 /***
24 * Class to maintain reference to current worker thread
25 * under separate synchronization control.
26 */
27 private static class ThreadVar {
28 private Thread thread;
29 ThreadVar(Thread t) { thread = t; }
30 synchronized Thread get() { return thread; }
31 synchronized void clear() { thread = null; }
32 }
33
34 private ThreadVar threadVar;
35 private int taskLength = 0;
36 private int progress = 0;
37 private String jobName = null;
38 private String currentTask = null;
39 private boolean finished = false;
40 private boolean interrupted = false;
41
42 /***
43 * Get the value produced by the worker thread, or null if it
44 * hasn't been constructed yet.
45 */
46 protected synchronized Object getValue() {
47 return value;
48 }
49
50 /***
51 * Set the value produced by worker thread
52 */
53 private synchronized void setValue(Object x) {
54 value = x;
55 }
56
57 /***
58 * Compute the value to be returned by the <code>get</code> method.
59 */
60 public abstract Object construct();
61
62 /***
63 * Called on the event dispatching thread (not on the worker thread)
64 * after the <code>construct</code> method has returned.
65 */
66 public void finished() {
67 }
68
69 /***
70 * A new method that interrupts the worker thread. Call this method
71 * to force the worker to stop what it's doing.
72 */
73 public void interrupt() {
74 Thread t = threadVar.get();
75 if (t != null) {
76 t.interrupt();
77 }
78 threadVar.clear();
79 }
80
81 /***
82 * Return the value created by the <code>construct</code> method.
83 * Returns null if either the constructing thread or the current
84 * thread was interrupted before a value was produced.
85 *
86 * @return the value created by the <code>construct</code> method
87 */
88 public Object get() {
89 while (true) {
90 Thread t = threadVar.get();
91 if (t == null) {
92 return getValue();
93 }
94 try {
95 t.join();
96 }
97 catch (InterruptedException e) {
98 Thread.currentThread().interrupt();
99 return null;
100 }
101 }
102 }
103
104
105 /***
106 * Start a thread that will call the <code>construct</code> method
107 * and then exit.
108 */
109 public SwingWorker() {
110 final Runnable doFinished = new Runnable() {
111 public void run() { finished(); }
112 };
113
114 Runnable doConstruct = new Runnable() {
115 public void run() {
116 try {
117 setValue(construct());
118 }
119 finally {
120 threadVar.clear();
121 }
122
123 SwingUtilities.invokeLater(doFinished);
124 }
125 };
126
127 Thread t = new Thread(doConstruct);
128 threadVar = new ThreadVar(t);
129 }
130
131 /***
132 * Start the worker thread.
133 */
134 public void start() {
135 Thread t = threadVar.get();
136 if (t != null) {
137 t.start();
138 }
139 }
140
141 public int getProgress() {
142 return progress;
143 }
144 public void setProgress(int progress) {
145 if (this.progress != progress) {
146 this.progress = progress;
147 setChanged();
148 notifyObservers();
149 }
150 }
151
152 public int getTaskLength() {
153 return taskLength;
154 }
155 public void setTaskLength(int taskLength) {
156 if (this.taskLength != taskLength) {
157 this.taskLength = taskLength;
158 setChanged();
159 notifyObservers();
160 }
161 }
162
163
164 /***
165 * @return Returns the jobName.
166 */
167 public String getJobName() {
168 return jobName;
169 }
170 /***
171 * @param jobName The jobName to set.
172 */
173 public void setJobName(String jobName) {
174 if (this.jobName != jobName
175 && !(jobName != null && jobName.equals(this.jobName))) {
176 this.jobName = jobName;
177 setChanged();
178 notifyObservers();
179 }
180 }
181 /***
182 * @return Returns the currentTask.
183 */
184 public String getCurrentTask() {
185 return currentTask;
186 }
187 /***
188 * @param currentTask The currentTask to set.
189 */
190 public void setCurrentTask(String currentTask) {
191 if (this.currentTask != currentTask
192 && !(currentTask != null && currentTask.equals(this.currentTask))) {
193 this.currentTask = currentTask;
194 setChanged();
195 notifyObservers();
196 }
197 }
198 /***
199 * @return Returns the finished.
200 */
201 public boolean isFinished() {
202 return finished;
203 }
204 /***
205 * @param finished The finished to set.
206 */
207 public void setFinished(boolean finished) {
208 if (this.finished != finished) {
209 this.finished = finished;
210 setChanged();
211 notifyObservers();
212 }
213 }
214 /***
215 * @return Returns the interrupted.
216 */
217 public boolean isInterrupted() {
218 return interrupted;
219 }
220 /***
221 * @param interrupted The interrupted to set.
222 */
223 public void setInterrupted(boolean interrupted) {
224 if (this.interrupted != interrupted) {
225 this.interrupted = interrupted;
226 setChanged();
227 notifyObservers();
228 }
229 }
230 }