Dynamic layer info

Download Sample Viewer

Description

This application shows how to retrieve LayerInfo from an online dynamic layer (ArcGISDynamicMapServiceLayer) and a local dynamic layer (ArcGISLocalDynamicMapServiceLayer) using the getSubLayer method which takes either a layer name or layer id. The LayerInfo thus returned provides programmatic access to information about the sublayers of the dynamic layer, such as geometry type, name, scale limits, and so on. If the dynamic workspace functionality is being used, the LayerInfo will have its hasDynamicLayerInfo property true and will show information for the dynamically added layer (not shown in this application).

Code snippet


  private LayerInfo getLayerInfo(String layerName) {
      LayerInfo layerInfo = null;
      if (layerName != null) {
        if (currentLayer instanceof ArcGISDynamicMapServiceLayer) {
          layerInfo = ((ArcGISDynamicMapServiceLayer) currentLayer).getSubLayer(layerName);
        }
      }
      return layerInfo;
    }
  

Sample Code

/* Copyright 2014 Esri

All rights reserved under the copyright laws of the United States
and applicable international laws, treaties, and conventions.

You may freely redistribute and use this sample code, with or
without modification, provided you include the original copyright
notice and use restrictions.

See the use restrictions.*/
package com.esri.client.samples.dynamiclayers;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

import com.esri.client.local.ArcGISLocalDynamicMapServiceLayer;
import com.esri.client.local.ArcGISLocalTiledLayer;
import com.esri.toolkit.utilities.BrowserLauncher;
import com.esri.core.geometry.Envelope;
import com.esri.map.ArcGISDynamicMapServiceLayer;
import com.esri.map.JMap;
import com.esri.map.Layer;
import com.esri.map.Layer.LayerStatus;
import com.esri.map.LayerInfo;
import com.esri.map.LayerInitializeCompleteEvent;
import com.esri.map.LayerInitializeCompleteListener;
import com.esri.map.LayerList;
import com.esri.runtime.ArcGISRuntime;

/***
 * This application shows how to retrieve LayerInfo from an online dynamic layer 
 * (ArcGISDynamicMapServiceLayer) and a local dynamic layer (ArcGISLocalDynamicMapServiceLayer) 
 * using the <code>getSubLayer</code> method which takes either a layer name or 
 * layer id.
 * <p>
 * The LayerInfo thus returned provides programmatic access to information about 
 * the sublayers of the dynamic layer, such as geometry type, name, scale limits, 
 * and so on. If the dynamic workspace functionality is being used, the LayerInfo 
 * will have its hasDynamicLayerInfo property true and will show information for 
 * the dynamically added layer (not shown in this application).
 *
 */
public class LayerInfoApp {

  private JTextArea layerInfoTextArea;
  private JComboBox<ArcGISDynamicMapServiceLayer> layerComboBox;
  private JComboBox<String> sublayerComboBox;
  private UrlLabel urlLabel;
  private JProgressBar progressBar;
  private JMap map;
  private Layer currentLayer;
  private JScrollPane scrollPane;
  private static String FSP = System.getProperty("file.separator");

  // ------------------------------------------------------------------------
  // Default constructor
  // ------------------------------------------------------------------------
  public LayerInfoApp() { }

  // ------------------------------------------------------------------------
  // Core functionality
  // ------------------------------------------------------------------------

  /**
   * Uses the dynamic layer's getSubLayer method to obtain the layer info for a 
   * dynamic layer's sublayer by layer name. Can also be done by layer id.
   * 
   * @param layerName the name of the sub layer we want layer info for
   * @return the layer info
   */
  private LayerInfo getLayerInfo(String layerName) {
    LayerInfo layerInfo = null;
    if (layerName != null) {
      if (currentLayer instanceof ArcGISDynamicMapServiceLayer) {
        layerInfo = ((ArcGISDynamicMapServiceLayer) currentLayer).getSubLayer(layerName);
      }
    }
    return layerInfo;
  }

  /**
   * Displays the layer info to a text area in the application.
   * 
   * @param layerInfo
   */
  private void displayLayerInfo(final LayerInfo layerInfo) {

    SwingUtilities.invokeLater(new Runnable() {

      @Override
      public void run() {
        // display clickable help URL
        urlLabel.setText(layerInfo.getURL());
        urlLabel.setUrl(layerInfo.getURL());

        // display some of the layer info in our UI
        layerInfoTextArea.setText(" Name: " + layerInfo.getName() + "\n");
        layerInfoTextArea.append(" Display name: " + layerInfo.getDisplayName() + "\n");
        layerInfoTextArea.append(" Geometry type: " + layerInfo.getGeometryType() + "\n");
        layerInfoTextArea.append(" Default visibility: " + layerInfo.getDefaultVisibility() + "\n");
        layerInfoTextArea.append(" Display field: " + layerInfo.getDisplayField() + "\n");
        layerInfoTextArea.append(" Dynamic layer info present: " + layerInfo.hasDynamicLayerInfo() + "\n");
        layerInfoTextArea.append(" Max scale: " + layerInfo.getMaxScale() + "\n");
        layerInfoTextArea.append(" Min scale: " + layerInfo.getMinScale() + "\n");
        // etc.
        SwingUtilities.invokeLater(new Runnable() {
          @Override
          public void run() {
            scrollPane.getVerticalScrollBar().setValue(0);
          }
        });
      }
    });
  }
  
