Simple renderer

Download Sample Viewer

Description

This sample demonstrates that the client can override the default renderers specified by a dynamic map service layer. The dynamic layer needs to be enabled for dynamic rendering by calling setEnableDynamicLayers(true) on the layer before it is added to the map. The new renderers are created client-side but the information is applied at the server level when rendering the map image.

Code snippet


    // Create new drawing info from our renderer, with set transparency
    DrawingInfo drawingInfo = new DrawingInfo(renderer, TRANSPARENCY);
    
    // Get the layerInfo from the dynamic layer and set the drawing info
    DynamicLayerInfoCollection layerInfos = dynamicLayer.getDynamicLayerInfos();
    DynamicLayerInfo layerInfo = layerInfos.get(layerId);
    layerInfo.setDrawingInfo(drawingInfo);

    // Refresh the layer
    dynamicLayer.refresh();
  

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.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.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.util.Random;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;

import com.esri.client.local.ArcGISLocalDynamicMapServiceLayer;
import com.esri.client.local.ArcGISLocalTiledLayer;
import com.esri.core.geometry.Envelope;
import com.esri.core.map.DrawingInfo;
import com.esri.core.map.DynamicLayerInfo;
import com.esri.core.map.DynamicLayerInfoCollection;
import com.esri.core.renderer.Renderer;
import com.esri.core.renderer.SimpleRenderer;
import com.esri.core.symbol.SimpleFillSymbol;
import com.esri.core.symbol.SimpleLineSymbol;
import com.esri.core.symbol.SimpleMarkerSymbol;
import com.esri.core.symbol.SimpleMarkerSymbol.Style;
import com.esri.map.JMap;
import com.esri.map.LayerInitializeCompleteEvent;
import com.esri.map.LayerInitializeCompleteListener;
import com.esri.map.LayerList;
import com.esri.runtime.ArcGISRuntime;

/***
 * This sample demonstrates that the client can override the default renderers
 * specified by a dynamic map service layer. The dynamic layer needs to be enabled
 * for dynamic rendering by calling setEnableDynamicLayers(true) on the layer
 * before it is added to the map. The new renderers are created client-side but
 * the information is applied at the server level when rendering the map image.
 */
public class LocalDynamicSimpleRenderer {

  private JComponent contentPane;
  private JMap map;
  private JProgressBar progressBar;
  private JButton citiesButton;
  private JButton citiesDefaultButton;
  private JButton highwaysButton;
  private JButton highwaysDefaultButton;
  private JButton statesButton;
  private JButton statesDefaultButton;
  Random random;

  // constants
  private static final int TRANSPARENCY = 30; // 0 is opaque, 100 is transparent
  private static final int BUTTON_WIDTH = 220;

  // resources
  ArcGISLocalDynamicMapServiceLayer dynamicLayer;

  // ------------------------------------------------------------------------
  // Constructor
  // ------------------------------------------------------------------------
  /**
   * Creates an instance of this sample.
   */
  public LocalDynamicSimpleRenderer() {
  }

  // ------------------------------------------------------------------------
  // 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
          LocalDynamicSimpleRenderer localDynamicFeatureLayerApp = new LocalDynamicSimpleRenderer();

