English

How To: Create Legends for dynamic layers in MapObjects-Java

Summary

When using MapObjects-Java Standard Edition (MOJ), graphical features can be created and displayed dynamically in a Map component, such as an acetate layer. To manage the display of a dynamic layer, a developer may want to create a Legend to represent the layer in a TOC. Techniques for creating a dynamic layer's legend vary in difficulty and functionality, depending on the method used to create the layer. Three primary techniques are available:

  • Use a FeatureLayer and let MapObjects-Java manage the Legend
  • Add a GraphicsLayer, such as a LayerEvent
  • Reconstruct the TOC

Procedure

  • Use a FeatureLayer and let MapObjects-Java manage the Legend

    This technique is the easiest method for creating a dynamic layer's Legend.

    When creating a dynamic layer as a FeatureLayer, (for example: BaseFeatureLayer), and adding it to a Map component, a new Legend will automatically be added the Map's TOC. A dynamic FeatureLayer will have the same properties as a FeatureLayer using data located on disk, such as shapefile or ArcSDE layer. Legends can also be managed in the same fashion.
     
  • Add a GraphicsLayer using a LayerEvent

    When creating a dynamic layer as a GraphicsLayer, it is usually associated with an AcetateLayer object before being added to a Map. By default, no legend is created for a GraphicsLayer. To add a legend for a GraphicsLayer, a new LayerEvent can be created and processed by a Map component. A LayerEvent informs the Map component's LayerListener that a layer was added, moved, or deleted from a Map. A legend for a GraphicsLayer can be added to a TOC component using the following code:
    MyGraphicsLayer gLayer = new MyGraphicsLayer();
    gLayer.setName("My Graphics Layer");
    AcetateLayer acetateLayer = new AcetateLayer(gLayer);
    aMap.add(acetateLayer);
    LayerEvent event = new LayerEvent(acetateLayer.getLayer(), LayerEvent.ADD);
    aMap.getLayerset().processLayerEvent(event);
    The following image provides an example of a MapObjects-Java application interface after a GraphicsLayer has been added using a LayerEvent:
[O-Image] graphics_layer_example
The legend will not contain a symbol swatch and a Map must have a registered TOC before the LayerEvent can be processed. In addition, a TocListener must be added to the TOC to listen for events on the dynamic layer legend; for example: set layer visibility depending on the state of the check box. This technique can be used if the legend does not need a symbol swatch or the dynamic layer is a GraphicsLayer and the developer does not want to create a TOC from scratch (see next method).
  • Reconstruct a TOC

    If using a dynamic layer created from an AcetateLayer, or the legend for a GraphicsLayer needs to display a symbol swatch, the TOC component must be reconstructed to add a legend entry. The TOC is essentially a JScrollPane containing a parent JPanel consisting of one or more child JPanels (Legends). The TOC and its components, such as Legends and Listeners, can be created from scratch or the existing TOC component can be included within the new parent JPanel. To include the existing TOC components, do the following; the sample code is included:
  1. Retrieve the current TOC component.
Component component = aToc.getViewport().getView();
  1. Create a new 'parent' JPanel. This JPanel will contain multiple 'child' JPanels as dynamic layer legends, as well as existing TOC Legends. Ultimately, the content of the existing TOC component will be set to the new parent JPanel (Step 4).
JPanel jpp = new JPanel();
jpp.setLayout(new BorderLayout());
jpp.add(component,BorderLayout.NORTH);
  1. Create a new JPanel to represent each layer, including the dynamic layer. As the developer, you can choose the type of checkbox, title, and symbol used. If an AcetateLayer is used, its visibility is set by adding and removing it from the Map component. The visibility of a GraphicsLayer can be set using the setVisible() method. Add this JPanel as a child to the JPanel created in the previous step. Also, be sure to add the appropriate listeners as needed, such as adding an ActionListener to determine if the checkbox is checked. The following code illustrates creating a JPanel for an AcetateLayer:
Sample code:
import java.awt.*;
        import java.awt.event.*;
        import javax.swing.*;
	
        public class Dynamic_Layer extends JPanel {
	
	  //CustomMouseAdapter myMouseAdapter = new CustomMouseAdapter();
	  com.esri.mo.ui.bean.AcetateLayer m_acetate;
	  com.esri.mo.ui.bean.Map m_map;
	
	  public Dynamic_Layer(com.esri.mo.ui.bean.AcetateLayer layer, com.esri.mo.ui.bean.Map map) {
	
	    m_acetate = layer;
	    m_map = map;
	
	    // Set the layout manager for the JPanel.   
	    FlowLayout fl = new FlowLayout();
	    this.setLayout(fl);
	    fl.setAlignment(FlowLayout.LEFT);
	    fl.setHgap(3);
	    fl.setVgap(1); 
	
	    //Add a check box with an ActionListener to set the visibility of the AcetateLayer
	    final JCheckBox jcb = new JCheckBox();
	    jcb.setSelected(true);
	
	    jcb.addActionListener(new ActionListener(){
		public void actionPerformed(ActionEvent ae){
	         if (jcb.isSelected()) {
	          m_map.add(m_acetate);
	          m_map.redraw();
	        } else {
          	  m_map.remove((Component) m_acetate);	          
		  // After removing the AcetateLayer, the Map needs to be repainted
		  m_map.repaint();
	          m_map.redraw();
	        }
	
	      }
	
	    });
	
	    // Construct the legend label
	    JTextField jtf = new JTextField("MyLayer");
	    jtf.setEditable(false);
	    
	    // Add the components, set the color and size of the legend
	    this.add(jcb);
	    this.add(jtf);
	    //setBackground(Color.lightGray);
	    setPreferredSize(new Dimension(140, 50));
	    
	    /* Add a MouseListener to listen for mouse interaction with the legend JPanel.  
	    *  For example, selecting a legend to make it active.
	     */
	   // addMouseListener(myMouseAdapter);
	
	    }
	
	    public void paintComponent(Graphics g){
	        super.paintComponent(g);
	        Graphics2D g2d = (Graphics2D) g;
	        
	        // Add the symbol swatch to the legend component
	        java.awt.geom.Area e = new java.awt.geom.Area(new java.awt.geom.Rectangle2D.Double(17,25,15,15));
	        g2d.setColor(new Color(0,20,250));
	        g2d.fill(e);
	        g2d.setColor(new Color(0, 0, 0));
	        g2d.draw(e);
	
		}
	}
 
Once the new JPanel for the dynamic layer is created, add it to the parent JPanel, then associate the parent JPanel with the existing Toc.
Dynamic_Layer dyn_layer = new Dynamic_Layer(myAcetateLayer, map1);
jpp.add(dyn_layer, BorderLayout.CENTER);
aToc.setViewportView(jpp);
This technique can be used if an AcetateLayer needs a legend entry or the content of a TOC needs to be completely customized.

Related Information