001: /*
002: * The contents of this file are subject to the Mozilla Public License
003: * Version 1.1 (the "License"); you may not use this file except in
004: * compliance with the License. You may obtain a copy of the License at
005: * http://www.mozilla.org/MPL/
006: *
007: * Software distributed under the License is distributed on an "AS IS"
008: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
009: * License for the specific language governing rights and limitations
010: * under the License.
011: *
012: * The Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
013: *
014: * The Initial Developer of the Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
015: * Portions created by Mark A. Kobold are Copyright (C) 2000-2007. All Rights Reserved.
016: *
017: * Contributor(s):
018: * Mark A. Kobold [mkobold <at> isqlviewer <dot> com].
019: *
020: * If you didn't download this code from the following link, you should check
021: * if you aren't using an obsolete version: http://www.isqlviewer.com
022: */
023: package org.isqlviewer.event;
024:
025: import java.awt.event.ActionEvent;
026: import java.awt.event.ActionListener;
027: import java.awt.event.ComponentEvent;
028: import java.awt.event.ComponentListener;
029: import java.lang.reflect.InvocationTargetException;
030: import java.lang.reflect.Method;
031: import java.util.Enumeration;
032: import java.util.EventListener;
033: import java.util.EventObject;
034: import java.util.Vector;
035:
036: import javax.swing.event.ChangeEvent;
037: import javax.swing.event.ChangeListener;
038: import javax.swing.event.EventListenerList;
039:
040: /**
041: * TODO Add EventDispatcher Overview JavaDoc.
042: * <p>
043: *
044: * @author Mark A. Kobold <mkobold at isqlviewer dot com>
045: * @version 1.0
046: */
047: public final class EventDispatcher implements EventProxyDelegate {
048:
049: private Vector<EventQueueEntry> eventQueue = new Vector<EventQueueEntry>();
050: private Object queueLatch = new Object();
051: private EventListenerList eventDelegates = new EventListenerList();
052: private EventLoop eventLoop = new EventLoop();
053: private Thread eventThread = null;
054:
055: public EventDispatcher() {
056:
057: eventThread = new Thread(eventLoop, "event-queue");
058: eventThread.setDaemon(true);
059: eventThread.setPriority(Thread.NORM_PRIORITY);
060: eventThread.start();
061: }
062:
063: public synchronized void halt() {
064:
065: if (eventThread != null) {
066: eventThread.interrupt();
067: }
068:
069: synchronized (queueLatch) {
070: queueLatch.notifyAll();
071: }
072: }
073:
074: public void addProgressListener(ProgressListener eventListener) {
075:
076: eventDelegates.add(ProgressListener.class, eventListener);
077: }
078:
079: public void removeProgressListener(ProgressListener eventListener) {
080:
081: eventDelegates.remove(ProgressListener.class, eventListener);
082: }
083:
084: public void addDatabaseListener(DatabaseListener eventListener) {
085:
086: eventDelegates.add(DatabaseListener.class, eventListener);
087: }
088:
089: public void removeDatabaseListener(DatabaseListener eventListener) {
090:
091: eventDelegates.remove(DatabaseListener.class, eventListener);
092: }
093:
094: public void addChangeListener(ChangeListener eventListener) {
095:
096: eventDelegates.add(ChangeListener.class, eventListener);
097: }
098:
099: public void removeChangeListener(ChangeListener eventListener) {
100:
101: eventDelegates.remove(ChangeListener.class, eventListener);
102: }
103:
104: public void addComponentListener(ComponentListener eventListener) {
105:
106: eventDelegates.add(ComponentListener.class, eventListener);
107: }
108:
109: public void removeComponentListener(ComponentListener eventListener) {
110:
111: eventDelegates.remove(ComponentListener.class, eventListener);
112: }
113:
114: public void addActionListener(ActionListener eventListener) {
115:
116: eventDelegates.add(ActionListener.class, eventListener);
117: }
118:
119: public void removeActionListener(ActionListener eventListener) {
120:
121: eventDelegates.remove(ActionListener.class, eventListener);
122: }
123:
124: public void stateChanged(ChangeEvent event) {
125:
126: enqueueEvent(ChangeListener.class, ChangeEvent.class, event,
127: "stateChanged");
128: }
129:
130: public void actionPerformed(ActionEvent event) {
131:
132: enqueueEvent(ActionListener.class, ActionEvent.class, event,
133: "actionPerformed");
134: }
135:
136: public void componentHidden(ComponentEvent event) {
137:
138: enqueueEvent(ComponentListener.class, ComponentEvent.class,
139: event, "componentHidden");
140: }
141:
142: public void componentMoved(ComponentEvent event) {
143:
144: enqueueEvent(ComponentListener.class, ComponentEvent.class,
145: event, "componentMoved");
146: }
147:
148: public void componentResized(ComponentEvent event) {
149:
150: enqueueEvent(ComponentListener.class, ComponentEvent.class,
151: event, "componentResized");
152: }
153:
154: public void componentShown(ComponentEvent event) {
155:
156: enqueueEvent(ComponentListener.class, ComponentEvent.class,
157: event, "componentShown");
158: }
159:
160: public void databaseStateChanged(DatabaseEvent event) {
161:
162: enqueueEvent(DatabaseListener.class, DatabaseEvent.class,
163: event, "databaseStateChanged");
164: }
165:
166: public void progressUpdated(ProgressEvent event) {
167:
168: enqueueEvent(ProgressListener.class, ProgressEvent.class,
169: event, "progressUpdated");
170: }
171:
172: private synchronized void enqueueEvent(
173: Class<? extends EventListener> listener,
174: Class<? extends EventObject> event, Object argument,
175: String method) {
176:
177: EventQueueEntry eqe = new EventQueueEntry(listener, argument,
178: event, method);
179: eventQueue.add(eqe);
180: synchronized (queueLatch) {
181: queueLatch.notifyAll();
182: }
183: }
184:
185: private class EventLoop implements Runnable {
186:
187: public void run() {
188:
189: Thread process = Thread.currentThread();
190: main: while (!process.isInterrupted()) {
191: if (eventQueue.isEmpty()) {
192: synchronized (queueLatch) {
193: try {
194: queueLatch.wait();
195: } catch (InterruptedException error) {
196: break main;
197: }
198: }
199: }
200: Enumeration queueCursor = eventQueue.elements();
201: while (queueCursor.hasMoreElements()) {
202: EventQueueEntry event = eventQueue.remove(0);
203: if (event == null) {
204: continue;
205: }
206: EventListener[] delegates = eventDelegates
207: .getListeners(event.listenerType);
208: Object[] eventArguments = new Object[] { event.eventArgument };
209: for (int i = 0; i < delegates.length; i++) {
210: try {
211: Method eventMethod = event.getMethod();
212: eventMethod.invoke(delegates[i],
213: eventArguments);
214: } catch (InvocationTargetException ite) {
215:
216: } catch (Exception error) {
217: error.printStackTrace();
218: } catch (Error fatalError) {
219: break main;
220: }
221: }
222: }
223: }
224: }
225: }
226:
227: private static class EventQueueEntry {
228:
229: Class<? extends EventObject> eventArgumentType = null;
230: Class<? extends EventListener> listenerType = null;
231: Object eventArgument = null;
232: String eventMethod = null;
233:
234: EventQueueEntry(Class<? extends EventListener> listener,
235: Object argument, Class<? extends EventObject> type,
236: String method) {
237:
238: this .listenerType = listener;
239: this .eventArgument = argument;
240: this .eventArgumentType = type;
241: this .eventMethod = method;
242: }
243:
244: public Method getMethod() throws NoSuchMethodException {
245:
246: return listenerType.getMethod(eventMethod,
247: new Class[] { eventArgumentType });
248: }
249:
250: }
251:
252: }
|