//**********************************************************************
//
//<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/tools/dnd/DropListenerSupport.java,v $
//$RCSfile: DropListenerSupport.java,v $
//$Revision: 1.3 $
//$Date: 2005/08/09 20:45:09 $
//$Author: dietrick $
//
//**********************************************************************
package com.bbn.openmap.tools.dnd;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
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.MapBean;
import com.bbn.openmap.SoloMapComponent;
import com.bbn.openmap.util.Debug;
/**
* The DropListenerSupport manages the DefaultDnDCatchers that handle
* Drag and Drop events on the map. There should only be one
* DropListenerSupport within a MapHandler.
*
* DropListenerSupport keeps a list of all DefaultDnDCatcher objects
* from a MapHandler. It adds itself to the MapBean as MouseListener
* and MouseMotionListener. On MousePressed, MouseDragged, and
* MouseReleased events it loops through the DnDCatchers and invokes a
* consume() method in each of them.
*
* @see DefaultDnDCatcher
*/
public class DropListenerSupport implements PropertyChangeListener,
java.io.Serializable, BeanContextChild, BeanContextMembershipListener,
SoloMapComponent, MouseListener, MouseMotionListener {
/**
* Holds a list of DefaultDndCatchers
*/
protected transient Vector dndCatchers = new Vector(2);
/**
* The MapBean.
*/
protected transient MapBean map;
/**
* PropertyChangeSupport for handling listeners.
*/
protected PropertyChangeSupport pcSupport = new PropertyChangeSupport(this);
/**
* BeanContextChildSupport object provides helper functions for
* BeanContextChild interface.
*/
protected BeanContextChildSupport beanContextChildSupport = new BeanContextChildSupport();
/**
* Construct a DropListenerSupport without an associated MapBean.
* You will need to set the MapBean via <code>setMap()</code>.
*
* @see #setMap
*/
public DropListenerSupport() {
this(null);
}
/**
* Construct a DropListenerSupport with an associated MapBean.
*
* @param map MapBean
*/
public DropListenerSupport(MapBean map) {
setMap(map);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(listener);
}
/** Method for BeanContextChild interface. */
public void addPropertyChangeListener(String propertyName,
PropertyChangeListener in_pcl) {
pcSupport.addPropertyChangeListener(propertyName, in_pcl);
}
/** Method for BeanContextChild interface. */
public void addVetoableChangeListener(String propertyName,
VetoableChangeListener in_vcl) {
beanContextChildSupport.addVetoableChangeListener(propertyName, in_vcl);
}
/**
* 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
* DropListenerSupport looks for the MapBean it is managing
* MouseEvents for, and any DefaultDndCatchers 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 when an object should be evaluated by the
* DropListenerSupport to see if it is needed.
*/
public void findAndInit(Object someObj) {
if (someObj instanceof MapBean) {
Debug.message("droplistenersupport",
"DropListenerSupport found a map.");
setMap((MapBean) someObj);
}
if (someObj instanceof DefaultDnDCatcher) {
getBeanContext().addBeanContextMembershipListener((DefaultDnDCatcher) someObj);
Debug.message("DropListener",
"DropListener found a DefaultDnDCatcher.");
dndCatchers.addElement(someObj);
}
}
/**
* Eventually gets called when the DropListenerSupport is added to
* the BeanContext, and when other objects are added to the
* BeanContext anytime after that. The DropListenerSupport looks
* for a MapBean to manage MouseEvents for, and DefaultDndCatchers
* 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 by childrenRemoved.
*/
public void findAndUndo(Object someObj) {
if (someObj instanceof MapBean) {
if (getMap() == (MapBean) someObj) {
Debug.message("droplistenersupport",
"DropListenerSupport: removing the map.");
setMap(null);
}
}
}
public void firePropertyChange(String property, Object oldObj, Object newObj) {
pcSupport.firePropertyChange(property, oldObj, newObj);
}
/**
* 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);
}
/** Method for BeanContextChild interface. */
public BeanContext getBeanContext() {
return beanContextChildSupport.getBeanContext();
}
/**
* Get the associated MapBean.
*
* @return MapBean
*/
public MapBean getMap() {
return map;
}
/**
* Invoked when the mouse has been clicked on a component.
*/
public void mouseClicked(java.awt.event.MouseEvent e) {}
/**
* Invoked when a mouse button is pressed on a component and then
* dragged. Mouse drag events will continue to be delivered to the
* component where the first originated until the mouse button is
* released (regardless of whether the mouse position is within
* the bounds of the component).
*/
public void mouseDragged(java.awt.event.MouseEvent e) {
for (int i = 0; i < dndCatchers.size(); i++) {
if (((DefaultDnDCatcher) dndCatchers.get(i)).consume(e))
break;
}
}
/**
* Invoked when the mouse enters a component.
*/
public void mouseEntered(java.awt.event.MouseEvent e) {}
/**
* Invoked when the mouse exits a component.
*/
public void mouseExited(java.awt.event.MouseEvent e) {}
/**
* Invoked when the mouse button has been moved on a component
* (with no buttons no down).
*/
public void mouseMoved(java.awt.event.MouseEvent e) {}
/**
* Invoked when a mouse button has been pressed on a component.
*/
public void mousePressed(java.awt.event.MouseEvent e) {
for (int i = 0; i < dndCatchers.size(); i++) {
if (((DefaultDnDCatcher) dndCatchers.get(i)).consume(e))
break;
}
}
/**
* Invoked when a mouse button has been released on a component.
*/
public void mouseReleased(java.awt.event.MouseEvent e) {
for (int i = 0; i < dndCatchers.size(); i++) {
if (((DefaultDnDCatcher) dndCatchers.get(i)).consume(e))
break;
}
}
/**
* PropertyChangeListenter Interface method.
*
* @param evt PropertyChangeEvent
*/
public void propertyChange(PropertyChangeEvent evt) {}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcSupport.removePropertyChangeListener(listener);
}
/** Method for BeanContextChild interface. */
public void removePropertyChangeListener(String propertyName,
PropertyChangeListener in_pcl) {
pcSupport.removePropertyChangeListener(propertyName, in_pcl);
}
/** Method for BeanContextChild interface. */
public void removeVetoableChangeListener(String propertyName,
VetoableChangeListener in_vcl) {
beanContextChildSupport.removeVetoableChangeListener(propertyName,
in_vcl);
}
/** 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());
}
}
/**
* Set the associated MapBean.
*
* @param mapbean MapBean
*/
public void setMap(MapBean mapbean) {
if (map != null) {
map.removePropertyChangeListener(this);
map.removeMouseListener(this);
map.removeMouseMotionListener(this);
}
map = mapbean;
if (map != null) {
map.addPropertyChangeListener(this);
map.addMouseListener(this);
map.addMouseMotionListener(this);
}
}
}