// **********************************************************************
//
// <copyright>
//
// BBN Technologies, a Verizon Company
// 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/plugin/AbstractPlugIn.java,v $
// $RCSfile: AbstractPlugIn.java,v $
// $Revision: 1.8.2.4 $
// $Date: 2006/01/13 21:04:22 $
// $Author: dietrick $
//
// **********************************************************************
package com.bbn.openmap.plugin;
import java.awt.Component;
import java.awt.event.MouseEvent;
import java.util.Properties;
import com.bbn.openmap.Environment;
import com.bbn.openmap.I18n;
import com.bbn.openmap.Layer;
import com.bbn.openmap.PropertyConsumer;
import com.bbn.openmap.event.MapMouseListener;
import com.bbn.openmap.event.SelectMouseMode;
import com.bbn.openmap.omGraphics.OMGraphicList;
import com.bbn.openmap.proj.Projection;
import com.bbn.openmap.util.PropUtils;
/**
* This class is an abstract implementation of the PlugIn. It takes care of
* setting up the layer, setting properties, etc.
*
* @see com.bbn.openmap.plugin.PlugInLayer
* @see com.bbn.openmap.plugin.PlugIn
*/
public abstract class AbstractPlugIn implements PlugIn, PropertyConsumer,
MapMouseListener {
/**
* Property 'removable' to designate this layer as removable from the
* application, or able to be deleted. True by default.
*/
public static final String RemovableProperty = "removable";
/**
* Flag to designate the layer as removable or not.
*/
protected boolean removable = true;
/** The parent component, usually the PlugInLayer. */
protected Component component = null;
/** The prefix for the plugin's properties. */
protected String prefix = null;
/**
* The pretty name for a plugin, if it was set in the properties.
*/
protected String name = this.getClass().getName();
/**
* The object handling mouse events for the plugin. By default, the Plugin
* is it, but it doesn't have to be.
*/
protected MapMouseListener mml = this;
/**
* Flag to denote whether the plugin should be added to the bean context
* (MapHandler). True by default.
*/
protected boolean addToBeanContext = true;
/**
* Internationalization
*/
public I18n i18n = Environment.getI18n();
public AbstractPlugIn() {}
public AbstractPlugIn(Component comp) {
setComponent(comp);
}
/**
* Set the name of the plugin. If the parent component is a layer, set its
* pretty name as well.
*/
public void setName(String name) {
this.name = name;
Component comp = getComponent();
if (comp != null) {
comp.setName(name);
}
}
/**
* Get the pretty name of the plugin, which is really the pretty name of the
* parent component if it's set.
*/
public String getName() {
Component comp = getComponent();
if (comp != null) {
name = comp.getName();
}
return name;
}
/**
* Set the component that this PlugIn uses as a grip to the map.
*/
public void setComponent(Component comp) {
this.component = comp;
}
/**
* Get the component that this plugin uses as a grip to the map.
*/
public Component getComponent() {
return component;
}
/**
* Call repaint on the parent component.
*/
public void repaint() {
component.repaint();
}
/**
* Checks to see if the parent component is a PlugInLayer, and calls
* doPrepare() on it if it is.
*/
public void doPrepare() {
if (component instanceof PlugInLayer) {
((PlugInLayer) component).doPrepare();
}
}
/**
* Set the MapMouseListener for this PlugIn. The MapMouseListener is
* responsible for handling the MouseEvents that are occuring over the layer
* using the PlugIn, as well as being able to let others know which
* MouseModes are of interest to receive MouseEvents from.
*
* @param mml MapMouseListener.
*/
public void setMapMouseListener(MapMouseListener mml) {
this.mml = mml;
}
/**
* Returns the MapMouseListener that the plugin thinks should be used.
*/
public MapMouseListener getMapMouseListener() {
return mml;
}
/**
* The getRectangle call is the main call into the PlugIn module. The module
* is expected to fill a graphics list with objects that are within the
* screen parameters passed. It's assumed that the PlugIn will call
* generate(projection) on the OMGraphics returned! If you don't call
* generate on the OMGraphics, they will not be displayed on the map.
*
* @param p projection of the screen, holding scale, center coords, height,
* width. May be null if the parent component hasn't been given a
* projection.
*/
public abstract OMGraphicList getRectangle(Projection p);
/**
*/
public Component getGUI() {
return null;
}
public void setAddToBeanContext(boolean value) {
addToBeanContext = value;
}
public boolean getAddToBeanContext() {
return addToBeanContext;
}
/**
* Mark the plugin (and layer) as removable, or one that can be deleted from
* the application. What that means is up to the LayerHandler or other
* application components.
*/
public void setRemovable(boolean set) {
this.removable = set;
Component comp = getComponent();
if ((comp != null) && (comp instanceof Layer)) {
((Layer) comp).setRemovable(set);
}
}
/**
* Check to see if the plugin (and layer) is marked as one that can be
* removed from an application.
*
* @return true if plugin should be allowed to be deleted.
*/
public boolean isRemovable() {
Component comp = getComponent();
if ((comp != null) && (comp instanceof Layer)) {
this.removable = ((Layer) comp).isRemovable();
}
return removable;
}
// //// PropertyConsumer Interface Methods
/**
* Method to set the properties in the PropertyConsumer. It is assumed that
* the properties do not have a prefix associated with them, or that the
* prefix has already been set.
*
* @param setList a properties object that the PropertyConsumer can use to
* retrieve expected properties it can use for configuration.
*/
public void setProperties(Properties setList) {
setProperties(null, setList);
}
/**
* Method to set the properties in the PropertyConsumer. The prefix is a
* string that should be prepended to each property key (in addition to a
* separating '.') in order for the PropertyConsumer to uniquely identify
* properies meant for it, in the midst of of Properties meant for several
* objects.
*
* @param prefix a String used by the PropertyConsumer to prepend to each
* property value it wants to look up -
* setList.getProperty(prefix.propertyKey). If the prefix had already
* been set, then the prefix passed in should replace that previous
* value.
* @param setList a Properties object that the PropertyConsumer can use to
* retrieve expected properties it can use for configuration.
*/
public void setProperties(String prefix, Properties setList) {
setPropertyPrefix(prefix);
String realPrefix = PropUtils.getScopedPropertyPrefix(prefix);
name = setList.getProperty(realPrefix + Layer.PrettyNameProperty);
setAddToBeanContext(PropUtils.booleanFromProperties(setList, realPrefix
+ Layer.AddToBeanContextProperty, addToBeanContext));
setRemovable(PropUtils.booleanFromProperties(setList, realPrefix
+ RemovableProperty, removable));
}
/**
* Method to fill in a Properties object, reflecting the current values of
* the PropertyConsumer. If the PropertyConsumer has a prefix set, the
* property keys should have that prefix plus a separating '.' prepended to
* each propery key it uses for configuration.
*
* @param getList 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 getProperties(Properties getList) {
if (getList == null) {
getList = new Properties();
}
String realPrefix = PropUtils.getScopedPropertyPrefix(this);
getList.put(realPrefix + Layer.AddToBeanContextProperty,
new Boolean(addToBeanContext).toString());
getList.put(prefix + RemovableProperty,
new Boolean(removable).toString());
return getList;
}
/**
* 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.).
*
* @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();
}
String internString = i18n.get(Layer.class,
Layer.AddToBeanContextProperty,
I18n.TOOLTIP,
"Flag to give access to all of the other application components.");
list.put(Layer.AddToBeanContextProperty, internString);
internString = i18n.get(Layer.class,
Layer.AddToBeanContextProperty,
"Add to MapHandler");
list.put(Layer.AddToBeanContextProperty + LabelEditorProperty, internString);
list.put(Layer.AddToBeanContextProperty + ScopedEditorProperty,
"com.bbn.openmap.util.propertyEditor.YesNoPropertyEditor");
internString = i18n.get(AbstractPlugIn.class,
RemovableProperty,
I18n.TOOLTIP,
"Flag to allow layer to be deleted.");
list.put(RemovableProperty, internString);
internString = i18n.get(Layer.class, RemovableProperty, "Removable");
list.put(RemovableProperty + LabelEditorProperty, internString);
list.put(RemovableProperty + ScopedEditorProperty,
"com.bbn.openmap.util.propertyEditor.YesNoPropertyEditor");
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) {
this.prefix = 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 plugin.
*/
public String getPropertyPrefix() {
return prefix;
}
// /////// MapMouseListener interface methods
/**
* Return a list of the modes that are interesting to the MapMouseListener.
* The source MouseEvents will only get sent to the MapMouseListener if the
* mode is set to one that the listener is interested in. Layers interested
* in receiving events should register for receiving events in "select"
* mode: <code>
* <pre>
* return new String[] { SelectMouseMode.modeID };
* </pre>
* <code>
* @return String[] of modeID's
* @see com.bbn.openmap.event.NavMouseMode#modeID
* @see com.bbn.openmap.event.SelectMouseMode#modeID
* @see com.bbn.openmap.event.NullMouseMode#modeID
*/
public String[] getMouseModeServiceList() {
return new String[] { SelectMouseMode.modeID };
}
// Mouse Listener events
// //////////////////////
/**
* Invoked when a mouse button has been pressed on a component.
*
* @param e MouseEvent
* @return true if the listener was able to process the event.
*/
public boolean mousePressed(MouseEvent e) {
return false;
}
/**
* Invoked when a mouse button has been released on a component.
*
* @param e MouseEvent
* @return true if the listener was able to process the event.
*/
public boolean mouseReleased(MouseEvent e) {
return false;
}
/**
* Invoked when the mouse has been clicked on a component. The listener will
* receive this event if it successfully processed
* <code>mousePressed()</code>, or if no other listener processes the
* event. If the listener successfully processes <code>mouseClicked()</code>,
* then it will receive the next <code>mouseClicked()</code> notifications
* that have a click count greater than one.
* <p>
* NOTE: We have noticed that this method can sometimes be erroneously
* invoked. It seems to occur when a light-weight AWT component (like an
* internal window or menu) closes (removes itself from the window
* hierarchy). A specific OpenMap example is when you make a menu selection
* when the MenuItem you select is above the MapBean canvas. After making
* the selection, the mouseClicked() gets invoked on the MouseDelegator,
* which passes it to the appropriate listeners depending on the MouseMode.
* The best way to avoid this problem is to not implement anything crucial
* in this method. Use a combination of <code>mousePressed()</code> and
* <code>mouseReleased()</code> instead.
*
* @param e MouseEvent
* @return true if the listener was able to process the event.
*/
public boolean mouseClicked(MouseEvent e) {
return false;
}
/**
* Invoked when the mouse enters a component.
*
* @param e MouseEvent
*/
public void mouseEntered(MouseEvent e) {}
/**
* Invoked when the mouse exits a component.
*
* @param e MouseEvent
*/
public void mouseExited(MouseEvent e) {}
// Mouse Motion Listener events
// /////////////////////////////
/**
* Invoked when a mouse button is pressed on a component and then dragged.
* The listener will receive these events if it successfully processes
* mousePressed(), or if no other listener processes the event.
*
* @param e MouseEvent
* @return true if the listener was able to process the event.
*/
public boolean mouseDragged(MouseEvent e) {
return false;
}
/**
* Invoked when the mouse button has been moved on a component (with no
* buttons down).
*
* @param e MouseEvent
* @return true if the listener was able to process the event.
*/
public boolean mouseMoved(MouseEvent e) {
return false;
}
/**
* Handle a mouse cursor moving without the button being pressed. This event
* is intended to tell the listener that there was a mouse movement, but
* that the event was consumed by another layer. This will allow a mouse
* listener to clean up actions that might have happened because of another
* motion event response.
*/
public void mouseMoved() {}
/**
* Method that gets called when the PlugInLayer has been removed from the
* map, so the PlugIn can free up resources.
*/
public void removed() {}
}