1 package nl.tudelft.simulation.language.swing;
2
3 import javax.swing.SwingUtilities;
4
5 /***
6 * This is the 3rd version of SwingWorker (also known as SwingWorker 3), an
7 * abstract class that you subclass to perform GUI-related work in a dedicated
8 * thread. For instructions on and examples of using this class, see:
9 *
10 * http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html
11 *
12 * Note that the API changed slightly in the 3rd version: You must now invoke
13 * start() on the SwingWorker after creating it.
14 */
15 public abstract class SwingWorker
16 {
17 /*** the value of the worker */
18 private Object value;
19
20 /*** the thread to use. */
21 protected ThreadVar threadVar;
22
23 /***
24 * @return Get the value produced by the worker thread, or null if it hasn't
25 * been constructed yet.
26 */
27 protected synchronized Object getValue()
28 {
29 return this.value;
30 }
31
32 /***
33 * Set the value produced by worker thread
34 *
35 * @param x the value
36 */
37 protected synchronized void setValue(final Object x)
38 {
39 this.value = x;
40 }
41
42 /***
43 * @return Compute the value to be returned by the <code>get</code>
44 * method.
45 */
46 public abstract Object construct();
47
48 /***
49 * Called on the event dispatching thread (not on the worker thread) after
50 * the <code>construct</code> method has returned.
51 */
52 public void finished()
53 {
54
55 }
56
57 /***
58 * A new method that interrupts the worker thread. Call this method to force
59 * the worker to stop what it's doing.
60 */
61 public void interrupt()
62 {
63 Thread t = this.threadVar.get();
64 if (t != null)
65 {
66 t.interrupt();
67 }
68 this.threadVar.clear();
69 }
70
71 /***
72 * Return the value created by the <code>construct</code> method. Returns
73 * null if either the constructing thread or the current thread was
74 * interrupted before a value was produced.
75 *
76 * @return the value created by the <code>construct</code> method
77 */
78 public Object get()
79 {
80 while (true)
81 {
82 Thread t = this.threadVar.get();
83 if (t == null)
84 {
85 return getValue();
86 }
87 try
88 {
89 t.join();
90 } catch (InterruptedException e)
91 {
92 Thread.currentThread().interrupt();
93 return null;
94 }
95 }
96 }
97
98
99 /***
100 * Start a thread that will call the <code>construct</code> method and
101 * then exit.
102 */
103 public SwingWorker()
104 {
105 final Runnable doFinished = new Runnable()
106 {
107 public void run()
108 {
109 finished();
110 }
111 };
112
113 Runnable doConstruct = new Runnable()
114 {
115 public void run()
116 {
117 try
118 {
119 SwingWorker.this.setValue(construct());
120 } finally
121 {
122 SwingWorker.this.threadVar.clear();
123 }
124
125 SwingUtilities.invokeLater(doFinished);
126 }
127 };
128
129 Thread t = new Thread(doConstruct);
130 this.threadVar = new ThreadVar(t);
131 }
132
133 /***
134 * Start the worker thread.
135 */
136 public void start()
137 {
138 Thread t = this.threadVar.get();
139 if (t != null)
140 {
141 t.start();
142 }
143 }
144
145 /***
146 * Class to maintain reference to current worker thread under separate
147 * synchronization control.
148 */
149 private static class ThreadVar
150 {
151 /*** the thread to use */
152 private Thread thread;
153
154 /***
155 * constructs a new ThreadVar
156 *
157 * @param t the thread
158 */
159 ThreadVar(final Thread t)
160 {
161 this.thread = t;
162 }
163
164 /***
165 * returns the thread
166 *
167 * @return Thread the thread
168 */
169 synchronized Thread get()
170 {
171 return this.thread;
172 }
173
174 /***
175 * clears the thread
176 */
177 synchronized void clear()
178 {
179 this.thread = null;
180 }
181 }
182 }