EventDispatcher.java
上传用户:haobig99
上传日期:2022-06-15
资源大小:369k
文件大小:10k
源码类别:

J2ME

开发平台:

Java

  1. /*
  2.  * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
  3.  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4.  *
  5.  * This code is free software; you can redistribute it and/or modify it
  6.  * under the terms of the GNU General Public License version 2 only, as
  7.  * published by the Free Software Foundation.  Sun designates this
  8.  * particular file as subject to the "Classpath" exception as provided
  9.  * by Sun in the LICENSE file that accompanied this code.
  10.  *
  11.  * This code is distributed in the hope that it will be useful, but WITHOUT
  12.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13.  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14.  * version 2 for more details (a copy is included in the LICENSE file that
  15.  * accompanied this code).
  16.  *
  17.  * You should have received a copy of the GNU General Public License version
  18.  * 2 along with this work; if not, write to the Free Software Foundation,
  19.  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20.  *
  21.  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22.  * CA 95054 USA or visit www.sun.com if you need additional information or
  23.  * have any questions.
  24.  */
  25. package com.sun.lwuit.util;
  26. import com.sun.lwuit.*;
  27. import com.sun.lwuit.events.*;
  28. import com.sun.lwuit.plaf.Style;
  29. import java.util.Vector;
  30. /**
  31.  * Handles event dispatching while guaranteeing that all events would
  32.  * be fired properly on the EDT regardless of their source. This class handles listener
  33.  * registration/removal in a safe and uniform way. 
  34.  * 
  35.  * @author Shai Almog
  36.  */
  37. public class EventDispatcher {
  38.     private Vector listeners;
  39.     private Object[] pending;
  40.     private Object pendingEvent;
  41.     private final Runnable callback = new Runnable() {
  42.         /**
  43.          * Do not invoke this method it handles the dispatching internally and serves
  44.          * as an implementation detail
  45.          */
  46.         public final void run() {
  47.             if(!Display.getInstance().isEdt()) {
  48.                 throw new IllegalStateException("This method should not be invoked by external code!");
  49.             }
  50.             if(pending instanceof ActionListener[]) {
  51.                 fireActionSync((ActionListener[])pending, (ActionEvent)pendingEvent);
  52.                 return;
  53.             }
  54.             if(pending instanceof FocusListener[]) {
  55.                 fireFocusSync((FocusListener[])pending, (Component)pendingEvent);
  56.                 return;
  57.             }
  58.             if(pending instanceof DataChangedListener[]) {
  59.                 fireDataChangeSync((DataChangedListener[])pending, ((int[])pendingEvent)[0], ((int[])pendingEvent)[1]);
  60.                 return;
  61.             }
  62.             
  63.             if(pending instanceof SelectionListener[]) {
  64.                 fireSelectionSync((SelectionListener[])pending, ((int[])pendingEvent)[0], ((int[])pendingEvent)[1]);
  65.                 return;
  66.             }
  67.             if(pending instanceof StyleListener[]) {
  68.                 Object[] p = (Object[])pendingEvent;
  69.                 fireStyleChangeSync((StyleListener[])pending, (String)p[0], (Style)p[1]);
  70.                 return;
  71.             }
  72.         }
  73.     };
  74.     
  75.     /**
  76.      * Add a listener to the dispatcher that would receive the events when they occurs
  77.      * 
  78.      * @param listener a dispatcher listener to add
  79.      */
  80.     public synchronized void addListener(Object listener) {
  81.         if(listeners == null) {
  82.             listeners = new Vector();
  83.         }
  84.         listeners.addElement(listener);
  85.     }
  86.     
  87.     /**
  88.      * Returns the vector of the listeners
  89.      * 
  90.      * @return the vector of listeners attached to the event dispatcher
  91.      */
  92.     public Vector getListenerVector() {
  93.         return listeners;
  94.     }
  95.     /**
  96.      * Remove the listener from the dispatcher
  97.      *
  98.      * @param listener a dispatcher listener to remove
  99.      */
  100.     public synchronized void removeListener(Object listener) {
  101.         if(listeners != null) {
  102.             listeners.removeElement(listener);
  103.         }
  104.     }
  105.     /**
  106.      * Fires the event safely on the EDT without risk of concurrency errors
  107.      * 
  108.      * @param ev the ActionEvent to fire to the listeners
  109.      */
  110.     public void fireDataChangeEvent(int index, int type) {
  111.         if(listeners == null || listeners.size() == 0) {
  112.             return;
  113.         }
  114.         DataChangedListener[] array;
  115.         synchronized(this) {
  116.             array = new DataChangedListener[listeners.size()];
  117.             for(int iter = 0 ; iter < array.length ; iter++) {
  118.                 array[iter] = (DataChangedListener)listeners.elementAt(iter);
  119.             }
  120.         }
  121.         // if we already are on the EDT just fire the event
  122.         if(Display.getInstance().isEdt()) {
  123.             fireDataChangeSync(array, type, index);
  124.         } else {
  125.             pending = array;
  126.             pendingEvent = new int[] {type, index};
  127.             Display.getInstance().callSeriallyAndWait(callback);
  128.         }
  129.     }
  130.     
  131.     /**
  132.      * Fires the style change even to the listeners
  133.      *
  134.      * @param property the property name for the event
  135.      * @param source the style firing the event
  136.      */
  137.     public void fireStyleChangeEvent(String property, Style source) {
  138.         if(listeners == null || listeners.size() == 0) {
  139.             return;
  140.         }
  141.         StyleListener[] array;
  142.         synchronized(this) {
  143.             array = new StyleListener[listeners.size()];
  144.             for(int iter = 0 ; iter < array.length ; iter++) {
  145.                 array[iter] = (StyleListener)listeners.elementAt(iter);
  146.             }
  147.         }
  148.         // if we already are on the EDT just fire the event
  149.         if(Display.getInstance().isEdt()) {
  150.             fireStyleChangeSync(array, property, source);
  151.         } else {
  152.             pending = array;
  153.             pendingEvent = new Object[] {property, source};
  154.             Display.getInstance().callSerially(callback);
  155.         }
  156.     }
  157.     /**
  158.      * Synchronious internal call for common code
  159.      */
  160.     private void fireDataChangeSync(DataChangedListener[] array, int type, int index) {
  161.         for(int iter = 0 ; iter < array.length ; iter++) {
  162.             array[iter].dataChanged(type, index);
  163.         }
  164.     }
  165.     
  166.     /**
  167.      * Synchronious internal call for common code
  168.      */
  169.     private void fireStyleChangeSync(StyleListener[] array, String property, Style source) {
  170.         for(int iter = 0 ; iter < array.length ; iter++) {
  171.             array[iter].styleChanged(property, source);
  172.         }
  173.     }
  174.     /**
  175.      * Synchronious internal call for common code
  176.      */
  177.     private void fireSelectionSync(SelectionListener[] array, int oldSelection, int newSelection) {
  178.         for(int iter = 0 ; iter < array.length ; iter++) {
  179.             array[iter].selectionChanged(oldSelection, newSelection);
  180.         }
  181.     }
  182.     
  183.     /**
  184.      * Fires the event safely on the EDT without risk of concurrency errors
  185.      * 
  186.      * @param ev the ActionEvent to fire to the listeners
  187.      */
  188.     public void fireActionEvent(ActionEvent ev) {
  189.         if(listeners == null || listeners.size() == 0) {
  190.             return;
  191.         }
  192.         ActionListener[] array;
  193.         synchronized(this) {
  194.             array = new ActionListener[listeners.size()];
  195.             for(int iter = 0 ; iter < array.length ; iter++) {
  196.                 array[iter] = (ActionListener)listeners.elementAt(iter);
  197.             }
  198.         }
  199.         // if we already are on the EDT just fire the event
  200.         if(Display.getInstance().isEdt()) {
  201.             fireActionSync(array, ev);
  202.         } else {
  203.             pending = array;
  204.             pendingEvent = ev;
  205.             Display.getInstance().callSeriallyAndWait(callback);
  206.         }
  207.     }
  208.     /**
  209.      * Fires the event safely on the EDT without risk of concurrency errors
  210.      * 
  211.      * @param oldSelection old selection
  212.      * @param newSelection new selection
  213.      */
  214.     public void fireSelectionEvent(int oldSelection, int newSelection) {
  215.         if(listeners == null || listeners.size() == 0) {
  216.             return;
  217.         }
  218.         SelectionListener[] array;
  219.         synchronized(this) {
  220.             array = new SelectionListener[listeners.size()];
  221.             for(int iter = 0 ; iter < array.length ; iter++) {
  222.                 array[iter] = (SelectionListener)listeners.elementAt(iter);
  223.             }
  224.         }
  225.         // if we already are on the EDT just fire the event
  226.         if(Display.getInstance().isEdt()) {
  227.             fireSelectionSync(array, oldSelection, newSelection);
  228.         } else {
  229.             pending = array;
  230.             pendingEvent = new int[] {oldSelection, newSelection};
  231.             Display.getInstance().callSeriallyAndWait(callback);
  232.         }
  233.     }
  234.     
  235.     /**
  236.      * Synchronious internal call for common code
  237.      */
  238.     private void fireActionSync(ActionListener[] array, ActionEvent ev) {
  239.         for(int iter = 0 ; iter < array.length ; iter++) {
  240.             if(!ev.isConsumed()) {
  241.                 array[iter].actionPerformed(ev);
  242.             }
  243.         }
  244.     }
  245.     
  246.     /**
  247.      * Fires the event safely on the EDT without risk of concurrency errors
  248.      * 
  249.      * @param c the Component that gets the focus event
  250.      */
  251.     public void fireFocus(Component c) {
  252.         if(listeners == null || listeners.size() == 0) {
  253.             return;
  254.         }
  255.         FocusListener[] array;
  256.         synchronized(this) {
  257.             array = new FocusListener[listeners.size()];
  258.             for(int iter = 0 ; iter < array.length ; iter++) {
  259.                 array[iter] = (FocusListener)listeners.elementAt(iter);
  260.             }
  261.         }
  262.         // if we already are on the EDT just fire the event
  263.         if(Display.getInstance().isEdt()) {
  264.             fireFocusSync(array, c);
  265.         } else {
  266.             pending = array;
  267.             pendingEvent = c;
  268.             Display.getInstance().callSeriallyAndWait(callback);
  269.         }
  270.     }
  271.     
  272.     /**
  273.      * Synchronious internal call for common code
  274.      */
  275.     private void fireFocusSync(FocusListener[] array, Component c) {
  276.         if(c.hasFocus()) {
  277.             for(int iter = 0 ; iter < array.length ; iter++) {
  278.                 array[iter].focusGained(c);
  279.             }
  280.         } else {
  281.             for(int iter = 0 ; iter < array.length ; iter++) {
  282.                 array[iter].focusLost(c);
  283.             }
  284.         }
  285.     }
  286. }