Package DisplayProject.events

Source Code of DisplayProject.events.ClientEventManager$EventListener

/*
Copyright (c) 2003-2008 ITerative Consulting Pty Ltd. All Rights Reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted
provided that the following conditions are met:

o Redistributions of source code must retain the above copyright notice, this list of conditions and
the following disclaimer.
 
o Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the distribution.
   
o This jcTOOL Helper Class software, whether in binary or source form may not be used within,
or to derive, any other product without the specific prior written permission of the copyright holder

 
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


*/
package DisplayProject.events;

import java.awt.Component;
import java.awt.Container;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.WeakHashMap;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.MenuElement;
import javax.swing.SwingUtilities;

import org.apache.log4j.Logger;

import DisplayProject.DisplayEvent;
import DisplayProject.UIutils;
import DisplayProject.WindowSystem;
import DisplayProject.controls.OutlineField;
import DisplayProject.dnd.ForteTransferHandler;
import Framework.EventCompletionHandler;
import Framework.EventHandle;
import Framework.EventManager;
import Framework.EventRegistration;
import Framework.EventRegistrationCallback;
import Framework.ParameterHolder;

public class ClientEventManager{
    private static Logger _Log = Logger.getLogger(ClientEventManager.class);

    /**
     * Stores information about what event listener is required. Typically an event is mapped to
     * an event listener which determines the class
     * @author tfaulkes
     *
     */
    private static class EventListener {     
        private HashMap<Class<?>, Class<?>> registrations = new HashMap<Class<?>, Class<?>>();
        public EventListener() {};
        public EventListener(Class<?> pRootType, Class<?> pListener) {
            this();
            this.addListener(pRootType, pListener);
        }

        /**
         * Add the new mapping into the hash map, replacing the existing one if there is one.
         * @param pRootType the root class that defines where this event is posted
         * @param pListener the class that needs to handle the event.
         */
        public synchronized void addListener(Class<?> pRootType, Class<?> pListener) {
            registrations.put(pRootType, pListener);
        }

        public synchronized Class<?> getEventListenerClass(Class<?> pClass) {
            for (Class<?> aClass : registrations.keySet()) {
                if (aClass.isAssignableFrom(pClass)) {
                    return registrations.get(aClass);
                }
            }
            return null;
        }
    }

    /**
     * Intercept any events being processed by the event manager, so we can slip a
     * gui event processing in there at the appropriate time, transparently.
     * @author tfaulkes
     *
     */
    private static class CallBack implements EventCompletionHandler{
        public void processEventCompletion(EventHandle pEvent) {
            UIutils.processGUIActions();
        }
    }

    private static HashMap<String, EventListener> requiredListeners = new HashMap<String, EventListener>();

    /**
     * Many of the event listeners are static, that is to transform the java event into the forte
     * event requires no specific information from the registering object, nor what is being registered.
     * For these static events we store only a single instance which is always reused. This is mapped
     * keyed by Class type
     */
    private static HashMap<Class<?>, Object> staticListeners = new HashMap<Class<?>, Object>();

    static  {
        populateStaticListeners();
        populateListenerMap();
        EventManager.setEventCompletionCallBack(new CallBack());
    }