  /**
   * Update the combo box with the sublayers (by name) of the selected dynamic layer.
   */
  private void updateSubLayers() {
    sublayerComboBox.removeAllItems();
    // get sub layers of chosen layer and add to comboBox
    if (currentLayer instanceof ArcGISDynamicMapServiceLayer) {
      for (String subLayer : ((ArcGISDynamicMapServiceLayer) currentLayer).getLayers().keySet()) {
        sublayerComboBox.addItem(subLayer);
      }
    }
  }

  // ------------------------------------------------------------------------
  // Public methods
  // ------------------------------------------------------------------------
  /**
   * Creates and displays the UI, including the map, for this application.
   * @return the UI for this sample.
   */
  public JComponent createUI() {

    final JPanel contentPane = new JPanel();
    contentPane.setLayout(new BorderLayout(0, 0));

    // progress bar
    progressBar = new JProgressBar();
    progressBar.setSize(200, 20);
    contentPane.addComponentListener(new ComponentAdapter() {
      @Override
      public void componentResized(ComponentEvent e) {
        progressBar.setLocation(
            contentPane.getWidth()/2 - progressBar.getWidth()/2,
            contentPane.getHeight() - progressBar.getHeight() - 20);
      }
    });
    progressBar.setStringPainted(true);
    progressBar.setIndeterminate(true);
    progressBar.setVisible(false);

    JPanel taskPanel = createLayerInfoPanel();
    map = createMap();

    contentPane.add(taskPanel, BorderLayout.NORTH);
    contentPane.add(map, BorderLayout.CENTER);

    return contentPane;
  }

