home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / VCAFE.3.0A / Main.bin / EventQueue.java < prev    next >
Text File  |  1999-01-11  |  9KB  |  305 lines

  1. /*
  2.  * @(#)EventQueue.java    1.23 98/12/10
  3.  *
  4.  * Copyright 1995-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  * 
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.awt;
  16.  
  17. import java.awt.event.FocusEvent;
  18. import java.awt.event.KeyEvent;
  19. import java.awt.event.MouseEvent;
  20. import java.awt.event.PaintEvent;
  21. import java.awt.event.WindowEvent;
  22. import java.util.EventListener;
  23.  
  24. import java.util.Vector;
  25.  
  26. /**
  27.  * EventQueue is a platform-independent class that queues events, both
  28.  * from the underlying peer classes and from trusted application classes.
  29.  * There is only one EventQueue for the system.
  30.  *
  31.  * @version 1.23 12/10/98
  32.  * @author Thomas Ball
  33.  */
  34. public class EventQueue {
  35.  
  36.     // From Thread.java
  37.     private static int threadInitNumber;
  38.  
  39.     // fix for 4187686 Several class objects are used for synchronization
  40.     private static Object classLock = new Object();
  41.  
  42.     private static int nextThreadNum() {
  43.     // fix for 4187686 Several class objects are used for synchronization
  44.     synchronized (classLock) {
  45.         return threadInitNumber++;
  46.     }
  47.     }
  48.  
  49.     private EventQueueItem queue;
  50.     /* The multiplexed EventQueueListener list. */
  51.     EventQueueListener eventQueueListener;
  52.  
  53.     public EventQueue() {
  54.         queue = null;
  55.         String name = "AWT-EventQueue-" + nextThreadNum();
  56.         new EventDispatchThread(name, this).start();
  57.     }
  58.  
  59.     /**
  60.      * Post a 1.1-style event to the EventQueue.
  61.      *
  62.      * @param theEvent an instance of java.awt.AWTEvent, or a
  63.      * subclass of it.
  64.      */
  65.     public synchronized void postEvent(AWTEvent theEvent) {
  66.         EventQueueItem eqi = new EventQueueItem(theEvent);
  67.     if (queue == null) {
  68.         queue = eqi;
  69.         notifyAll();
  70.     } else {
  71.         EventQueueItem q = queue;
  72.         for (;;) {
  73.         if (q.id == eqi.id) {
  74.             switch (q.id) {
  75.               case Event.MOUSE_MOVE:
  76.               case Event.MOUSE_DRAG:
  77.               // New-style event id's never collide with 
  78.               // old-style id's, so if the id's are equal, 
  79.               // we can safely cast the queued event to be 
  80.               // an old-style one.
  81.               MouseEvent e = (MouseEvent)q.event;
  82.               if (e.getSource() == ((MouseEvent)theEvent).getSource() &&
  83.                   e.getModifiers() == ((MouseEvent)theEvent).getModifiers()) {
  84.                   q.event = eqi.event;// just replace old event
  85.                   return;
  86.               }
  87.               break;
  88.  
  89.               case PaintEvent.PAINT:
  90.               case PaintEvent.UPDATE:
  91.               PaintEvent pe = (PaintEvent)q.event;
  92.               if (pe.getSource() == theEvent.getSource()) {
  93.                   Rectangle rect = pe.getUpdateRect();
  94.                   Rectangle newRect = 
  95.                   ((PaintEvent)theEvent).getUpdateRect();
  96.                   if (!rect.equals(newRect)) {
  97.                   pe.setUpdateRect(rect.union(newRect));
  98.                   }
  99.                   return;
  100.               }
  101.               break;
  102.  
  103.             }
  104.         }
  105.         if (q.next != null) {
  106.             q = q.next;
  107.         } else {
  108.             break;
  109.         }
  110.         }
  111.         q.next = eqi;
  112.     }
  113.     notifyEventQueueListeners(theEvent);
  114.     }
  115.  
  116.     /**
  117.      * Remove an event from the queue and return it.  This method will
  118.      * block until an event has been posted by another thread.
  119.      * @return the next AWTEvent
  120.      * @exception InterruptedException 
  121.      *            if another thread has interrupted this thread.
  122.      */
  123.     public synchronized AWTEvent getNextEvent() throws InterruptedException {
  124.         while (queue == null) {
  125.             wait();
  126.         }
  127.         EventQueueItem eqi = queue;
  128.         queue = queue.next;
  129.         return eqi.event;
  130.     }
  131.  
  132.     /**
  133.      * Return the first event without removing it.
  134.      * @return the first event, which is either an instance of java.awt.Event
  135.      * or java.awt.AWTEvent.
  136.      */
  137.     public synchronized AWTEvent peekEvent() {
  138.         return (queue != null) ? queue.event : null;
  139.     }
  140.  
  141.     /*
  142.      * Return the first event of the specified type, if any.
  143.      * @param id the id of the type of event desired.
  144.      * @return the first event of the requested type, 
  145.      * which is either an instance of java.awt.Event
  146.      * or java.awt.AWTEvent.
  147.      */
  148.     public synchronized AWTEvent peekEvent(int id) {
  149.         EventQueueItem q = queue;
  150.         for (; q != null; q = q.next) {
  151.             if (q.id == id) {
  152.                 return q.event;
  153.             }
  154.         }
  155.         return null;
  156.     }
  157.  
  158.     /* comment out until 1.2...
  159.     /**
  160.      * Dispatch an event to its source.
  161.      *
  162.      * @param theEvent an instance of java.awt.AWTEvent, or a
  163.      * subclass of it.
  164.      *
  165.      *    protected void dispatchEvent(AWTEvent event) {
  166.      *        Object src = event.getSource();
  167.      *        if (src instanceof Component) {
  168.      *            ((Component)src).dispatchEvent(event);
  169.      *        } else if (src instanceof MenuComponent) {
  170.      *            ((MenuComponent)src).dispatchEvent(event);
  171.      *        }
  172.      *    }
  173.      */
  174.  
  175.     /*
  176.      * (Copied from new public 1.2 API)
  177.      * Adds listener to event queue
  178.      */
  179.     synchronized void addEventQueueListener(EventQueueListener l) {
  180.         eventQueueListener = EventQueueMulticaster.add(eventQueueListener, l);
  181.     }
  182.  
  183.     /*
  184.      * (Copied from new public 1.2 API)
  185.      * Removes listener from event queue
  186.      */
  187.     synchronized void removeEventQueueListener(EventQueueListener l) {
  188.         eventQueueListener = EventQueueMulticaster.remove(eventQueueListener, l);
  189.     }
  190.  
  191.  
  192.     /*
  193.      * Change the target of any pending KeyEvents because of a focus change.
  194.      */
  195.     synchronized void changeKeyEventFocus(Object newSource) {
  196.         EventQueueItem q = queue;
  197.         for (; q != null; q = q.next) {
  198.             if (q.event instanceof KeyEvent) {
  199.                 q.event.setSource(newSource);
  200.             }
  201.         }
  202.     }
  203.  
  204.     /*
  205.      * Remove any pending events for the specified source object.
  206.      * This method is normally called by the source's removeNotify method.
  207.      */
  208.     synchronized void removeSourceEvents(Object source) {
  209.         EventQueueItem entry = queue;
  210.         EventQueueItem prev = null;
  211.         while (entry != null) {
  212.             if (entry.event.getSource().equals(source)) {
  213.                 if (prev == null) {
  214.                     queue = entry.next;
  215.                 } else {
  216.                     prev.next = entry.next;
  217.                 }
  218.             }
  219.             prev = entry;
  220.             entry = entry.next;
  221.         }
  222.     }
  223.  
  224.     /*
  225.      * Remove any pending events of the given class and id
  226.      */
  227.     synchronized void removeEvents(Class evClass, int id) {
  228.         EventQueueItem entry = queue;
  229.         EventQueueItem prev = null;
  230.         while (entry != null) {
  231.             if (evClass.isInstance(entry.event) && entry.event.getID() == id) {
  232.                 if (prev == null) {
  233.                     queue = entry.next;
  234.                 } else {
  235.                     prev.next = entry.next;
  236.                 }
  237.             }
  238.             prev = entry;
  239.             entry = entry.next;
  240.         }
  241.     }
  242.  
  243.     static private class EventQueueMulticaster extends AWTEventMulticaster
  244.         implements EventQueueListener {
  245.         // Implementation cloned from AWTEventMulticaster.
  246.  
  247.         EventQueueMulticaster(EventListener a, EventListener b) {
  248.             super(a, b);
  249.         }
  250.  
  251.         static EventQueueListener add(EventQueueListener a,
  252.                                       EventQueueListener b) {
  253.               if (a == null)  return b;
  254.               if (b == null)  return a;
  255.               return new EventQueueMulticaster(a, b);
  256.         }
  257.  
  258.         static EventQueueListener remove(EventQueueListener l,
  259.                                          EventQueueListener oldl) {
  260.             return (EventQueueListener) removeInternal(l, oldl);
  261.         }
  262.         
  263.       // #4179773: must overload remove(EventListener) to call our add()
  264.       // instead of the static addInternal() so we allocate an
  265.       // EventQueueMulticaster instead of an AWTEventMulticaster.
  266.       // Note: this method is called by AWTEventMulticaster.removeInternal(),
  267.       // so its method signature must match AWTEventMulticaster.remove().
  268.         protected EventListener remove(EventListener oldl) {
  269.             if (oldl == a)  return b;
  270.             if (oldl == b)  return a;
  271.             EventQueueListener a2 = (EventQueueListener)removeInternal(a, oldl);
  272.             EventQueueListener b2 = (EventQueueListener)removeInternal(b, oldl);
  273.             if (a2 == a && b2 == b) {
  274.                 return this;    // it's not here
  275.             }
  276.             return add(a2, b2);
  277.         }
  278.  
  279.       public void eventPosted(AWTEvent e) {
  280.             ((EventQueueListener)a).eventPosted(e);
  281.             ((EventQueueListener)b).eventPosted(e);
  282.         }
  283.     }
  284.  
  285.     /*
  286.      * Based on new protected 1.2 API
  287.      */
  288.     private void notifyEventQueueListeners(AWTEvent theEvent) {
  289.         if (eventQueueListener != null) {
  290.             eventQueueListener.eventPosted(theEvent);
  291.         }
  292.     }
  293. }
  294.  
  295. class EventQueueItem {
  296.     AWTEvent event;
  297.     int      id;
  298.     EventQueueItem next;
  299.  
  300.     EventQueueItem(AWTEvent evt) {
  301.         event = evt;
  302.         id = evt.getID();
  303.     }
  304. }
  305.