001: package org.openharmonise.swing;
002:
003: import javax.swing.SwingUtilities;
004:
005: /**
006: * This is the 3rd version of SwingWorker (also known as
007: * SwingWorker 3), an abstract class that you subclass to
008: * perform GUI-related work in a dedicated thread. For
009: * instructions on and examples of using this class, see:
010: *
011: * http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html
012: *
013: * Note that the API changed slightly in the 3rd version:
014: * You must now invoke start() on the SwingWorker after
015: * creating it.
016: */
017: public abstract class SwingWorker {
018: private Object value;
019:
020: /**
021: * Class to maintain reference to current worker thread
022: * under separate synchronization control.
023: */
024: private static class ThreadVar {
025: private Thread thread;
026:
027: ThreadVar(Thread t) {
028: thread = t;
029: }
030:
031: synchronized Thread get() {
032: return thread;
033: }
034:
035: synchronized void clear() {
036: thread = null;
037: }
038: }
039:
040: private ThreadVar threadVar;
041:
042: /**
043: * Get the value produced by the worker thread, or null if it
044: * hasn't been constructed yet.
045: */
046: protected synchronized Object getValue() {
047: return value;
048: }
049:
050: /**
051: * Set the value produced by worker thread
052: */
053: private synchronized void setValue(Object x) {
054: value = x;
055: }
056:
057: /**
058: * Compute the value to be returned by the <code>get</code> method.
059: */
060: public abstract Object construct();
061:
062: /**
063: * Called on the event dispatching thread (not on the worker thread)
064: * after the <code>construct</code> method has returned.
065: */
066: public void finished() {
067: }
068:
069: /**
070: * A new method that interrupts the worker thread. Call this method
071: * to force the worker to stop what it's doing.
072: */
073: public void interrupt() {
074: Thread t = threadVar.get();
075: if (t != null) {
076: t.interrupt();
077: }
078: threadVar.clear();
079: }
080:
081: /**
082: * Return the value created by the <code>construct</code> method.
083: * Returns null if either the constructing thread or the current
084: * thread was interrupted before a value was produced.
085: *
086: * @return the value created by the <code>construct</code> method
087: */
088: public Object get() {
089: while (true) {
090: Thread t = threadVar.get();
091: if (t == null) {
092: return getValue();
093: }
094: try {
095: t.join();
096: } catch (InterruptedException e) {
097: Thread.currentThread().interrupt(); // propagate
098: return null;
099: }
100: }
101: }
102:
103: /**
104: * Start a thread that will call the <code>construct</code> method
105: * and then exit.
106: */
107: public SwingWorker() {
108: final Runnable doFinished = new Runnable() {
109: public void run() {
110: finished();
111: }
112: };
113:
114: Runnable doConstruct = new Runnable() {
115: public void run() {
116: try {
117: setValue(construct());
118: } finally {
119: threadVar.clear();
120: }
121:
122: SwingUtilities.invokeLater(doFinished);
123: }
124: };
125:
126: Thread t = new Thread(doConstruct);
127: threadVar = new ThreadVar(t);
128: }
129:
130: /**
131: * Start the worker thread.
132: */
133: public void start() {
134: Thread t = threadVar.get();
135: if (t != null) {
136: t.start();
137: }
138: }
139: }
|