  // ------------------------------------------------------------------------
  // Static methods
  // ------------------------------------------------------------------------
  /**
   * Starting point of this application.
   * @param args arguments to this application.
   */
  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        try {
          // instance of this application
          LayerInfoApp liApp = new LayerInfoApp();

          // create the UI, including the map, for the application.
          JFrame appWindow = liApp.createWindow();
          appWindow.add(liApp.createUI());
          appWindow.setVisible(true);
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    });
  }

  // ------------------------------------------------------------------------
  // Private methods
  // ------------------------------------------------------------------------
  /**
   * Creates the map.
   * @return a map.
   */
  private JMap createMap() {

    final JMap jMap = new JMap();
    jMap.setExtent(new Envelope(-15000000, 2000000, -7000000, 8000000));

    // setting a tiled layer as basemap
    ArcGISLocalTiledLayer tiledLayer = new ArcGISLocalTiledLayer(
        getPathSampleData() + "tpks/Topographic.tpk");
    final LayerList layers = jMap.getLayers();
    layers.add(tiledLayer);

    final ArcGISDynamicMapServiceLayer onlineDynamicLayer = new ArcGISDynamicMapServiceLayer(
        "http://sampleserver6.arcgisonline.com/arcgis/rest/services/WorldTimeZones/MapServer");
    layers.add(onlineDynamicLayer);
    onlineDynamicLayer.addLayerInitializeCompleteListener(new LayerInitializeCompleteListener() {

      @Override
      public void layerInitializeComplete(LayerInitializeCompleteEvent e) {
        if (onlineDynamicLayer.getStatus() == LayerStatus.INITIALIZED) {
          SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
              layerComboBox.addItem(onlineDynamicLayer);
            }
          });
        }
      }
    });

    updateProgresBarUI("Starting local dynamic map service...", true);
    // create the dynamic layer
    final ArcGISLocalDynamicMapServiceLayer localDynamicLayer = new ArcGISLocalDynamicMapServiceLayer(
        getPathSampleData() + "mpks/USCitiesStates.mpk");
    localDynamicLayer.addLayerInitializeCompleteListener(new LayerInitializeCompleteListener() {
      @Override
      public void layerInitializeComplete(LayerInitializeCompleteEvent event) {
        updateProgresBarUI(null, false);
        SwingUtilities.invokeLater(new Runnable() {
          @Override
          public void run() {
            layerComboBox.addItem(localDynamicLayer);
          }
        });
      }
    });
    layers.add(localDynamicLayer);

    return jMap;
  }

  private JPanel createLayerInfoPanel() {

    JPanel panel = new JPanel();
    panel.setLayout(new BorderLayout());

    JPanel panel1 = new JPanel();
    panel1.setLayout(new BorderLayout());

    layerComboBox = new JComboBox<>();
    layerComboBox.setMinimumSize(new Dimension(300, 40));
    layerComboBox.setAlignmentX(Component.LEFT_ALIGNMENT);
    layerComboBox.addActionListener(new ActionListener() {

      @Override
      public void actionPerformed(ActionEvent e) {
        currentLayer = (Layer) layerComboBox.getSelectedItem();
        if (currentLayer != null) {
          updateSubLayers();
        }
      }
    });

    panel1.add(layerComboBox, BorderLayout.CENTER);
    panel1.setBorder(BorderFactory.createTitledBorder("Choose a dynamic layer below to see its sublayers:"));

    JPanel panel2 = new JPanel();
    panel2.setMinimumSize(new Dimension(550, 85));
    panel2.setLayout(new BorderLayout(0, 5));
    panel2.setAlignmentX(Component.LEFT_ALIGNMENT);

    sublayerComboBox = new JComboBox<>();
    sublayerComboBox.setMinimumSize(new Dimension(300, 40));
    sublayerComboBox.setAlignmentX(Component.LEFT_ALIGNMENT);
    sublayerComboBox.addActionListener(new ActionListener() {

      @Override
      public void actionPerformed(ActionEvent e) {
        LayerInfo li = getLayerInfo((String) sublayerComboBox.getSelectedItem());
        if (li != null) {
          displayLayerInfo(li);
        }
      }
    });

    JPanel urlPanel = new JPanel();
    urlPanel.setLayout(new BoxLayout(urlPanel, BoxLayout.X_AXIS));
    urlPanel.add(new JLabel("Layer REST endpoint:   "));
    urlLabel = new UrlLabel("","");
    urlPanel.add(urlLabel);

    layerInfoTextArea = new JTextArea();
    layerInfoTextArea.setEditable(false);
    layerInfoTextArea.setRows(6);

    scrollPane = new JScrollPane(layerInfoTextArea);

    panel2.add(sublayerComboBox, BorderLayout.NORTH);
    panel2.add(urlPanel, BorderLayout.CENTER);
    panel2.add(scrollPane, BorderLayout.SOUTH);
    panel2.setBorder(BorderFactory.createTitledBorder("Choose a sub layer below to see its layer info:"));

    panel.add(panel1, BorderLayout.NORTH);
    panel.add(panel2, BorderLayout.CENTER);

    return panel;
  }

  /**
   * Creates a window.
   * @return a window.
   */
  private JFrame createWindow() {
    JFrame window = new JFrame("Layer Info application");
    window.setBounds(100, 100, 1000, 700);
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    window.addWindowListener(new WindowAdapter() {
      @Override
      public void windowClosing(WindowEvent windowEvent) {
        super.windowClosing(windowEvent);
        map.dispose();
      }
    });
    return window;
  }

  private String getPathSampleData() {
    String dataPath = null;
    String javaPath = ArcGISRuntime.getInstallDirectory();
    if (javaPath != null) {
      if (!(javaPath.endsWith("/") || javaPath.endsWith("\\"))){
        javaPath += FSP;
      }
      dataPath = javaPath + "sdk" + FSP + "samples" + FSP + "data" + FSP;
    }
    File dataFile = new File(dataPath);
    if (!dataFile.exists()) { 
      dataPath = ".." + FSP + "data" + FSP;
    }
    return dataPath;
  }

  /**
   * Updates progress bar UI from Swing's Event Dispatch Thread.
   * @param str string to be set.
   * @param visible flag to indicate visibility of the progress bar.
   */
  private void updateProgresBarUI(final String str, final boolean visible) {
    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        if (str != null) {
          progressBar.setString(str);
        }
        progressBar.setVisible(visible);
      }
    }); 
  }

  class UrlLabel extends JLabel {

    private static final long serialVersionUID = 1L;
    private String url;
    private Color selected_color = new Color(160,160,160);
    private Color link_color = Color.BLUE;

    UrlLabel(String labelText, String url) {
      super(labelText);
      this.url = url;
      setForeground(link_color);
      addMouseListener(new UrlMouseListener());
    }

    public String getUrl() {
      return url;
    }

    public void setUrl(String url) {
      this.url = url;
    }

    class UrlMouseListener extends MouseAdapter {

      @Override
      public void mouseEntered(MouseEvent event) {
        handleMouseEntered();
      }

      @Override
      public void mouseExited(MouseEvent event) {
        handleMouseExited();
      }

      @Override
      public void mouseClicked(MouseEvent event) {
        handleMouseClicked();
      }
    }

    void handleMouseEntered() {
      setForeground(selected_color);
      setCursor(new Cursor(Cursor.HAND_CURSOR));
    }

    void handleMouseExited() {
      setForeground(link_color);
      setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
    }

    void handleMouseClicked() {
      BrowserLauncher.openURL(url);
    }
  }
}
Feedback on this topic?