Time slider

Download Sample Viewer

Description

This application demonstrates the use of the JTimeSlider to display hurricane paths changing with the passage of time. To use the sample, move the start date and end date slider to the time interval you want to start with. Push the play button to automate the display of hurricane paths on the map. The time slider can also be manipulated manually. For example, you can change the time interval or use the forward and rewind buttons to manually cycle through the hurricane paths being displayed. This sample uses a local map package (.mpk) made in ArcMap to create a ArcGISLocalDynamicMapServiceLayer which contains the time-aware layer and the associated symbology. The legend is displayed in this application using a screenshot image.

Code snippet


    JTimeSlider jTimeSlider = new JTimeSlider();
    jTimeSlider.setTitle("Hurricane Paths");
    jTimeSlider.addLayer(timeAwareLayer);
    jTimeSlider.setTimeMode(TimeMode.TimeExtent);
  

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.toolkit;

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;

import java.awt.BorderLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.net.URL;
import java.util.Calendar;

import com.esri.map.JMap;
import com.esri.map.LayerInitializeCompleteEvent;
import com.esri.map.LayerInitializeCompleteListener;
import com.esri.map.LayerList;
import com.esri.map.TimeAwareLayer;
import com.esri.runtime.ArcGISRuntime;
import com.esri.client.local.ArcGISLocalDynamicMapServiceLayer;
import com.esri.client.local.ArcGISLocalTiledLayer;
import com.esri.toolkit.sliders.JTimeSlider;
import com.esri.toolkit.sliders.JTimeSlider.TimeMode;
import com.esri.core.geometry.Envelope;
import com.esri.core.map.TimeOptions.Units;

/**
 * This application demonstrates the use of the toolkit's
 * {@link JTimeSlider} to display hurricane paths changing with the
 * passage of time.
 * <p>
 * To use the sample, move the start date and end date slider to the time
 * interval you want to start with. Push the play button to automate the
 * display of hurricane paths on the map. The time slider can also be
 * manipulated manually. For example, you can change the time interval
 * or use the forward and rewind buttons to manually cycle through the
 * hurricane paths being displayed.
 * <p>
 * This sample uses a local map package (.mpk) made in ArcMap to
 * create a {@link ArcGISLocalDynamicMapServiceLayer} which contains the
 * time-aware layer and the associated symbology.  The legend is
 * displayed in this application using a screenshot image.
 */
public class LocalTimeAwareApp {

  private JMap map;
  private JComponent contentPane;
  private JTimeSlider timeSlider;
  private static String FSP = System.getProperty("file.separator");

  // ------------------------------------------------------------------------
  // Constructor
  // ------------------------------------------------------------------------
  public LocalTimeAwareApp() {

  }

  // ------------------------------------------------------------------------
  // Core functionality
  // ------------------------------------------------------------------------
  /**
   * Creates a JTimeSlider.
   * @param TimeAwareLayer layer to which the time slider will be associated.
   */
  private JTimeSlider createTimeSlider(TimeAwareLayer layer) {
    JTimeSlider jTimeSlider = new JTimeSlider();
    jTimeSlider.setTitle("Hurricane Paths");
    jTimeSlider.addLayer(layer);
    jTimeSlider.setTimeMode(TimeMode.TimeExtent);
    jTimeSlider.setPlaybackRate(1000); // 1 second per tick
    jTimeSlider.setVisible(false);
    return jTimeSlider;
  }

