Package com.bbn.openmap.gui

Source Code of com.bbn.openmap.gui.AbstractOpenMapMenu

// **********************************************************************
//
// <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/gui/AbstractOpenMapMenu.java,v $
// $RCSfile: AbstractOpenMapMenu.java,v $
// $Revision: 1.6.2.4 $
// $Date: 2006/02/13 17:02:03 $
// $Author: dietrick $
//
// **********************************************************************

package com.bbn.openmap.gui;

import java.awt.Component;
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.Hashtable;
import java.util.Iterator;
import java.util.Properties;
import java.util.Vector;

import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JSeparator;

import com.bbn.openmap.Environment;
import com.bbn.openmap.I18n;
import com.bbn.openmap.Layer;
import com.bbn.openmap.LightMapHandlerChild;
import com.bbn.openmap.MapHandler;
import com.bbn.openmap.PropertyConsumer;
import com.bbn.openmap.util.ComponentFactory;
import com.bbn.openmap.util.Debug;
import com.bbn.openmap.util.PropUtils;

/**
* Abstract Menu Object that takes care of common bean context-related
* functionality. Components on this Menu that implement the
* LightMapHandlerChild interface, that also are created via the
* constructor, or created when the properties are evaluated, will be
* given the MapHandler through the findAndInit(Object) method. These
* components will also receive findAndInit() and findAndUndo() calls
* when other components are added to the MapHandler (BeanContext).
* This makes the LightMapHandlerChild menu components invisible to
* MapHandler components, but able to connect to them.
* <P>
*
* If you have a component that needs to be added to the menu that
* should in the MapHandler, you should *NOT* make it a
* LightMapHandlerChild, but implement the same methods as the
* MapHandlerChild and add it to the MapHandler before adding it to
* this menu. If the component is a LightMapHandlerChild, added to
* this menu, and also added to the MapHandler, it will receive double
* membership notifications which may be confusing.
* <P>
*
* AbstractOpenMapMenus can be configure via properties. You can set,
* with 'menu' as a property prefix:
* <P>
*
* <pre>
*
*   # Title used in the Menu Bar.
*   menu.prettyName=Menu Title
*   # The letter to use as Mnemonic
*   menu.mnemonic=M
*   # A marker name list of items to use in the menu. 'sep' inserts a
*   # separator, property classname definition not needed.
*   menu.items=first second sep third
*   first.class=Classname of first menu item
*   # You can add properties for Menu Item, if it is a PropertyConsumer.
*   #first.property1=prop1
*   second.class=classname
*   third.class=classname
*  
*  
* </pre>
*
* If no properties are set, the name, mnemonic and any items added in
* the constructor will be in the menu. Any items in the properties
* will be added to items created and added in the constructor - this
* really applies to any subclasses to this class.
*/
abstract public class AbstractOpenMapMenu extends JMenu implements
        BeanContextChild, BeanContextMembershipListener, PropertyConsumer,
        MenuBarMenu, LightMapHandlerChild {

    /**
     * All AbstractOpenMapMenus have access to an I18n object, which
     * is provided by the Environment.
     */
    protected I18n i18n = Environment.getI18n();

    protected BeanContextChildSupport beanContextChildSupport = new BeanContextChildSupport(this);

    /**
     * Token uniquely identifying this component in the application
     * properties.
     */
    protected String propertyPrefix = null;
    /**
     * A hashtable to keep track of item prefixes and their
     * components, for restructuring properties later. Only created if
     * menu uses properties to create items.
     */
    protected Hashtable items = null;

    public final static String ItemsProperty = "items";
    public final static String SeparatorProperty = "sep";
    public final static String PrettyNameProperty = Layer.PrettyNameProperty;
    public final static String MnemonicProperty = "mnemonic";

    protected String itemsPropertyContents = null;
    protected Hashtable itemsProperties = null;

    public AbstractOpenMapMenu() {
        super();
    }

    public AbstractOpenMapMenu(String title) {
        super(title);
    }

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

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

        // let MenuItems find it if they want to look for
        // it there, or if they want to add themselves. Not sure what
        // the ConcurrentModificationException ramifications will be,
        // though.
        findAndInit((Object) in_bc);
        findAndInit(in_bc.iterator());
    }

    /** Method for BeanContextMembership interface. */
    public void childrenAdded(BeanContextMembershipEvent bcme) {
        findAndInit(bcme.iterator());
    }

    /** Method for BeanContextMembership interface. */
    public void childrenRemoved(BeanContextMembershipEvent bcme) {
        findAndUndo(bcme.iterator());
    }

    /**
     * Subclasses should no longer implement this method. Use the
     * findAndUndo(Object) instead, so subclasses and superclasses can
     * be given the opportunity to use the object, too.
     */
    public void findAndUndo(Iterator it) {
        while (it.hasNext()) {
            findAndUndo(it.next());
        }
    }

    /**
     * Method called when an object is removed from the MapHandler.
     * Called to let menu objects disconnect from it.
     */
    public void findAndUndo(Object someObj) {
        Component menuItems[] = getMenuComponents();

        for (int i = 0; i < menuItems.length; i++) {
            Component item = menuItems[i];
            if (item instanceof LightMapHandlerChild) {
                ((LightMapHandlerChild) item).findAndUndo(someObj);
            }
        }
    }

    /**
     * Subclasses should no longer implement this method. Use the
     * findAndInit(Object) instead, so subclasses and superclasses can
     * be given the opportunity to use the object, too.
     */
    public void findAndInit(Iterator it) {
        while (it.hasNext()) {
            findAndInit(it.next());
        }
    }

    /**
     * Method called when an object is added from the MapHandler.
     * Called to let menu objects connect to it.
     */
    public void findAndInit(Object someObj) {
        Component menuItems[] = getMenuComponents();

        for (int i = 0; i < menuItems.length; i++) {
            Component item = menuItems[i];
            if (item instanceof LightMapHandlerChild) {
                ((LightMapHandlerChild) item).findAndInit(someObj);
            }
        }
    }

    /** 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);
    }

    /**
     * Return the MapHandler, if it's been set. May be null if the
     * Menu hasn't been added to the MapHandler.
     */
    public MapHandler getMapHandler() {
        return (MapHandler) beanContextChildSupport.getBeanContext();
    }

    /**
     * Sets the properties for the OMComponent.
     *
     * @param props the <code>Properties</code> object.
     */
    public void setProperties(java.util.Properties props) {
        setProperties(getPropertyPrefix(), props);
    }

    /**
     * Sets the properties for the OMComponent.
     *
     * @param prefix the token to prefix the property names
     * @param props the <code>Properties</code> object
     */
    public void setProperties(String prefix, java.util.Properties props) {
        setPropertyPrefix(prefix);

        String realPrefix = PropUtils.getScopedPropertyPrefix(prefix);

        String prettyName = props.getProperty(realPrefix + PrettyNameProperty);
        if (prettyName != null) {
            setText(prettyName);
        }

        String mnemonicString = props.getProperty(realPrefix + MnemonicProperty);
        if (mnemonicString != null) {
            setMnemonic((int) mnemonicString.charAt(0));
        }

        itemsPropertyContents = props.getProperty(realPrefix + ItemsProperty);
        Vector menuItems = PropUtils.parseSpacedMarkers(itemsPropertyContents);

        if (!menuItems.isEmpty()) {

            int nMenuItems = menuItems.size();

            if (Debug.debugging("menu")) {
                Debug.output("Menu " + getText() + " created with "
                        + nMenuItems + " item" + (nMenuItems == 1 ? "" : "s")
                        + " in properties");
            }

            for (int i = 0; i < nMenuItems; i++) {
                String itemPrefix = (String) menuItems.elementAt(i);
                if (itemPrefix.equals(SeparatorProperty)) {
                    add(new JSeparator());
                    continue;
                }

                String classProperty = itemPrefix + ".class";
                String className = props.getProperty(classProperty);
                if (className == null) {
                    Debug.error("Menu " + getText()
                            + ".setProperties(): Failed to locate property \""
                            + classProperty + "\"\n  Skipping menu item \""
                            + itemPrefix + "\"");
                    continue;
                }

                if (itemsProperties == null) {
                    itemsProperties = new Properties();
                }

                itemsProperties.put(classProperty, className);

                Object obj = ComponentFactory.create(className,
                        itemPrefix,
                        props);
                if (obj instanceof Component) {
                    add((Component) obj);
                } else if (obj instanceof JMenuItem) {
                    add((JMenuItem) obj);
                }
            }
        } else {
            if (Debug.debugging("menu")) {
                Debug.output("Menu " + getText()
                        + " created without items in properties");
            }
        }

    }

    /**
     * PropertyConsumer method, to fill in a Properties object,
     * reflecting the current values of the OMComponent. If the
     * component has a propertyPrefix set, the property keys should
     * have that prefix plus a separating '.' prepended to each
     * propery key it uses for configuration.
     *
     * @param props a Properties object to load the PropertyConsumer
     *        properties into. If props equals null, then a new
     *        Properties object should be created.
     * @return Properties object containing PropertyConsumer property
     *         values. If getList was not null, this should equal
     *         getList. Otherwise, it should be the Properties object
     *         created by the PropertyConsumer.
     */
    public Properties getProperties(Properties props) {
        if (props == null) {
            props = new Properties();
        }

        String prefix = PropUtils.getScopedPropertyPrefix(propertyPrefix);

        props.put(prefix + PrettyNameProperty, getText());
        props.put(prefix + MnemonicProperty, "" + ((char) getMnemonic()));

        if (itemsPropertyContents != null) {
            props.put(prefix + ItemsProperty, itemsPropertyContents);
        }

        if (itemsProperties != null) {
            props.putAll(itemsProperties);
        }

        return props;
    }

    /**
     * Method to fill in a Properties object with values reflecting
     * the properties able to be set on this PropertyConsumer. The key
     * for each property should be the raw property name (without a
     * prefix) with a value that is a String that describes what the
     * property key represents, along with any other information about
     * the property that would be helpful (range, default value,
     * etc.). For Layer, this method should at least return the
     * 'prettyName' property.
     *
     * @param list a Properties object to load the PropertyConsumer
     *        properties into. If getList equals null, then a new
     *        Properties object should be created.
     * @return Properties object containing PropertyConsumer property
     *         values. If getList was not null, this should equal
     *         getList. Otherwise, it should be the Properties object
     *         created by the PropertyConsumer.
     */
    public Properties getPropertyInfo(Properties list) {
        if (list == null) {
            list = new Properties();
        }
        return list;
    }

    /**
     * Set the property key prefix that should be used by the
     * PropertyConsumer. The prefix, along with a '.', should be
     * prepended to the property keys known by the PropertyConsumer.
     *
     * @param prefix the prefix String.
     */
    public void setPropertyPrefix(String prefix) {
        propertyPrefix = prefix;
    }

    /**
     * Get the property key prefix that is being used to prepend to
     * the property keys for Properties lookups.
     *
     * @return the property prefix for the menu
     */
    public String getPropertyPrefix() {
        return propertyPrefix;
    }
}
TOP

Related Classes of com.bbn.openmap.gui.AbstractOpenMapMenu

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.