    /**
     * Static listeners are listeners that only a single instance is required in the jvm -- they do not
     * store state associated with particular controls, and hence can be re-used across controls. We
     * create a single instance of these controls here, and store them for later use.
     */
    protected static void populateStaticListeners() {
        // Populate the static listeners
        staticListeners.put(AfterValueChangeListener.class, new AfterValueChangeListener());
        staticListeners.put(AfterFieldScrolledListener.class, new AfterFieldScrolledListener()); // CraigM 29/01/2008.
        staticListeners.put(AfterResizeListener.class, new AfterResizeListener());         // TF:10/10/2009:DET 117
        staticListeners.put(ChildAfterValueChangeListener.class, new ChildAfterValueChangeListener());
        staticListeners.put(ChildClickListener.class, new ChildClickListener());
        staticListeners.put(ChildClickMiddleListener.class, new ChildClickMiddleListener());
        staticListeners.put(ChildClickOuterListener.class, new ChildClickOuterListener());
        staticListeners.put(ChildDoubleClickListener.class, new ChildDoubleClickListener());
        staticListeners.put(ChildDoubleClickMiddleListener.class, new ChildDoubleClickMiddleListener());
        staticListeners.put(ChildDoubleClickOuterListener.class, new ChildDoubleClickOuterListener());
        staticListeners.put(ChildMouseEnterListener.class, new ChildMouseEnterListener());
        staticListeners.put(ChildMouseLeaveListener.class, new ChildMouseLeaveListener());
        staticListeners.put(ClickListener.class, new ClickListener());
        staticListeners.put(ClickMiddleListener.class, new ClickMiddleListener());
        staticListeners.put(ClickOuterListener.class, new ClickOuterListener());
        staticListeners.put(ClipBoardChangedListener.class, new ClipBoardChangedListener());
        staticListeners.put(DoubleClickListener.class, new DoubleClickListener());
        staticListeners.put(DoubleClickMiddleListener.class, new DoubleClickMiddleListener());
        staticListeners.put(DoubleClickOuterListener.class, new DoubleClickOuterListener());
        staticListeners.put(ForteTransferHandler.class, new ForteTransferHandler());
        staticListeners.put(FocusListener.class, new FocusListener()); // CraigM 17/7/2007
        staticListeners.put(MouseEnterListener.class, new MouseEnterListener());
        staticListeners.put(MouseLeaveListener.class, new MouseLeaveListener());
        staticListeners.put(NodeChangedListener.class, new NodeChangedListener());
        staticListeners.put(PopupRequestListener.class, new PopupRequestListener());
        staticListeners.put(RequestSortListener.class, new RequestSortListener()); // CraigM:20/08/2008.
        staticListeners.put(ActivateListener.class, new ActivateListener());
        staticListeners.put(ChildActivateListener.class, new ChildActivateListener());
        staticListeners.put(TextMenuStatusChangedListener.class, new TextMenuStatusChangedListener());
    }

