Package com.bbn.openmap

Source Code of com.bbn.openmap.MouseDelegator

// **********************************************************************
//
// <copyright>
//
//  BBN Technologies
//  10 Moulton Street
//  Cambridge, MA 02138
//  (617) 873-8000
//
//  Copyright (C) BBNT Solutions LLC. All rights reserved.
//
// </copyright>
// **********************************************************************
//
// $Source: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/MouseDelegator.java,v $
// $RCSfile: MouseDelegator.java,v $
// $Revision: 1.3.2.4 $
// $Date: 2005/12/16 13:56:28 $
// $Author: dietrick $
//
// **********************************************************************

package com.bbn.openmap;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
import java.beans.beancontext.BeanContext;
import java.beans.beancontext.BeanContextChild;
import java.beans.beancontext.BeanContextChildSupport;
import java.beans.beancontext.BeanContextMembershipEvent;
import java.beans.beancontext.BeanContextMembershipListener;
import java.util.Iterator;
import java.util.Vector;

import com.bbn.openmap.event.MapMouseListener;
import com.bbn.openmap.event.MapMouseMode;
import com.bbn.openmap.event.NavMouseMode;
import com.bbn.openmap.event.NullMouseMode;
import com.bbn.openmap.event.ProjectionListener;
import com.bbn.openmap.event.SelectMouseMode;
import com.bbn.openmap.util.Debug;

