1 package eu.simuline.util;
2
3 import javax.swing.SwingUtilities;
4
5 /* ********FROM SUN but FREE ************* */
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.
11 * For 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 {
20 private Object value; // see getValue(), setValue()
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 thr) {
30 thread = thr;
31 }
32 synchronized Thread get() {
33 return thread;
34 }
35 synchronized void clear() {
36 thread = null;
37 }
38 }
39
40 private final ThreadVar threadVar;
41
42 /**
43 * Get the value produced by the worker thread, or null if it
44 * hasn't been constructed yet.
45 */
46 protected final synchronized Object getValue() {
47 return this.value;
48 }
49
50 /**
51 * Set the value produced by worker thread.
52 */
53 private synchronized void setValue(Object obj) {
54 this.value = obj;
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 // is empty.
68 }
69
70 /**
71 * A new method that interrupts the worker thread. Call this method
72 * to force the worker to stop what it's doing.
73 */
74 public final void interrupt() {
75 Thread thr = threadVar.get();
76 if (thr != null) {
77 thr.interrupt();
78 }
79 threadVar.clear();
80 }
81
82 /**
83 * Return the value created by the <code>construct</code> method.
84 * Returns null if either the constructing thread or the current
85 * thread was interrupted before a value was produced.
86 *
87 * @return the value created by the <code>construct</code> method
88 */
89 public final Object get() {
90 while (true) {
91 Thread thr = threadVar.get();
92 if (thr == null) {
93 return getValue();
94 }
95 try {
96 thr.join();
97 } catch (InterruptedException e) {
98 Thread.currentThread().interrupt(); // propagate
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() {
112 finished();
113 }
114 };
115
116 Runnable doConstruct = new Runnable() {
117 public void run() {
118 try {
119 setValue(construct());
120 } finally {
121 threadVar.clear();
122 }
123
124 SwingUtilities.invokeLater(doFinished);
125 }
126 };
127
128 Thread thr = new Thread(doConstruct);
129 threadVar = new ThreadVar(thr);
130 }
131
132 /**
133 * Start the worker thread.
134 */
135 public final void start() {
136 Thread thr = threadVar.get();
137 if (thr != null) {
138 thr.start();
139 }
140 }
141 }