/* **********************************************************************
*
* Use, duplication, or disclosure by the Government is subject to
* restricted rights as set forth in the DFARS.
*
* BBNT Solutions LLC
* A Part of
* Verizon
* 10 Moulton Street
* Cambridge, MA 02138
* (617) 873-3000
*
* Copyright (C) 2002 by BBNT Solutions, LLC
* All Rights Reserved.
* ********************************************************************** */
package com.bbn.openmap.tools.beanbox;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.beans.BeanInfo;
import java.util.HashMap;
import java.util.Vector;
import com.bbn.openmap.image.ImageScaler;
import com.bbn.openmap.util.Debug;
/**
* The BeanBox class manages a set of java beans that are delivered to
* it from the {@link com.bbn.openmap.tools.beanbox.BeanPanel}via the
* {@link com.bbn.openmap.tools.beanbox.BeanBoxDnDCatcher}. An
* implementation of this abstract class is expected to be associated
* with an openmap layer. The abstract BeanBox class performs
* functions such as adding and removing beans from the associated
* openmap layer and provides support for moving beans on the layer
* and cut/copy/paste functionality.
* <p>
* Layer developers wishing to make use of the BeanBox's bean
* management capabilities should:
* <p>
* <ul>
* <li>Implement a layer specific version of this abstract class.
* </li>
* <li>Implement the
* {@link com.bbn.openmap.tools.beanbox.BeanBoxHandler}interface in
* the layer associated with the BeanBox implementation.</li>
* </ul>
* <p>
*
* An implementation of this class should provide layer specific
* versions of at least the following abstract base class methods:
* <p>
* <ul>
* <li>addBean</li>
* <li>removeBean</li>
* <li>containsBean</li>
* <li>setBeanProperties</li>
* <li>getBeanAtLocation</li>
* <li>findEnclosingContainer (should always return null if
* implementation does not support
* {@link com.bbn.openmap.tools.beanbox.BeanContainer}s)</li>
* <li>relocateBean</li>
* <li>beanChanged</li>
* </ul>
* <p>
* Additionally, an implementation of this class can optionally
* provide layer specific versions of the following base class
* methods:
* <p>
* <ul>
* <li>showSelected</li>
* <li>showCut</li>
* <li>showUnCut</li>
* </ul>
* <p>
*/
public abstract class BeanBox {
private HashMap beanInfoMap;
/**
* Default constructor initializes the BeanBox.
*/
public BeanBox() {
beanInfoMap = new HashMap();
}
/**
* Utility method to obtain the BeanInfo object associated with a
* bean class that the BeanBox knows about. Returns a null if none
* found.
*/
public BeanInfo getBeanInfoForBean(String beanClassName) {
BeanInfo beanInfo = (BeanInfo) beanInfoMap.get(beanClassName);
if (beanInfo == null) {
beanInfo = BeanPanel.findBeanInfo(beanClassName);
if (beanInfo != null)
beanInfoMap.put(beanClassName, beanInfo);
}
return beanInfo;
}
/**
* This method is called by the BeanBoxDnDCatcher to give the
* BeanBox the bean has has just been dropped on the map.
*
* @param object a Vector containing in the following order: the dropped
* bean object, its BeanInfo and a Point object containing
* the drop location.
*/
void addBean(Vector object) {
if (object == null || object.size() != 3
|| !(object.get(1) instanceof BeanInfo)
|| !(object.get(2) instanceof Point)) {
throw new IllegalArgumentException("bad drop object " + object);
}
Object bean = object.get(0);
BeanInfo beanInfo = (BeanInfo) object.get(1);
Point point = (Point) object.get(2);
beanInfoMap.put(bean.getClass().getName(), beanInfo);
prepareForAddition(bean, beanInfo, point);
}
/**
* This method is called by a
* {@link com.bbn.openmap.tools.beanbox.GenericPropertySheet}when
* the user closes the propertysheet window.
*/
void editComplete(Object bean) {
if (!containsBean(bean)) {
addBean(bean);
doSpecialHandling(bean);
}
}
/**
* This method is called to prepare the bean for addition to the
* beanbox. In the base class implementation, this method calls
* the abstract setBeanProperties method. It then displays the
* property sheet for the bean, thereby giving the user a chance
* to edit the bean's properties before the bean is added to the
* beanbox.
*/
protected void prepareForAddition(Object bean, BeanInfo beanInfo,
Point location) {
try {
setBeanProperties(bean, beanInfo, location);
createPropertySheet(bean);
} catch (Exception e) {
//System.out.println(e);
e.printStackTrace();
}
}
/**
* Utility method to create and display a property sheet to show
* the specified bean's properties.
*/
protected void createPropertySheet(Object bean) throws Exception {
// Create a new Property Sheet.
GenericPropertySheet propertySheet = new GenericPropertySheet(bean, 575, 20, null, this);
propertySheet.setVisible(true);
}
/**
* Checks if the specified bean should be added to a
* {@link com.bbn.openmap.tools.beanbox.BeanContainer}.
*/
protected void doSpecialHandling(Object bean) {
// if bean is a container, add its id to our list of
// containers
// adding containers to other containers is not handled for
// now because of unresolved issues about treating
// over-lapping
// containers.
if (!(bean instanceof BeanContainer)) {
// check if the bean was dropped into a container,
// if so add it to the container
BeanContainer container = findEnclosingContainer(bean);
if (container != null)
container.add(bean);
}
}
/**
* Returns the image that the cursor will be set to when the
* specified bean is dragged over the map. Default implementation
* returns the image contained in the BeanInfo for the bean, or
* the default BeanPanel image if no image is found in the
* BeanInfo.
*/
protected Image getDragImage(Object bean) {
BeanInfo beanInfo = this.getBeanInfoForBean(bean.getClass().getName());
if (beanInfo == null) {
if (Debug.debugging("beanbox"))
Debug.output("No beanInfo found for bean: " + bean);
return BeanPanel.defaultBeanIcon.getImage();
}
Image img = beanInfo.getIcon(BeanInfo.ICON_COLOR_32x32);
if (img == null) {
if (Debug.debugging("beanbox"))
Debug.output("No image found in beanInfo for bean: " + bean);
return BeanPanel.defaultBeanIcon.getImage();
}
Dimension d = Toolkit.getDefaultToolkit().getBestCursorSize(16, 16);
if (Debug.debugging("beanbox"))
Debug.output("" + d);
img = ImageScaler.getOptimalScalingImage(img,(int) d.getWidth(),
(int) d.getHeight());
return img;
}
/**
* This method is called when the user selects a bean, usually as
* a a result of the clicking on it in a layer. An implementation
* of this class can override this method to highlight the
* selected bean using a mechanism specific to the openmap layer
* associated with that BeanBox. Base class method does nothing.
*/
public void showSelected(Object bean) {}
/**
* This method is called when the user 'cuts' a bean, usually as a
* a result of the clicking on it in a layer and then pressing
* Ctrl-X. An implementation of this class can override this
* method to highlight the selected bean using a mechanism
* specific to the openmap layer associated with that BeanBox.
* Base class method does nothing.
*/
public void showCut(Object bean) {}
/**
* This method is called when the user cancels a 'cut' operation,
* usually as a a result of pressing the ESC key. An
* implementation of this class can override this method to remove
* any highlights on the bean marked for cutting. Base class
* method does nothing.
*/
public void showUnCut(Object bean) {}
/**
* This method is called when a bean is dropped on the layer
* associated with this BeanBox.
*/
public abstract void addBean(Object bean);
/**
* This method is called when a bean is moved from the layer
* associated with this BeanBox to another layer.
*/
public abstract void removeBean(Object bean);
/**
* This method is intended to check whether this BeanBox knows
* about the specified bean.
*/
public abstract boolean containsBean(Object bean);
/**
* This method is called when a bean is dropped on the layer
* associated with this BeanBox. This method gives a chance to set
* the dropped bean's properties based on the information in its
* BeanInfo and the drop location. The called to addBean follows
* this call in the drop sequence.
*/
public abstract void setBeanProperties(Object bean, BeanInfo beanInfo,
Point location);
/**
* Returns a bean contained in the layer at the specified map
* location.
*
* @return a bean Object or null if no bean is found at the
* location.
*/
public abstract Object getBeanAtLocation(Point pointOnMap);
/**
* Returns a bean contained in the layer that implements the
* BeanContainer interface and which contains the specified bean.
*
* @return a BeanContainer object or null if no such container
* bean is found.
*/
public abstract BeanContainer findEnclosingContainer(Object bean);
/**
* This method is called when a bean is moved from its present
* location to the newlocation within the layer associated with
* this BeanBox.
*/
public abstract void relocateBean(Object bean, BeanInfo beanInfo,
Point newLocation);
/**
* This method is called by a propertysheet whenever a bean
* property changes. It is intended to provide a place for the
* layer developer to update the layer if required.
*/
public abstract void beanChanged(Object bean, String changedPropertyName);
}