/**
* The MouseDelegator manages the MapMouseModes that handle
* MouseEvents on the map. There should only be one MouseDelegator
* within a MapHandler.
*
* @see com.bbn.openmap.event.MapMouseMode
* @see com.bbn.openmap.event.AbstractMouseMode
* @see com.bbn.openmap.event.NavMouseMode
* @see com.bbn.openmap.event.SelectMouseMode
*/
public class MouseDelegator implements PropertyChangeListener,
        java.io.Serializable, BeanContextChild, BeanContextMembershipListener,
        SoloMapComponent {

    public final static transient String ActiveModeProperty = "NewActiveMouseMode";
    public final static transient String MouseModesProperty = "NewListOfMouseModes";

    /**
     * The active MapMouseMode.
     */
    protected transient MapMouseMode activeMouseMode = null;

    /**
     * The registered MapMouseModes.
     */
    protected transient Vector mouseModes = new Vector(0);

    /**
     * The MapBean.
     */
    protected transient MapBean map;

    /**
     * Need to keep a safe copy of the current layers that are part of
     * the MapBean in case a MouseMode gets added before the MapBean
     * is set in the MouseDelegator. Without this, you can get into a
     * situation where new MapMouseModes don't know about layers until
     * the MouseDelegator receives a property change event from the
     * MapBean.
     */
    protected Layer[] currentLayers = null;

    /**
     * PropertyChangeSupport for handling listeners.
     */
    protected PropertyChangeSupport pcSupport = new PropertyChangeSupport(this);

    /**
     * BeanContextChildSupport object provides helper functions for
     * BeanContextChild interface.
     */
    protected BeanContextChildSupport beanContextChildSupport = new BeanContextChildSupport(this);

    /**
     * Construct a MouseDelegator with an associated MapBean.
     *
     * @param map MapBean
     */
    public MouseDelegator(MapBean map) {
        setMap(map);
    }

    /**
     * Construct a MouseDelegator without an associated MapBean. You
     * will need to set the MapBean via <code>setMap()</code>.
     *
     * @see #setMap
     */
    public MouseDelegator() {
        this(null);
    }

    /**
     * Set the associated MapBean.
     *
     * @param mapbean MapBean
     */
    public void setMap(MapBean mapbean) {
        if (map != null) {
            map.removePropertyChangeListener(this);
            setInactive(activeMouseMode);
        }

        map = mapbean;
        if (map != null) {
            map.addPropertyChangeListener(this);
            setActive(activeMouseMode);
        }
    }

    /**
     * Get the associated MapBean.
     *
     * @return MapBean
     */
    public MapBean getMap() {
        return map;
    }

    //----------------------------------------------------------------------
    //
    // Mouse Event handling support
    //
    //----------------------------------------------------------------------

    /**
     * Returns the ID string for the active Mouse Mode.
     *
     * @return String ID of the active mouse mode.
     */
    public String getActiveMouseModeID() {
        if (activeMouseMode != null)
            return activeMouseMode.getID();
        else
            return null;
    }

    /**
     * Sets the mouse mode to the mode with the same ID string. If
     * none of the MouseEventDelagates have a matching ID string, the
     * mode is not changed. <br>
     * The map mouse cursor is set to the recommended cursor retrieved
     * from the active mouseMode.
     *
     * @param MouseModeID the string ID of the mode to set active.
     */
    public void setActiveMouseModeWithID(String MouseModeID) {
        if (MouseModeID == null) {
            Debug.error("MouseDelegator:setActiveMouseModeWithID() - null value");
            return;
        }

        MapMouseMode oldActive = activeMouseMode;
        setInactive(activeMouseMode);

        for (int i = 0; i < mouseModes.size(); i++) {
            MapMouseMode med = (MapMouseMode) mouseModes.elementAt(i);
            if (MouseModeID.equals(med.getID())) {
                setActive(med);
                if (Debug.debugging("mousemode")) {
                    Debug.output("MouseDelegator.setActiveMouseModeWithID() setting new mode to mode "
                            + i + " " + med.getID());
                }
                break;
            }
        }

        firePropertyChange(ActiveModeProperty, oldActive, activeMouseMode);
    }

    /**
     * Returns the mouse mode delegate that is active at the moment.
     *
     * @return MapMouseMode the active mouse mode
     */
    public MapMouseMode getActiveMouseMode() {
        return activeMouseMode;
    }

    /**
     * Sets the active mouse mode. If the MapMouseMode is not a member
     * of the current mouse modes, it is added to the list. <br>
     * The map mouse cursor is set to the recommended cursor retrieved
     * from the active mouseMode.
     *
     * @param aMed a MapMouseMode to make active.
     */
    public void setActiveMouseMode(MapMouseMode aMed) {
        if (aMed == null) {
            Debug.error("MouseDelegator:setActiveMouseMode() - null value");
            return;
        }
        MapMouseMode oldActive = activeMouseMode;
        boolean isAlreadyAMode = false;

        for (int i = 0; i < mouseModes.size(); i++) {
            MapMouseMode med = (MapMouseMode) mouseModes.elementAt(i);
            // Need to go through the modes, turn off the other active
            // mode, and turn on this one.
            if (aMed.getID().equals(med.getID())) {
                isAlreadyAMode = true;
            }
        }

        if (!isAlreadyAMode) {
            addMouseMode(aMed);
        }

        setActive(aMed);

        firePropertyChange(ActiveModeProperty, oldActive, activeMouseMode);
    }

    /**
     * Returns an array of MapMouseModes that are available to the
     * MapBean.
     *
     * @return an array of MapMouseModes.
     */
    public MapMouseMode[] getMouseModes() {
        int nMouseModes = mouseModes.size();
        if (nMouseModes == 0)
            return (new MapMouseMode[0]);
        MapMouseMode[] result = new MapMouseMode[nMouseModes];
        for (int i = 0; i < nMouseModes; i++) {
            result[i] = (MapMouseMode) mouseModes.elementAt(i);
        }
        return result;
    }

    /**
     * Used to set the mouseModes available to the MapBean. The
     * Delegator drops all references to any mouseModes it knew about
     * previously. It also sets the index of the array to be the
     * active mouse mode. <br>
     * The map mouse cursor is set to the recommended cursor retrieved
     * from the active mouseMode.
     *
     * @param meds an array of MapMouseModes
     * @param activeIndex which mouse mode to make active
     */
    public void setMouseModes(MapMouseMode[] meds, int activeIndex) {
        mouseModes.removeAllElements();
        MapMouseMode oldActive = activeMouseMode;
        for (int i = 0; i < meds.length; i++) {
            mouseModes.addElement(meds[i]);

            if (i == activeIndex) { // activate the right mode
                setActive(meds[i]);
            }
        }

        firePropertyChange(MouseModesProperty, null, mouseModes);
        firePropertyChange(ActiveModeProperty, oldActive, activeMouseMode);
    }

    /**
     * Used to set the mouseModes available to the MapBean. The
     * MapBean drops all references to any mouseModes it knew about
     * previously. The meds[0] mode is made active, by default.
     *
     * @param meds an array of MapMouseModes
     */
    public void setMouseModes(MapMouseMode[] meds) {
        setMouseModes(meds, 0);
    }

    /**
     * Adds a MapMouseMode to the MouseMode list. Does not make it the
     * active mode.
     *
     * @param med the MouseEvent Delegate to add.
     */
    public void addMouseMode(MapMouseMode med) {

        if (med != null) {
            mouseModes.addElement(med);
            //  All of the MouseModes will think they are active, but
            //  the Delegator will only pass events to the one it
            //  thinks is...
            if (mouseModes.size() == 1) {
                setActive(med);
            }

            if (currentLayers != null) {
                setupMouseModeWithLayers(med, currentLayers);
            }

            firePropertyChange(MouseModesProperty, null, mouseModes);
        }
    }

    /**
     * Removes a particular MapMouseMode from the MouseMode list.
     *
     * @param med the MapMouseMode that should be removed.
     */
    public void removeMouseMode(MapMouseMode med) {
        boolean needToAdjustActiveMode = false;
        if (med.equals(activeMouseMode)) {
            needToAdjustActiveMode = true;
            setInactive(med);
        }

        for (int i = 0; i < mouseModes.size(); i++) {
            if (med.equals(mouseModes.elementAt(i))) {
                med.removeAllMapMouseListeners();
                mouseModes.removeElementAt(i);
            }
            // Set the first mode to the active one, if deleting the
            // active one.
            else if (needToAdjustActiveMode) {
                setActive(med);
                needToAdjustActiveMode = false;
            }
        }

        firePropertyChange(MouseModesProperty, null, mouseModes);
    }

    /**
     * Removes a particular MapMouseMode from the MouseMode list, with
     * the ID given.
     *
     * @param id the ID of the MapMouseMode that should be removed
     */
    public void removeMouseMode(String id) {
        for (int i = 0; i < mouseModes.size(); i++) {
            MapMouseMode med = (MapMouseMode) mouseModes.elementAt(i);
            if (id.equals(med.getID())) {
                removeMouseMode(med);
                break;
            }
        }
    }

    /**
     * Sets the three default OpenMap mouse modes. These modes are:
     * NavMouseMode (Map Navigation), the SelectMouseMode (MouseEvents
     * go to Layers), and NullMouseMode (MouseEvents are ignored).
     */
    public void setDefaultMouseModes() {
        MapMouseMode[] modes = new MapMouseMode[3];
        modes[0] = new NavMouseMode(true);
        modes[1] = new SelectMouseMode(true);
        modes[2] = new NullMouseMode();

        setMouseModes(modes);
    }

    /**
     * PropertyChangeListenter Interface method.
     *
     * @param evt PropertyChangeEvent
     */
    public void propertyChange(PropertyChangeEvent evt) {
        String property = evt.getPropertyName();
        if (property == MapBean.LayersProperty) {
            // make a safe copy of the layers that are part of the
            // MapBean
            Layer[] layers = (Layer[]) evt.getNewValue();
            currentLayers = new Layer[layers.length];
            System.arraycopy(layers, 0, currentLayers, 0, layers.length);

            setupMouseModesWithLayers(currentLayers);
        }
    }

    /**
     * Does the work putting the layers given on each mouse mode's
     * list of layers to notify if it becomes active.
     */
    public void setupMouseModesWithLayers(Layer[] layers) {
        for (int j = 0; j < mouseModes.size(); j++) {
            // Clear out the old listeners first
            MapMouseMode mmm = (MapMouseMode) mouseModes.elementAt(j);
            setupMouseModeWithLayers(mmm, layers);
        }
    }

    /**
     * Gives a MapMouseMode access to a Layer[], and it will find the
     * layers that want to listen to it and will forward events to
     * them if it is added to the MapBean as a MouseListener or a
     * MouseMotionListener.
     *
     * @param mmm MapMouseMode
     * @param layers Layer[]
     */
    public void setupMouseModeWithLayers(MapMouseMode mmm, Layer[] layers) {
        mmm.removeAllMapMouseListeners();
        for (int i = 0; i < layers.length; i++) {
            // Add the listeners from each layer to the mouse mode.
            MapMouseListener tempmml = null;

            if (layers[i] != null) {
                tempmml = layers[i].getMapMouseListener();
            }

            if (tempmml == null) {
                continue;
            }
            String[] services = tempmml.getMouseModeServiceList();
            if (services != null) {
                for (int k = 0; k < services.length; k++) {
                    if (mmm.getID().equals(services[k])) {
                        mmm.addMapMouseListener(tempmml);
                        if (Debug.debugging("mousemode")) {
                            Debug.output("MouseDelegator.setupMouseModeWithLayers():"
                                    + " layer = "
                                    + layers[i].getName()
                                    + " service = " + mmm.getID());
                        }
                        break;
                    }
                }
            }
        }
    }

    /**
     * Set the active MapMouseMode. This sets the MapMouseMode of the
     * associated MapBean.
     *
     * @param mm MapMouseMode
     */
    public void setActive(MapMouseMode mm) {
        if (activeMouseMode != null) {
            setInactive(activeMouseMode);
        }

        activeMouseMode = mm;

        if (map != null && activeMouseMode != null) {
            if (Debug.debugging("mousemode")) {
                Debug.output("MouseDelegator.setActive(): " + mm.getID());
            }
            map.addMouseListener(mm);
            map.addMouseMotionListener(mm);
            map.addMouseWheelListener(mm);
            map.addPaintListener(mm);
            map.setCursor(activeMouseMode.getModeCursor());
            if (mm instanceof ProjectionListener) {
                map.addProjectionListener((ProjectionListener) mm);
            }
            activeMouseMode.setActive(true);
        }
    }

    /**
     * Deactivate the MapMouseMode.
     *
     * @param mm MapMouseMode.
     */
    public void setInactive(MapMouseMode mm) {
        if (map != null) {
            map.removeMouseListener(mm);
            map.removeMouseMotionListener(mm);
            map.removeMouseWheelListener(mm);
            map.removePaintListener(mm);
            // should set map's cursor to some default value??
            if (mm instanceof ProjectionListener) {
                map.removeProjectionListener((ProjectionListener) mm);
            }
        }
        if (activeMouseMode == mm) {
            activeMouseMode = null;
        }
        if (mm != null) {
            mm.setActive(false);
        }
    }

    /**
     * Eventually gets called when the MouseDelegator is added to the
     * BeanContext, and when other objects are added to the
     * BeanContext anytime after that. The MouseDelegator looks for a
     * MapBean to manage MouseEvents for, and MouseModes to use to
     * manage those events. If a MapBean is added to the BeanContext
     * while another already is in use, the second MapBean will take
     * the place of the first.
     *
     * @param it iterator to use to go through the new objects in the
     *        BeanContext.
     */
    public void findAndInit(Iterator it) {
        while (it.hasNext()) {
            findAndInit(it.next());
        }
    }

    /**
     * Called when an object should be evaluated by the MouseDelegator
     * to see if it is needed.
     */
    public void findAndInit(Object someObj) {
        if (someObj instanceof MapBean) {
            Debug.message("mousedelegator", "MouseDelegator found a map.");
            setMap((MapBean) someObj);
        }
        if (someObj instanceof MapMouseMode) {
            Debug.message("mousedelegator",
                    "MouseDelegator found a MapMouseMode.");
            addMouseMode((MapMouseMode) someObj);
        }
    }

    /**
     * BeanContextMembershipListener method. Called when new objects
     * are added to the parent BeanContext.
     *
     * @param bcme event that contains an iterator that can be used to
     *        go through the new objects.
     */
    public void childrenAdded(BeanContextMembershipEvent bcme) {
        findAndInit(bcme.iterator());
    }

    /**
     * BeanContextMembershipListener method. Called when objects have
     * been removed from the parent BeanContext. The MouseDelegator
     * looks for the MapBean it is managing MouseEvents for, and any
     * MouseModes that may be removed.
     *
     * @param bcme event that contains an iterator that can be used to
     *        go through the removed objects.
     */
    public void childrenRemoved(BeanContextMembershipEvent bcme) {
        Iterator it = bcme.iterator();
        while (it.hasNext()) {
            findAndUndo(it.next());
        }
    }

    /**
     * Called by childrenRemoved.
     */
    public void findAndUndo(Object someObj) {
        if (someObj instanceof MapBean) {
            if (getMap() == (MapBean) someObj) {
                Debug.message("mousedelegator",
                        "MouseDelegator: removing the map.");
                setMap(null);
            }
        }
        if (someObj instanceof MapMouseMode) {
            Debug.message("mousedelegator",
                    "MouseDelegator: removing a MapMouseMode.");
            removeMouseMode((MapMouseMode) someObj);
        }
    }

    /** Method for BeanContextChild interface. */
    public BeanContext getBeanContext() {
        return beanContextChildSupport.getBeanContext();
    }

    /** Method for BeanContextChild interface. */
    public void setBeanContext(BeanContext in_bc) throws PropertyVetoException {
        if (in_bc != null) {
            in_bc.addBeanContextMembershipListener(this);
            beanContextChildSupport.setBeanContext(in_bc);
            findAndInit(in_bc.iterator());
        }
    }

    /** Method for BeanContextChild interface. */
    public void addPropertyChangeListener(String propertyName,
                                          PropertyChangeListener in_pcl) {
        pcSupport.addPropertyChangeListener(propertyName, in_pcl);
    }

    /** Method for BeanContextChild interface. */
    public void removePropertyChangeListener(String propertyName,
                                             PropertyChangeListener in_pcl) {
        pcSupport.removePropertyChangeListener(propertyName, in_pcl);
    }

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        // This function is why we don't use the
        // BeanContextChildSupport PropertyChangeSupport object.
        pcSupport.addPropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(PropertyChangeListener listener) {
        // This function is why we don't use the
        // BeanContextChildSupport PropertyChangeSupport object.
        pcSupport.removePropertyChangeListener(listener);
    }

    public void firePropertyChange(String property, Object oldObj, Object newObj) {

        pcSupport.firePropertyChange(property, oldObj, newObj);
    }

    /** Method for BeanContextChild interface. */
    public void addVetoableChangeListener(String propertyName,
                                          VetoableChangeListener in_vcl) {
        beanContextChildSupport.addVetoableChangeListener(propertyName, in_vcl);
    }

    /** Method for BeanContextChild interface. */
    public void removeVetoableChangeListener(String propertyName,
                                             VetoableChangeListener in_vcl) {
        beanContextChildSupport.removeVetoableChangeListener(propertyName,
                in_vcl);
    }

    /**
     * Report a vetoable property update to any registered listeners.
     * If anyone vetos the change, then fire a new event reverting
     * everyone to the old value and then rethrow the
     * PropertyVetoException.
     * <P>
     *
     * No event is fired if old and new are equal and non-null.
     * <P>
     *
     * @param name The programmatic name of the property that is about
     *        to change
     *
     * @param oldValue The old value of the property
     * @param newValue - The new value of the property
     *
     * @throws PropertyVetoException if the recipient wishes the
     *         property change to be rolled back.
     */
    public void fireVetoableChange(String name, Object oldValue, Object newValue)
            throws PropertyVetoException {
        beanContextChildSupport.fireVetoableChange(name, oldValue, newValue);
    }

}
TOP

Related Classes of com.bbn.openmap.MouseDelegator

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.