001: package net.suberic.util.thread;
002:
003: import java.util.HashMap;
004: import javax.swing.Action;
005: import java.awt.event.*;
006: import java.util.Vector;
007:
008: /**
009: * This is a Thread which handles ActionEvents. Instead of having the
010: * Action handled by the main thread, it is put into a queue on
011: * this thread, which will then handle the Action.
012: */
013: public class ActionThread extends Thread {
014:
015: // indicates high priority
016: public static int PRIORITY_HIGH = 10;
017:
018: // indicates normal priority
019: public static int PRIORITY_NORMAL = 5;
020:
021: // indicates low priority
022: public static int PRIORITY_LOW = 0;
023:
024: boolean stopMe = false;
025:
026: Object runLock = new Object();
027:
028: String mCurrentActionName = "";
029:
030: /**
031: * Creates an ActionThread with the given threadName.
032: */
033: public ActionThread(String threadName) {
034: super (threadName);
035: setPriority(Thread.NORM_PRIORITY);
036: }
037:
038: /**
039: * Represents an action/event pair. This also stores the priority of
040: * the event.
041: */
042: public class ActionEventPair {
043: public Action action;
044: public ActionEvent event;
045: public int priority = PRIORITY_NORMAL;
046:
047: /**
048: * Creates an NORMAL priority ActionEventPair.
049: */
050: public ActionEventPair(Action newAction, ActionEvent newEvent) {
051: this (newAction, newEvent, PRIORITY_NORMAL);
052: }
053:
054: /**
055: * Creates an ActionEventPair with the given priority.
056: */
057: public ActionEventPair(Action newAction, ActionEvent newEvent,
058: int newPriority) {
059: action = newAction;
060: event = newEvent;
061: priority = newPriority;
062: }
063: }
064:
065: // the action queue.
066: private Vector actionQueue = new Vector();
067:
068: private boolean sleeping;
069:
070: public void run() {
071: while (!stopMe) {
072: sleeping = false;
073: ActionEventPair pair = popQueue();
074: while (pair != null) {
075: try {
076: synchronized (runLock) {
077: mCurrentActionName = (String) pair.action
078: .getValue(Action.SHORT_DESCRIPTION);
079: if (mCurrentActionName == null) {
080: mCurrentActionName = (String) pair.action
081: .getValue(Action.NAME);
082: if (mCurrentActionName == null) {
083: mCurrentActionName = "Unknown action";
084: }
085: }
086: pair.action.actionPerformed(pair.event);
087: }
088: } catch (Throwable e) {
089: e.printStackTrace();
090: } finally {
091: mCurrentActionName = "";
092: }
093: pair = popQueue();
094: }
095: try {
096: sleeping = true;
097: while (true)
098: Thread.sleep(100000000);
099: } catch (InterruptedException ie) {
100: sleeping = false;
101: }
102: }
103: }
104:
105: /**
106: * This returns the top item in the action queue, if one is available.
107: * If not, the method returns null.
108: */
109: public synchronized ActionEventPair popQueue() {
110: if (actionQueue.size() > 0) {
111: return (ActionEventPair) actionQueue.remove(0);
112: } else {
113: return null;
114: }
115: }
116:
117: /**
118: * This adds an item to the queue. It also starts up the Thread if it's
119: * not already running.
120: */
121: public synchronized void addToQueue(Action action, ActionEvent event) {
122: addToQueue(action, event, PRIORITY_NORMAL);
123: }
124:
125: /**
126: * This adds an item to the queue. It also starts up the Thread if it's
127: * not already running.
128: */
129: public synchronized void addToQueue(Action action,
130: ActionEvent event, int priority) {
131: if (!stopMe) {
132: // see where this should go.
133: int index = 0;
134: boolean found = false;
135: while (!found && index < actionQueue.size()) {
136: ActionEventPair current = (ActionEventPair) actionQueue
137: .elementAt(index);
138: if (current.priority < priority)
139: found = true;
140: else
141: index++;
142: }
143: actionQueue.add(index, new ActionEventPair(action, event,
144: priority));
145: if (sleeping)
146: this .interrupt();
147: }
148: }
149:
150: /**
151: * Stops the ActionThread.
152: */
153: public void setStop(boolean newValue) {
154: stopMe = newValue;
155: this .interrupt();
156: }
157:
158: /**
159: * Returns whether or not this thread has been stopped.
160: */
161: public boolean getStopped() {
162: return stopMe;
163: }
164:
165: /**
166: * Returns the run lock for this thread.
167: */
168: public Object getRunLock() {
169: return runLock;
170: }
171:
172: /**
173: * Returns the queue size for this thread.
174: */
175: public int getQueueSize() {
176: return actionQueue.size();
177: }
178:
179: /**
180: * Returns a copy of the current action queue.
181: */
182: public java.util.List getQueue() {
183: return new Vector(actionQueue);
184: }
185:
186: /**
187: * Returns the name of the current action.
188: */
189: public String getCurrentActionName() {
190: return mCurrentActionName;
191: }
192:
193: /**
194: * Sets the name of the current action.
195: */
196: public void setCurrentActionName(String pCurrentActionName) {
197: mCurrentActionName = pCurrentActionName;
198: }
199: }
|