    /**
     * The listener map contains a list of all known display events. Each event is associated with an
     * event listener, which is consulted whenever an object registers for that event. The event listener
     * contains a mapping of components to the class used to map that event from Forte to Java
     *
     */
    protected static void populateListenerMap() {
        // Populate table that determines which listener to instantiate for which events.
        requiredListeners.put("AfterClipboardChange", new EventListener(WindowSystem.class, ClipBoardChangedListener.class));
        requiredListeners.put("AfterCurrentNodeChange", new EventListener(OutlineField.class, NodeChangedListener.class));
        requiredListeners.put("AfterFieldScrolled", new EventListener(JComponent.class, AfterFieldScrolledListener.class)); // CraigM 29/01/2008.
        requiredListeners.put("AfterResize", new EventListener(Component.class, AfterResizeListener.class)); // TF:10/10/2009:DET 117
        requiredListeners.put("AfterValueChange", new EventListener(JComponent.class, AfterValueChangeListener.class));
        requiredListeners.put("BeforeFocusLoss", new EventListener(JComponent.class, FocusListener.class)); // CraigM 17/07/2007
        requiredListeners.put("AfterFocusGain", new EventListener(JComponent.class, FocusListener.class)); // CraigM 06/11/2007
        requiredListeners.put("ChildAfterValueChange", new EventListener(JComponent.class, ChildAfterValueChangeListener.class));
        requiredListeners.put("ChildClick", new EventListener(JComponent.class, ChildClickListener.class));
        requiredListeners.put("ChildClickMiddle", new EventListener(JComponent.class, ChildClickMiddleListener.class));
        requiredListeners.put("ChildClickOuter", new EventListener(JComponent.class, ChildClickOuterListener.class));
        requiredListeners.put("ChildDoubleClick", new EventListener(JComponent.class, ChildDoubleClickListener.class));
        requiredListeners.put("ChildDoubleMiddleClick", new EventListener(JComponent.class, ChildDoubleClickMiddleListener.class));
        requiredListeners.put("ChildDoubleOuterClick", new EventListener(JComponent.class, ChildDoubleClickOuterListener.class));
        requiredListeners.put("ChildMouseEnter", new EventListener(JComponent.class, ChildMouseEnterListener.class));
        requiredListeners.put("ChildMouseLeave", new EventListener(JComponent.class, ChildMouseLeaveListener.class));
        requiredListeners.put("Click", new EventListener(JComponent.class, ClickListener.class));
        requiredListeners.put("ClickMiddle", new EventListener(JComponent.class, ClickMiddleListener.class));
        requiredListeners.put("ClickOuter", new EventListener(JComponent.class, ClickOuterListener.class));
        requiredListeners.put("DoubleClick", new EventListener(JComponent.class, DoubleClickListener.class));
        requiredListeners.put("DoubleClickMiddle", new EventListener(JComponent.class, DoubleClickMiddleListener.class));
        requiredListeners.put("DoubleClickOuter", new EventListener(JComponent.class, DoubleClickOuterListener.class));
        requiredListeners.put("MouseEnter", new EventListener(JComponent.class, MouseEnterListener.class));
        requiredListeners.put("MouseLeave", new EventListener(JComponent.class, MouseLeaveListener.class));
        requiredListeners.put("PopUpRequest", new EventListener(JFrame.class, PopupRequestListener.class));
        requiredListeners.put("RequestSort", new EventListener(JComponent.class, RequestSortListener.class)); // CraigM:20/08/2008.
        requiredListeners.put("ObjectDrop", new EventListener(JComponent.class, ForteTransferHandler.class));
        requiredListeners.put("FileDrop", new EventListener(JComponent.class, ForteTransferHandler.class));    // 11/07/2008 JNL
        requiredListeners.put("Traverse", new EventListener(Container.class, TraverseListener.class));
//        requiredListeners.put("Activate", new EventListener(JMenuItem.class, ActivateListener.class));
//        requiredListeners.put("Activate", new EventListener(MenuList.class, ActivateListener.class));
//        requiredListeners.put("Activate", new EventListener(JCheckBoxMenuItem.class, ActivateListener.class));
        requiredListeners.put("Activate", new EventListener(MenuElement.class, ActivateListener.class));
        // TF:18/11/07:We need to listen to 2 classes for ChildActivate events, so explicitly put them here...
        requiredListeners.put("ChildActivate", new EventListener(MenuElement.class, ChildActivateListener.class));
        requiredListeners.get("ChildActivate").addListener(JMenuBar.class, ChildActivateListener.class);
        requiredListeners.put("TextMenuStatusChange", new EventListener(WindowSystem.class, TextMenuStatusChangedListener.class));

    }

    /**
     * The knownWidgets map contains mapping of widget -> events registered against that widget, which is
     * again a map of event names (string) to ?. This stops us registering for events multiple times if
     * the event is used in multiple event loops for example.
     */
    private static Map<Object, Map<String, String>> knownWidgets = new WeakHashMap<Object, Map<String, String>>();

    private static synchronized void _register(Object pObject, String pEvent) {
        // ignore anything that's not a widget, or which we don't know about listeners for
        EventListener thisListener = (EventListener)requiredListeners.get(pEvent);
        if ((pObject instanceof JComponent || pObject instanceof JFrame) && thisListener != null) {
            Map<String, String> eventMap = knownWidgets.get(pObject);
            if (eventMap == null) {
                eventMap = new HashMap<String, String>();
                knownWidgets.put(pObject, eventMap);
            }
            if (!eventMap.containsKey(pEvent)) {
                try {
                    // We need to add the registration of this event
                    Class<?> registrationClass = thisListener.getEventListenerClass(pObject.getClass());
                    if (registrationClass != null) {
                        // See if it's a static registration
                        InstallableListener listener = (InstallableListener)staticListeners.get(registrationClass);
                        if (listener == null) {
                            // There's no static instance available, create a dynamic one.
                            listener = (InstallableListener)registrationClass.newInstance();
                        }
                        listener.install(pObject, pEvent);

                        // Notify that we've added the event
                        eventMap.put(pEvent, pEvent);
                    }
                }
                catch (IllegalAccessException e) {
                    _Log.error("Could not instaniate class", e);
                }
                catch (InstantiationException e) {
                    _Log.error("Could not instaniate class", e);
                }
            }
        }
    }

    // Prevent anyone creating an instance of this static class
    private ClientEventManager() {
    }