          // create the UI, including the map, for the application.
          JFrame appWindow = localDynamicFeatureLayerApp.createWindow();
          appWindow.add(localDynamicFeatureLayerApp.createUI());
          appWindow.setVisible(true);
        } catch (Exception e) {
          // on any error, display the stack trace.
          e.printStackTrace();
        }
      }
    });
  }

  // ------------------------------------------------------------------------
  // Core functionality: how to change rendering options for Dynamic Layers
  // ------------------------------------------------------------------------
  /**
   * Sets the drawing info of sublayer number 'layerId' of a dynamic layer
   * with the given renderer
   * @param renderer
   * @param layerId
   */
  private void render(Renderer renderer, int layerId) {
    // Create new drawing info from our renderer, with set transparency
    DrawingInfo drawingInfo = new DrawingInfo(renderer, TRANSPARENCY);

    // Get the layerInfo from the dynamic layer and set the drawing info
    DynamicLayerInfoCollection layerInfos = dynamicLayer.getDynamicLayerInfos();
    DynamicLayerInfo layerInfo = layerInfos.get(layerId);
    layerInfo.setDrawingInfo(drawingInfo);

    // Refresh the layer
    dynamicLayer.refresh();
  }

  /**
   * Resets the default rendering options of sublayer number 'layerId' of
   * the dynamic layer
   */
  private void resetDefault(int layerId) {
    DynamicLayerInfo layerInfo = dynamicLayer.getDynamicLayerInfos().get(layerId);
    layerInfo.resetToDefault();
    dynamicLayer.refresh();
  }

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

    random = new Random();

    contentPane = createContentPane();

    // button panel
    JPanel buttonPanel = createButtonPanel();
    contentPane.add(buttonPanel);

    // progress bar
    progressBar = createProgressBar(contentPane);
    contentPane.add(progressBar);

    // create map
    map = createMap();
    contentPane.add(map);

    return contentPane;
  }

  // ------------------------------------------------------------------------
  // 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);

    updateProgresBarUI("Starting local dynamic map service...", true);

    // create the dynamic layer
    dynamicLayer = new ArcGISLocalDynamicMapServiceLayer(
        getPathSampleData() + "mpks/USCitiesStates.mpk");
    // Allow the client to override the default rendering options by setting the enabling
    // dynamic layers to be true. This must be done before adding the layer to the map.
    dynamicLayer.setEnableDynamicLayers(true);

    dynamicLayer
        .addLayerInitializeCompleteListener(new LayerInitializeCompleteListener() {
          @Override
          public void layerInitializeComplete(LayerInitializeCompleteEvent arg0) {
            synchronized (progressBar) {
              if (arg0.getID() == LayerInitializeCompleteEvent.LOCALLAYERCREATE_ERROR) {
                String errMsg = "Failed to initialize due to "
                    + dynamicLayer.getInitializationError();
                JOptionPane.showMessageDialog(jMap, wrap(errMsg), "",
                    JOptionPane.ERROR_MESSAGE);
              }
              updateProgresBarUI(null, false);
            }

            // activate buttons once the dynamic layer is done initializing
            citiesButton.setEnabled(true);
            citiesDefaultButton.setEnabled(true);
            highwaysButton.setEnabled(true);
            highwaysDefaultButton.setEnabled(true);
            statesButton.setEnabled(true);
            statesDefaultButton.setEnabled(true);
          }

        });

    // then, add the layer to the map
    layers.add(dynamicLayer);

    return jMap;
  }

  private JPanel createButtonPanel() {
    JPanel panel = new JPanel();
    panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
    panel.setSize(BUTTON_WIDTH + 10, 205);
    panel.setLocation(10, 10);

    // create the buttons
    citiesButton = createCitiesButton();
    citiesDefaultButton = createCitiesDefaultButton();
    highwaysButton = createHighwaysButton();
    highwaysDefaultButton = createHighwaysDefaultButton();
    statesButton = createStatesButton();
    statesDefaultButton = createStatesDefaultButton();

    // layout all the components together into a panel
    panel.setBackground(new Color(0, 0, 0, 120));
    panel.add(citiesButton);
    panel.add(Box.createRigidArea(new Dimension(0,5)));
    panel.add(citiesDefaultButton);
    panel.add(Box.createRigidArea(new Dimension(0,15)));
    panel.add(highwaysButton);
    panel.add(Box.createRigidArea(new Dimension(0,5)));
    panel.add(highwaysDefaultButton);
    panel.add(Box.createRigidArea(new Dimension(0,15)));
    panel.add(statesButton);
    panel.add(Box.createRigidArea(new Dimension(0,5)));
    panel.add(statesDefaultButton);
    panel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
    return panel;
  }

  private JButton createCitiesButton() {
    JButton button = new JButton("Change Cities Renderer");
    button.setMaximumSize(new Dimension(BUTTON_WIDTH, 25));
    button.setMinimumSize(new Dimension(BUTTON_WIDTH, 25));
    button.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent arg0) {
        render(new SimpleRenderer(new SimpleMarkerSymbol(getRandomColor(), 8, Style.CIRCLE)), 0);
      }
    });
    button.setEnabled(false);
    return button;
  }

  private JButton createCitiesDefaultButton() {
    JButton button = new JButton("Reset Cities Renderer");
    button.setMaximumSize(new Dimension(BUTTON_WIDTH, 25));
    button.setMinimumSize(new Dimension(BUTTON_WIDTH, 25));
    button.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent arg0) {
        resetDefault(0);
      }
    });
    button.setEnabled(false);
    return button;
  }

  private JButton createHighwaysButton() {
    JButton button = new JButton("Change Highways Renderer");
    button.setMaximumSize(new Dimension(BUTTON_WIDTH, 25));
    button.setMinimumSize(new Dimension(BUTTON_WIDTH, 25));
    button.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent arg0) {
        render(new SimpleRenderer(new SimpleLineSymbol(getRandomColor(), getRandomThickness())), 1);
      }
    });
    button.setEnabled(false);
    return button;
  }

  private JButton createHighwaysDefaultButton() {
    JButton button = new JButton("Reset Highways Renderer");
    button.setMaximumSize(new Dimension(BUTTON_WIDTH, 25));
    button.setMinimumSize(new Dimension(BUTTON_WIDTH, 25));
    button.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent arg0) {
        resetDefault(1);
      }
    });
    button.setEnabled(false);
    return button;
  }

  private JButton createStatesButton() {
    JButton button = new JButton("Change States Renderer");
    button.setMaximumSize(new Dimension(BUTTON_WIDTH, 25));
    button.setMinimumSize(new Dimension(BUTTON_WIDTH, 25));
    button.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent arg0) {
        render(new SimpleRenderer(new SimpleFillSymbol(getRandomColor(),
            new SimpleLineSymbol(getRandomColor(), getRandomThickness()))), 2);
      }
    });
    button.setEnabled(false);
    return button;
  }

  private JButton createStatesDefaultButton() {
    JButton button = new JButton("Reset States Renderer");
    button.setMaximumSize(new Dimension(BUTTON_WIDTH, 25));
    button.setMinimumSize(new Dimension(BUTTON_WIDTH, 25));
    button.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent arg0) {
        resetDefault(2);
      }
    });
    button.setEnabled(false);
    return button;
  }

  private Color getRandomColor(){
    return new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256));
  }

  /**
   * Generate a random line thickness
   * @return an int from [1,3]
   */
  private int getRandomThickness(){
    return random.nextInt(3) + 1;
  }

  /**
   * Creates a content pane.
   * @return a content pane.
   */
  private static JLayeredPane createContentPane() {
    JLayeredPane contentPane = new JLayeredPane();
    contentPane.setBounds(100, 100, 1000, 700);
    contentPane.setLayout(new BorderLayout(0, 0));
    contentPane.setVisible(true);
    return contentPane;
  }

  /**
   * Creates a progress bar.
   * @param parent progress bar's parent. The horizontal axis of the progress bar will be
   * center-aligned to the parent.
   * @return a progress bar.
   */
  private static JProgressBar createProgressBar(final JComponent parent) {
    final JProgressBar progressBar = new JProgressBar();
    progressBar.setSize(280, 20);
    parent.addComponentListener(new ComponentAdapter() {
      @Override
      public void componentResized(ComponentEvent e) {
        progressBar.setLocation(
            parent.getWidth()/2 - progressBar.getWidth()/2,
            parent.getHeight() - progressBar.getHeight() - 20);
      }
    });
    progressBar.setStringPainted(true);
    progressBar.setIndeterminate(true);
    return progressBar;
  }

  /**
   * Updates progress bar UI from the 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);
      }
    }); 
  }

  /**
   * Creates a window.
   * @return a window.
   */
  private JFrame createWindow() {
    JFrame window = new JFrame("Local Dynamic Simple Renderer Application");
    window.setBounds(100, 100, 1000, 700);
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    window.getContentPane().setLayout(new BorderLayout(0, 0));
    window.addWindowListener(new WindowAdapter() {
      @Override
      public void windowClosing(WindowEvent windowEvent) {
        super.windowClosing(windowEvent);
        map.dispose();
      }
    });
    return window;
  }

  private String getPathSampleData() {
    String FSP = System.getProperty("file.separator");
    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;
  }
  
  private String wrap(String str) {
    // create a HTML string that wraps text when longer
    return "<html><p style='width:200px;'>" + str + "</html>";
  }
}
Feedback on this topic?