// ********************************************************************** // // <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/layer/editor/EditorLayer.java,v $ // $RCSfile: EditorLayer.java,v $ // $Revision: 1.14 $ // $Date: 2006/04/11 00:15:06 $ // $Author: dietrick $ // // ********************************************************************** package com.bbn.openmap.layer.editor; import java.awt.Container; import java.util.Properties; import javax.swing.JPanel; import javax.swing.SwingConstants; import com.bbn.openmap.InformationDelegator; import com.bbn.openmap.event.SelectMouseMode; import com.bbn.openmap.gui.Tool; import com.bbn.openmap.layer.DrawingToolLayer; import com.bbn.openmap.omGraphics.OMAction; import com.bbn.openmap.omGraphics.OMGraphic; import com.bbn.openmap.omGraphics.event.MapMouseInterpreter; import com.bbn.openmap.tools.drawing.DrawingTool; import com.bbn.openmap.util.ComponentFactory; import com.bbn.openmap.util.Debug; import com.bbn.openmap.util.PropUtils; /** * The EditorLayer is a layer that provides a specific set of tools to modify a * set of OMGraphics that represent specific types of objects. It has an * EditorTool that controls what the interface looks like, and controls * reception of the mouse events to direct their interpretation usefully. The * EditorLayer can use the following property: * * <pre> * * * # could be com.bbn.openmap.layer.editor.DrawingEditorTool, for instance * editorLayer.editor=EditorTool class * * * </pre> */ public class EditorLayer extends DrawingToolLayer implements Tool { /** * The EditorTool controls the interface, and how OMGraphics are managed. */ protected EditorTool editorTool = null; /** * The mouse mode used to direct mouse events to the editor. */ protected EditorLayerMouseMode elmm = null; /** * The property to use of the EditorLayer doesn't really know what * EditorTool it will have. This property is used in setProperties if the * EditorTool isn't already set. If you extend the EditorLayer and * specifically set the EditorTool in the constructor, this property will be * ignored. */ public final static String EditorToolProperty = "editor"; protected int orientation = SwingConstants.HORIZONTAL; public EditorLayer() { super(); } public void setProperties(String prefix, Properties props) { super.setProperties(prefix, props); if (editorTool == null) { String realPrefix = PropUtils.getScopedPropertyPrefix(prefix); String editorClassName = props.getProperty(realPrefix + EditorToolProperty); if (editorClassName != null) { // Try to create with this layer as an argument. Object[] objArgs = { this }; editorTool = (EditorTool) ComponentFactory.create(editorClassName, objArgs, prefix, props); if (editorTool == null) { // OK, try to create with an empty constructor. editorTool = (EditorTool) ComponentFactory.create(editorClassName, prefix, props); } if (editorTool == null) { String additionalInfo = "."; if (editorClassName != null) { additionalInfo = ", although an editor tool class (" + editorClassName + ") was defined."; } Debug.error(getName() + " doesn't have a EditorTool defined" + additionalInfo); } } } } /** * Get and/or create the EditorLayerMouseMode that can be used specifically * for this layer, used to capture the MapBean's MouseEvents when an * EditorTool is invoked. The EditorLayerMouseMode is invisible, meaning it * won't show up in standard OpenMap GUI widgets as a viable MouseMode. It * is expected that the EditorTool will compensate for displaying what is * going on. * <P> * * If the EditorLayerMouseMode isn't set programmatically, this method will * create one with this layer's name as the mouse mode ID. If the layer's * name hasn't been set, a temporary mouse mode will be returned, but with a * somewhat random name that may not really work as expected. Once the * layer's name gets set, however, a good, usable mouse mode will get picked * up and used. */ public EditorLayerMouseMode getMouseMode() { if (elmm == null) { String ln = getName(); if (ln == null) { // Try something unique, but don't make it permanent. // This will keep the layer cookin' along, but force a // new mouse mode until the name gets set. ln = this.getClass().getName() + System.currentTimeMillis(); return new EditorLayerMouseMode(ln.intern(), true); } elmm = new EditorLayerMouseMode(ln.intern(), true); } return elmm; } /** * Need to do this so the EditorLayerMouseMode will be recreated with the * proper identification if the name of the layer changes. */ public void setName(String name) { super.setName(name); elmm = null; /* * Need to call this in case the layer name gets set after the mouse * mode ids are set, so the new elmm id is included in this list. This * list might get populated with unused strings, but that should be OK, * as long as the one we need is on the list. */ setMouseModeIDsForEvents(getMouseModeIDsForEvents()); } /** * DrawingToolRequestor method. It's actually pretty important to call * EditorTool.drawingComplete() from here, too, if you create a subclass to * EditorLayer. The EditorTool needs to know this to reset the drawing tool * mouse mode, to get ready for another new OMGraphic if necessary. */ public void drawingComplete(OMGraphic omg, OMAction action) { super.drawingComplete(omg, action); if (editorTool != null) { editorTool.drawingComplete(omg, action); } } /** * Called by findAndInit(Iterator) so subclasses can find objects, too. */ public void findAndInit(Object someObj) { // We don't want the EditorLayer to find the DrawingTool // in the MapHandler. The EditorTool should set its own. if (!(someObj instanceof DrawingTool)) { super.findAndInit(someObj); } if (editorTool != null) { editorTool.findAndInit(someObj); } if (someObj instanceof InformationDelegator || someObj instanceof SelectMouseMode) { getMouseMode().findAndInit(someObj); } } public void findAndUndo(Object someObj) { super.findAndUndo(someObj); if (editorTool != null) { editorTool.findAndUndo(someObj); } if (someObj instanceof InformationDelegator || someObj instanceof SelectMouseMode) { getMouseMode().findAndUndo(someObj); } } public void dispose() { if (editorTool != null) { editorTool.dispose(); } super.dispose(); } public void setMouseModeIDsForEvents(String[] modes) { // creates the MouseMode if needed EditorLayerMouseMode elmm = getMouseMode(); String[] newModes = new String[modes.length + 1]; System.arraycopy(modes, 0, newModes, 0, modes.length); newModes[modes.length] = elmm.getID(); super.setMouseModeIDsForEvents(newModes); } public String[] getMouseModeIDsForEvents() { String[] modes = super.getMouseModeIDsForEvents(); if (modes == null) { // Set the internal mouse mode as valid, since it hasn't // been set yet. setMouseModeIDsForEvents(new String[0]); // Since it's set now, return it. return super.getMouseModeIDsForEvents(); } else { return modes; } } /** * Get the interpreter used to field and interpret MouseEvents, thereby * calling GestureResponsePolicy methods on this layer. It returns whatever * has been set as the interpreter, which could be null. */ public MapMouseInterpreter getMouseEventInterpreter() { return mouseEventInterpreter; } public EditorTool getEditorTool() { return editorTool; } public void setEditorTool(EditorTool editorTool) { this.editorTool = editorTool; } /** * Part of a layer hack to notify the component listener when the component * is hidden. These components don't receive the ComponentHidden * notification. Remove when it works. */ public void setVisible(boolean show) { if (editorTool != null) { editorTool.setVisible(show); } super.setVisible(show); } // ///////////////////////////// // Tool interface methods // ///////////////////////////// /** * The tool's interface. This is added to the tool bar. * * @return String The key for this tool. */ public Container getFace() { if (editorTool != null) { return editorTool.getFace(); } else { return new JPanel(); } } /** * The retrieval key for this tool. We use the property prefix for the key. * If the property prefix is not set then the name is used, which may not be * that unique. * * @return String The key for this tool. */ public String getKey() { String tmpKey = getPropertyPrefix(); if (tmpKey == null) { tmpKey = getName(); if (tmpKey == null) { tmpKey = getClass().getName(); } } return tmpKey; } /** * Set the retrieval key for this tool. This call sets the key used for the * Tool interface method, which is generally the property prefix used for * this layer. Do not use this lightly, since the ToolPanel may be expecting * to find a key that is reflected in the openmap.properties file. * * @param aKey The key for this tool. */ public void setKey(String aKey) { setPropertyPrefix(aKey); } public int getOrientation() { return orientation; } public void setOrientation(int orientation) { this.orientation = orientation; } /** * A hook to get a handle on a new OMGraphic that is being created for * editing. The DrawingEditorTool calls this. NOOP here, but if you need a * handle to the new OMGraphic just as it's being created, here it is. * * @param newOMG */ protected void creatingOMGraphic(OMGraphic newOMG) { } }