    public static EventRegistration register(Object pObject, String pEvent) {
        _register(pObject, pEvent);
        return EventManager.register(pObject, pEvent);
    }

    public static EventRegistration register(Object pObject, String pEvent, EventRegistrationCallback pCallback) {
        _register(pObject, pEvent);
        return EventManager.register(pObject, pEvent, pCallback);
    }

    public static void deregister(EventRegistration pRegistration) {
        EventManager.deregister(pRegistration);
    }

    public static ForteTransferHandler getObjectDropTransferHandler(){
        return (ForteTransferHandler)staticListeners.get(ForteTransferHandler.class);
    }

    /**
     * When a widget is re-parented, we may need to add it into the new parent's set
     * of events if the parent was listening for Child style events. We only do this
     * if everything is already set up, that is to say we're already listening on the
     * events.
     * @param pObject
     * @param pParent
     */
    public static void addChildForObject(JComponent pObject, Component pParent) {
        if (pParent != null && pObject != null) {
            // We don't care about de-registrations, we'll just post extra events for the moment
            while (pParent != null) {
                Map<String, String> eventMap = knownWidgets.get(pParent);
                if (eventMap != null) {
                    for (Iterator<String> it = eventMap.keySet().iterator(); it.hasNext();) {
                        String key = it.next();

                        // ignore anything that's not a widget, or which we don't know about listeners for
                        EventListener thisListener = (EventListener)requiredListeners.get(key);
                        if (thisListener != null) {
                            try {
                                // We need to add the registration of this event
                                Class<?> registrationClass = thisListener.getEventListenerClass(pObject.getClass());
                                if (registrationClass != null) {
                                    // See if it's a static registration
                                    InstallableListener listener = (InstallableListener)staticListeners.get(registrationClass);

                                    if (listener == null) {
                                        // There's no static instance available, create a dynamic one.
                                        listener = (InstallableListener)registrationClass.newInstance();
                                    }
                                    // Only install if it's an installable child listener
                                    if (listener instanceof ChildInstallableListener) {
                                        ChildInstallableListener childListener = (ChildInstallableListener)listener;
                                        childListener.installChildForParent(pObject, (Container)pParent, key);

                                        // Notify that we've added the event
                                        eventMap.put(key, key);
                                    }
                                }
                            }
                            catch (IllegalAccessException e) {
                                _Log.error("Could not instantiate class", e);
                            }
                            catch (InstantiationException e) {
                                _Log.error("Could not instantiate class", e);
                            }
                        }
                    }
                }
                pParent = pParent.getParent();
            }
        }
    }
    /**
     * Returns a reference to the text menu status change listener.
     */
    public static TextMenuStatusChangedListener getTextMenuStatusChangedListener(){
      return (TextMenuStatusChangedListener)staticListeners.get(TextMenuStatusChangedListener.class);
    }
   
    /**
     * Post an event to the event manager. If this event is being posted from the EDT, we lower the
     * priority of the event. This is necessary because Forte dropped the priority of EDT based events.
     * This means that if a thread that is responding to a GUI (EDT) event posts an event for which it
     * is subscribed, this new event will occur prior to other events generated in the event chain.
     * @param handle
     */
    public static void postEvent(EventHandle handle) {
      // TF:Also ensured that all events posted via this method (ie client events) have associated
      // with them a DisplayEvent parameter. This prevents runtime errors from people who use this.
      if (handle.getParameters() != null && handle.getParameter("eventInfo") == null) {
        handle.getParameters().put("eventInfo", new ParameterHolder(new DisplayEvent()));
      }
      if (SwingUtilities.isEventDispatchThread()) {
        handle.setPriority(EventHandle.PRIORITY_EDT);
      }
      EventManager.postEvent(handle);
    }
   
  @SuppressWarnings("unchecked")
  public static void postEvent(Object pObject, String pEvent, Hashtable pParameters) {
    ClientEventManager.postEvent(new EventHandle(pObject, pEvent, pParameters));
  }

  public static void postEvent(Object pObject, String pEvent) {
    ClientEventManager.postEvent(new EventHandle(pObject, pEvent));
  }
}
TOP

Related Classes of DisplayProject.events.ClientEventManager$EventListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.