  /**
   * Creates the JComponent and the application content
   * which gets added to this component.
   *
   * @return contentPane - the JComponent containing the application content
   */
  public JComponent createUI() {

    contentPane = createContentPane();

    // description
    final JPanel description = createDescription();
    description.setLocation(10, 10);
    contentPane.add(description);

    //legend
    final JPanel legend = createLegend();
    legend.setLocation(10, description.getHeight() + 20);
    contentPane.add(legend);

    // create map
    map = new JMap();

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

          @Override
          public void layerInitializeComplete(LayerInitializeCompleteEvent e) {
            if (e.getID() == LayerInitializeCompleteEvent.LOCALLAYERCREATE_ERROR) {
              String errMsg = "Failed to initialize due to "
                  + tiledLayer.getInitializationError();
              JOptionPane.showMessageDialog(map, wrap(errMsg), "",
                  JOptionPane.ERROR_MESSAGE);
            }
          }
        });

    // create and add the dynamic layer
    final ArcGISLocalDynamicMapServiceLayer dynamicLayer = new ArcGISLocalDynamicMapServiceLayer(
        getPathSampleData() + "mpks"+FSP+"TimeAwareHurricanes.mpk");
    layers.add(dynamicLayer);

    dynamicLayer
        .addLayerInitializeCompleteListener(new LayerInitializeCompleteListener() {

          @Override
          public void layerInitializeComplete(LayerInitializeCompleteEvent e) {
            if (e.getID() == LayerInitializeCompleteEvent.LOCALLAYERCREATE_ERROR) {
              String errMsg = "Failed to initialize due to "
                  + dynamicLayer.getInitializationError();
              JOptionPane.showMessageDialog(map, wrap(errMsg), "",
                  JOptionPane.ERROR_MESSAGE);
            }
          }
        });
    
    // create the time slider with the dynamic layer
    timeSlider = createTimeSlider(dynamicLayer);

    // set time extent of time slider once the dynamic layer is initialized
    dynamicLayer.addLayerInitializeCompleteListener(new LayerInitializeCompleteListener() {

      @Override
      public void layerInitializeComplete(LayerInitializeCompleteEvent e) {
        SwingUtilities.invokeLater(new Runnable() {
          @Override
          public void run() {
            timeSlider.setTimeExtent(dynamicLayer.getTimeInfo().getTimeExtent(), 1, Units.Days);
            Calendar calendar = dynamicLayer.getTimeInfo().getTimeExtent().getStartDate();
            timeSlider.setTimeIntervalStart(calendar);
            calendar.add(Calendar.DAY_OF_MONTH, 1);
            timeSlider.setTimeIntervalEnd(calendar);
            timeSlider.setVisible(true);
            description.setVisible(true);
            legend.setVisible(true);
          }
        });
      }
    });

    // set the initial extent of the map
    map.setExtent(new Envelope(-15141796,113237,5976634,8887493));

    // add map and time slider to content pane
    contentPane.add(map, BorderLayout.CENTER);
    contentPane.add(timeSlider, BorderLayout.SOUTH);

    return contentPane;
  }

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

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

  // ------------------------------------------------------------------------
  // Private methods
  // ------------------------------------------------------------------------
  /**
   * Creates a content pane.
   * @return contentPane - 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 window.
   * @return a window.
   */
  private JFrame createWindow() {
    JFrame window = new JFrame("Local Time Aware 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;
  }

  /**
   * Creates a JPanel displaying a legend image for the hurricane intensity
   *
   * @return legendContainer - a JPanel containing the legend
   */
  private JPanel createLegend() {
    JPanel legendContainer = new JPanel();
    legendContainer.setLayout(new BoxLayout(legendContainer, 0));
    legendContainer.setBackground(new Color(0, 0, 0, 0));

    try {
      URL url = this.getClass().getResource(
          "resources/localhurricane_legend.png");
      BufferedImage image = null;
      image = ImageIO.read(url);

      JLabel legend = new JLabel();
      legend.setIcon(new ImageIcon(image));
      legendContainer.add(legend);
      legendContainer.setSize(image.getWidth()+2, image.getHeight()+2);

    } catch (Exception e) {
      e.printStackTrace();
    }
    legendContainer.setBorder(new LineBorder(Color.BLACK, 1, false));
    legendContainer.setVisible(false);
    return legendContainer;
  }

  /**
   * Creates a description for this application.
   * @return descriptionContainer - a JPanel containing the description
   */
  private JPanel createDescription() {
    JPanel descriptionContainer = new JPanel();
    descriptionContainer.setLayout(new BoxLayout(descriptionContainer, 0));

    descriptionContainer.setSize(240, 185);
    JTextArea description = new JTextArea(
        "To use the sample, move the start date and end date slider to the time " +
            "interval you want to start with. Push the play button " +
            "to automate the display of hurricane paths on the map. The time slider can " +
            "also be manipulated manually. For example, you can change the time interval " +
            "or use the forward and rewind buttons to manually cycle through the hurricane " +
        "paths being displayed.");
    description.setFont(new Font("Verdana", Font.PLAIN, 11));
    description.setForeground(Color.WHITE);
    description.setBackground(new Color(0, 0, 0, 180));
    description.setEditable(false);
    description.setLineWrap(true);
    description.setWrapStyleWord(true);
    description.setBorder(BorderFactory.createEmptyBorder(5,10,5,5));
    descriptionContainer.add(description);
    descriptionContainer.setBackground(new Color(0, 0, 0, 0));
    descriptionContainer.setBorder(new LineBorder(Color.BLACK, 2, false));
    descriptionContainer.setVisible(false);
    return descriptionContainer;
  }

  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;
  }
  
  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?