// ********************************************************************** // // <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/LayerAddPanel.java,v $ // $RCSfile: LayerAddPanel.java,v $ // $Revision: 1.9 $ // $Date: 2006/02/14 20:55:52 $ // $Author: dietrick $ // // ********************************************************************** package com.bbn.openmap.gui; import java.awt.Frame; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.Serializable; import java.util.Hashtable; import java.util.Properties; import java.util.Set; import java.util.Vector; import javax.swing.InputVerifier; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JOptionPane; import javax.swing.JTextField; import com.bbn.openmap.Environment; import com.bbn.openmap.Layer; import com.bbn.openmap.LayerHandler; import com.bbn.openmap.MapHandler; import com.bbn.openmap.PropertyConsumer; import com.bbn.openmap.PropertyHandler; import com.bbn.openmap.plugin.PlugIn; import com.bbn.openmap.plugin.PlugInLayer; import com.bbn.openmap.util.ComponentFactory; import com.bbn.openmap.util.Debug; import com.bbn.openmap.util.PropUtils; import com.bbn.openmap.util.propertyEditor.Inspector; /** * Class to interactively add a Layer to the map. A LayerAddPanel utilizes the * bean context mechanisms to keep up to date about the applications * LayerHandler and PropertyHandler (see findAndInit method). A property is used * to determine objects of which Layer subclasses can be instantiated (see * static String layerTypes), for configuration of a layer-to-be an Inspector is * invoked to inspect and configure a Layer object through the PropertyConsumer * interface. */ public class LayerAddPanel extends OMComponentPanel implements Serializable, ActionListener { /** * Constant field containing markers used in properties file for layers that * can be created using the LayerAddPanel. */ public final static String layerTypes = "addableLayers"; /** * Holds the PropertyHandler. */ protected PropertyHandler propertyHandler = null; /** * Holds the LayerHandler. */ protected LayerHandler layerHandler = null; /** * The list of available Layer classes. Is initiated with pretty names. */ protected JComboBox list = null; /** * Text field used to define new Layer class to create. */ protected JTextField classTextField = null; /** The String to use as a prefix for the new Layer's properties. */ protected JTextField prefixTextField = null; /** Action command String for JButton. */ protected final String configureActionCommand = "configureActionCommand"; /** Contains Layer classes to be instantiated. */ protected Hashtable<String, String> layerClasses = null; /** The Inspector to handle the configuration of the new Layer. */ protected Inspector inspector = null; /** The layer to configure and add. */ protected Object layer; /** * JButton to use to create new Layer. */ protected JButton configureButton; /** * Creates the LayerPanel. */ public LayerAddPanel() { super(); if (Debug.debugging("addable")) { Debug.output("LayerAddPanel()"); } inspector = new Inspector(); inspector.addActionListener((ActionListener) this); } /** * Creates the LayerPanel. * * @param l the LayerHandler controlling the layers. */ public LayerAddPanel(PropertyHandler p, LayerHandler l) { this(); propertyHandler = p; layerHandler = l; } public void createLayerClasses(Layer[] layers) { getLayerClasses().clear(); for (Layer l : layers) { String name = l.getName(); if (name == null) { name = l.getClass().getName(); int lastDotIndex = name.lastIndexOf('.'); if (lastDotIndex >= 0) { name = name.substring(lastDotIndex); } } addLayer(name, l.getClass().getName()); } } /** * Produces a dialog panel to add a Layer, with the layers given. */ public void createPanel(Layer[] layers) { createLayerClasses(layers); createPanel(); } public final static String DefaultLayerName = "Layer Name"; /** * Produces a dialog panel to add a layer. If the layers haven't been * manually added through createPanel(layers), then the PropertyHandler is * consulted and the layer list is built from the layerTypes property. */ public void createPanel() { removeAll(); configureButton = new JButton(i18n.get(LayerAddPanel.class, "configureButton", "Configure")); configureButton.addActionListener(this); configureButton.setActionCommand(configureActionCommand); String defaultLayerName = i18n.get(LayerAddPanel.class, "defaultLayerName", DefaultLayerName); prefixTextField = new JTextField(defaultLayerName, 12); Set<String> keys = getLayerClasses().keySet(); String[] layerTypes = keys.toArray(new String[keys.size()]); GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); setLayout(gridbag); c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1.0; c.gridwidth = GridBagConstraints.REMAINDER; c.insets = new Insets(10, 10, 5, 10); if (layerTypes.length == 0) { configureButton.setEnabled(false); classTextField = new JTextField(30); classTextField.setToolTipText(i18n.get(LayerAddPanel.class, "classFieldToolTip", "Class name of layer to add")); /* * // Since there's no list provided, give a text box to let the * user // specify which layer to create. String message = * i18n.get(LayerAddPanel.class, "noLayersAvailableMessage", * "No Layers available for creation."); JLabel label = new * JLabel(message); */ classTextField.setInputVerifier(new InputVerifier() { @Override public boolean verify(JComponent input) { JTextField tf = (JTextField) input; String className = tf.getText(); try { ClassLoader.getSystemClassLoader().loadClass(className); } catch (ClassNotFoundException cnfe) { configureButton.setEnabled(false); return false; } configureButton.setEnabled(true); return true; } }); gridbag.setConstraints(classTextField, c); add(classTextField); configureButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String newClassName = (String) classTextField.getText(); String prefix = prefixTextField.getText().trim(); createLayer(newClassName, prefix); } }); } else { list = new JComboBox(layerTypes); gridbag.setConstraints(list, c); add(list); configureButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String prettyName = (String) list.getSelectedItem(); String prefix = prefixTextField.getText().trim(); if (prettyName == null) { return; } String newClassName = layerClasses.get(prettyName); createLayer(newClassName, prefix); } }); } // Prefix/Name field c.insets = new Insets(5, 10, 10, 10); c.gridwidth = GridBagConstraints.RELATIVE; gridbag.setConstraints(prefixTextField, c); add(prefixTextField); // Add configure button c.weightx = 0; gridbag.setConstraints(configureButton, c); add(configureButton); invalidate(); } public Hashtable<String, String> getLayerClasses() { if (layerClasses == null) { layerClasses = new Hashtable<String, String>(); } return layerClasses; } public void addLayer(String prettyName, String className) { getLayerClasses().put(prettyName, className); } public void setProperties(String prefix, Properties props) { super.setProperties(prefix, props); if (Debug.debugging("addable")) { Debug.output("LayerAddPanel.setProperties()"); } getLayerTypes(props); } public Properties getProperties(Properties props) { props = super.getProperties(props); int layerNumber = 1; if (layerClasses != null) { StringBuffer layerList = new StringBuffer(); for (String prettyName : layerClasses.keySet()) { String className = (String) layerClasses.get(prettyName); String markerName = "l" + (layerNumber++); layerList.append(markerName).append(" "); props.put(markerName + ".prettyName", prettyName); props.put(markerName + ".class", className); } props.put(Environment.OpenMapPrefix + "." + layerTypes, layerList.toString()); } return props; } /** * Gets Layer information from PropertyHandler. These layers are defined in * the application properties under the openmap.layerTypes property. * * @return Hashtable of prettyName String keys with classname values. Empty * Hashtable if no layers are available. */ protected Hashtable<String, String> getLayerTypes() { return getLayerTypes(null); } /** * Gets Layer information from the given properties. These layers are * defined in the application properties under the openmap.layerTypes * property. If the given properties are null, then the property handler, if * found, will be consulted directly. * * @return Hashtable of prettyName String keys with classname values. Empty * Hashtable if no layers are available. */ protected Hashtable<String, String> getLayerTypes(Properties props) { Hashtable<String, String> layerHash = getLayerClasses(); layerHash.clear(); if (props == null) { if (propertyHandler != null) { props = propertyHandler.getProperties(); } else { return layerHash; } } String prefix = Environment.OpenMapPrefix; String addableList = props.getProperty(prefix + "." + layerTypes); if (Debug.debugging("addable")) { Debug.output("LayerAddPanel: " + addableList); } Vector<String> layerClassList = PropUtils.parseSpacedMarkers(addableList); if (layerClassList == null) { return layerHash; } // debug info: available layers int unNamedCount = 1; for (String layerClassString : layerClassList) { String className = props.getProperty(layerClassString + ".class"); String prettyName = props.getProperty(layerClassString + ".prettyName"); if (prettyName == null) { prettyName = "Layer " + (unNamedCount++); } if (className != null) { if (Debug.debugging("addable")) { Debug.output(" adding " + className + ", " + className); } layerHash.put(prettyName, className); } } return layerHash; } /** * Create a layer given a class name and property prefix to be used as a * name. * * @param className class of layer to create. * @param prefix pretty name and property prefix. */ protected void createLayer(String className, String prefix) { Object obj = ComponentFactory.create(className); if (obj instanceof Layer || obj instanceof PlugIn) { if (obj instanceof PlugIn) { PlugInLayer pil = new PlugInLayer(); pil.setPlugIn((PlugIn) obj); layer = pil; } else { layer = (Layer) obj; } // Set the pretty name to what the user chose. ((Layer) layer).setName(prefix); prefixTextField.setText(""); if (classTextField != null) { classTextField.setText(""); } WindowSupport ws = getWindowSupport(); if (ws != null) { ws.cleanUp(); } } if (obj instanceof PropertyConsumer) { // Set the prefix to a modified version of the pretty name. prefix = propertyHandler.getUniquePrefix(prefix); ((PropertyConsumer) obj).setPropertyPrefix(prefix); inspector.inspectPropertyConsumer((PropertyConsumer) obj); } } /** * Method associated with the ActionListener interface. */ public void actionPerformed(ActionEvent e) { if (e.getActionCommand() == Inspector.doneCommand) { // the confirmation button of the Inspector panel was // pressed // find the beancontext and add the layer at hand (var. // layer) if (layer != null && layerHandler != null) { if (layer instanceof Layer) { // Let's add it on top, so the user can find it // easier, instead of adding it to the bottom and // having it lost behind some other layers. layerHandler.addLayer((Layer) layer, 0); } prefixTextField.setText(DefaultLayerName); } else if (layerHandler != null) { String message = i18n.get(LayerAddPanel.class, "noLayerHandlerMessage", "Layer Handler not found.\nCan't find anything to add the layer to."); JOptionPane.showMessageDialog(this, message); } else { String message = i18n.get(LayerAddPanel.class, "noLayerCreatedMessage", "No Layer instantiated."); JOptionPane.showMessageDialog(this, message); } } else if (e.getActionCommand() == Inspector.cancelCommand) { if (layer != null && propertyHandler != null) { propertyHandler.removeUsedPrefix(((PropertyConsumer) layer).getPropertyPrefix()); } } } /** * Show the panel in a JFrame. */ public void showPanel() { createPanel(); prefixTextField.setText(DefaultLayerName); WindowSupport ws = getWindowSupport(); MapHandler mh = (MapHandler) getBeanContext(); Frame frame = null; if (mh != null) { frame = (Frame) mh.get(java.awt.Frame.class); } if (ws == null) { ws = new WindowSupport(this, i18n.get(LayerAddPanel.class, "title", "Add Layer")); setWindowSupport(ws); } ws.displayInWindow(frame, -1, -1, -1, -1); } /** * Looks for PropertyHandler and LayerHandler. */ public void findAndInit(Object someObj) { if (someObj instanceof PropertyHandler) { // do the initializing that need to be done here Debug.message("layerspanel", "LayerAddPanel found a LayerHandler"); propertyHandler = (PropertyHandler) someObj; } if (someObj instanceof LayerHandler) { layerHandler = (LayerHandler) someObj; } } /** * Disconnect from any objects that are removed from MapHandler. */ public void findAndUndo(Object someObj) { if (someObj instanceof PropertyHandler && propertyHandler == someObj) { // do the initializing that need to be done here Debug.message("addable", "LayerAddPanel removing PropertyHandler"); propertyHandler = null; } if (someObj instanceof LayerHandler && someObj == layerHandler) { Debug.message("addable", "LayerAddPanel removing LayerHandler"); layerHandler = null; } } }