/*
 * Licensed Materials - Property of Rogue Wave Software, Inc. 
 * © Copyright Rogue Wave Software, Inc. 2014, 2015 
 * © Copyright IBM Corp. 2009, 2014
 * © Copyright ILOG 1996, 2009
 * All Rights Reserved.
 *
 * Note to U.S. Government Users Restricted Rights:
 * The Software and Documentation were developed at private expense and
 * are "Commercial Items" as that term is defined at 48 CFR 2.101,
 * consisting of "Commercial Computer Software" and
 * "Commercial Computer Software Documentation", as such terms are
 * used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4,
 * as applicable.
 */
import ilog.views.IlvGrapher;
import ilog.views.IlvGraphic;
import ilog.views.IlvManager;
import ilog.views.IlvManagerLayer;
import ilog.views.IlvManagerView;
import ilog.views.IlvManagerViewInteractor;
import ilog.views.IlvPoint;
import ilog.views.IlvRect;
import ilog.views.IlvSelection;
import ilog.views.IlvUnresizeableDrawSelection;
import ilog.views.event.InteractorChangedEvent;
import ilog.views.event.InteractorListener;
import ilog.views.graphic.IlvArrowLine;
import ilog.views.graphic.IlvHalfZoomingGraphic;
import ilog.views.graphic.IlvMarker;
import ilog.views.maps.IlvAreaOfInterest;
import ilog.views.maps.IlvAreaOfInterestVector;
import ilog.views.maps.IlvAreasOfInterestProperty;
import ilog.views.maps.IlvCoordinate;
import ilog.views.maps.IlvCoordinateSystemProperty;
import ilog.views.maps.IlvDMSCoordinateFormatter;
import ilog.views.maps.IlvDisplayPreferencesProperty;
import ilog.views.maps.IlvMagnifySymbolsInteractor;
import ilog.views.maps.IlvMapInputStream;
import ilog.views.maps.IlvMapLayerTreeProperty;
import ilog.views.maps.IlvMapScaleLimiter;
import ilog.views.maps.IlvUTMCoordinateFormatter;
import ilog.views.maps.beans.IlvJAreaOfInterestPanel;
import ilog.views.maps.beans.IlvJCompass;
import ilog.views.maps.beans.IlvJCoordinateSystemEditorPanel;
import ilog.views.maps.beans.IlvJMapsManagerViewControlBar;
import ilog.views.maps.beans.IlvJMouseCoordinateViewer;
import ilog.views.maps.beans.IlvLayerTreePanel;
import ilog.views.maps.beans.IlvMapLayer;
import ilog.views.maps.beans.IlvMapLayerTreeModel;
import ilog.views.maps.beans.editor.IlvCoordinatePanelFactory;
import ilog.views.maps.defense.symbology.app6a.IlvApp6aGraphic;
import ilog.views.maps.defense.symbology.app6a.IlvApp6aSymbol;
import ilog.views.maps.defense.symbology.app6a.IlvApp6aSymbologyTreeViewActions;
import ilog.views.maps.format.IlvDefaultDataPathResolver;
import ilog.views.maps.format.IlvMapDataPathManager;
import ilog.views.maps.graphic.IlvMapSelectionFactory;
import ilog.views.maps.graphic.style.IlvMapStyle;
import ilog.views.maps.grids.IlvAbstractBaseGrid;
import ilog.views.maps.grids.IlvLatLonGrid;
import ilog.views.maps.grids.IlvMGRSGrid;
import ilog.views.maps.grids.IlvMGRSGridZone;
import ilog.views.maps.projection.IlvProjectionUtil;
import ilog.views.maps.raster.IlvRasterMappedBuffer;
import ilog.views.maps.raster.datasource.IlvRasterStyle;
import ilog.views.maps.srs.coordsys.IlvCoordinateSystem;
import ilog.views.maps.srs.coordsys.IlvGeographicCoordinateSystem;
import ilog.views.maps.srs.coordsys.IlvProjectedCoordinateSystem;
import ilog.views.maps.srs.coordtrans.IlvCoordinateTransformation;
import ilog.views.maps.srs.coordtrans.IlvCoordinateTransformationException;
import ilog.views.maps.symbology.swing.IlvSymbologyTreeView;
import ilog.views.maps.theme.IlvMapStyleController;
import ilog.views.maps.theme.IlvMapStyleControllerProperty;
import ilog.views.sdm.IlvSDMEngine;
import ilog.views.sdm.IlvSDMException;
import ilog.views.sdm.renderer.IlvRendererUtil;
import ilog.views.sdm.renderer.IlvStyleSheetRenderer;
import ilog.views.sdm.renderer.maps.IlvMapStyleSheetRenderer;
import ilog.views.swing.IlvJManagerViewControlBar;
import ilog.views.swing.IlvJManagerViewPanel;
import ilog.views.swing.IlvToolTipManager;
import ilog.views.util.IlvProductUtil;
import ilog.views.util.IlvImageUtil;
import ilog.views.util.swing.layout.IlvBetterFlowLayout;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.ImageIcon;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.tree.DefaultMutableTreeNode;

import simulation.SimulationContext;
import simulation.SimulationController;

/**
 * This demo creates a simple map and overlays it with APP6a symbols, giving the
 * possibility to the user to start a symbol simulation. 
 */
public class App6aDemo extends JApplet {
  static {
    // replace the stylesheet renderer with map class.
    IlvRendererUtil.addRendererAlias(IlvRendererUtil.getRendererAlias(IlvStyleSheetRenderer.class.getName()), IlvMapStyleSheetRenderer.class.getName());
  }
  /**
   * subclass of IlvSymbologyTreeView to provide edition of the symbol on a
   * double-click
   */
  static class MySymbologyTreeView extends IlvSymbologyTreeView {
    /**
     * Creates a new <code>MySymbologyTreeView</code>.
     * @param engine The symbology engine that displays the symbol model.
     */
    public MySymbologyTreeView(IlvSDMEngine engine) {
      super(engine);
    }

    /**
     * Performs the edition of the currently selected symbol.
     */
    public void editSelectedSymbol() {
      performEdit();
    }
  }
  {
    // This sample uses JViews Maps for Defense features. When deploying an
    // application that includes this code, you need to be in possession
    // of a Rogue Wave JViews Maps for Defense Deployment license.
    IlvProductUtil.DeploymentLicenseRequired(
        IlvProductUtil.JViews_Maps_for_Defense_Deployment);
  }
  IlvManagerView view;// map view
  IlvJManagerViewPanel viewScroll;// scroll arond the map view
  JPanel symbologyPanel = new JPanel(new BorderLayout());
  MySymbologyTreeView symbPanel; // symbol tree
  IlvJCompass compass = new IlvJCompass();
  IlvJManagerViewControlBar viewToolbar; // zoom & selection toolbar
  IlvJAreaOfInterestPanel areaOfInterestPanel;// panel for areas of interest.
  IlvJCoordinateSystemEditorPanel csPanel;// coordinate system choice.
  IlvLayerTreePanel layerTreePanel;
  IlvJMouseCoordinateViewer locator;// coordinate information
  IlvSDMEngine symbology;
  int frames;
  long lastTime;
  private JButton brightnessUpButton;
  private JButton brightnessDownButton;
  private JButton contrastUpButton;
  private JButton contrastDownButton;
  private JButton saturationUpButton;
  private JButton saturationDownButton;
  private JButton transparencyUpButton;
  private JButton transparencyDownButton;
  private JComboBox gridCombo;
  private IlvManagerLayer gridLayer;

  /**
   * Constructor. creates and sets up the GUI.
   */
  public App6aDemo() {
    this(true);
  }

    /**
     * Constructor. creates and sets up the GUI.
     * @param applet indicates if the demo is launched in applet mode.
     */
    public App6aDemo(boolean applet) {
      super();
      if (applet) {
        IlvRasterMappedBuffer.setDefaultMemoryPolicy(IlvRasterMappedBuffer.USE_MEMORY);
      }
      // Make sure the swing construction is called in Swing event thread.
      ilog.views.util.swing.IlvSwingUtil.invokeAndWait(new Runnable() { public void run() {
      // create the main components
      view = new IlvManagerView() {
        public void paint(Graphics g) {
          super.paint(g);
          frames++;
        }
      };
      view.setManager(new IlvGrapher(0));
      IlvToolTipManager.registerView(view);
      viewScroll = new IlvJManagerViewPanel(view) {
                        public String getToolTipText(MouseEvent event) {
                                Point pt = SwingUtilities.convertPoint(this, event.getPoint(), view);
                                // Find component located at point pt
                                IlvGraphic o = view.getManager().getObject(new IlvPoint(pt.x, pt.y),
                                                view);
                                if(o instanceof IlvHalfZoomingGraphic) {
                                        return getToolTip(o);
                                }
                                return null;
                        }
      };
      viewToolbar = new IlvJMapsManagerViewControlBar();
      viewToolbar.setFloatable(false);
      IlvMagnifySymbolsInteractor magInteractor = new IlvMagnifySymbolsInteractor();
      // limit the number of iteration of the layout to increase speed.
      magInteractor.getAnnealingLabelLayout().setAllowedNumberOfIterations(1);
      IlvArrowLine lineTemplate = new IlvArrowLine();
      // setup a specific line
      lineTemplate.setForeground(Color.red);
      lineTemplate.setLineStyle(new float[] { 4, 4 });
      lineTemplate.setLineWidth(2);
      lineTemplate.setArrowPosition(1);
      // to set up a specific marker:
      IlvMarker markerTemplate = new IlvMarker();
      markerTemplate.setType(IlvMarker.IlvMarkerFilledCircle);
      markerTemplate.setForeground(Color.orange);
      markerTemplate.setSize(2);
      magInteractor.setTargetMarkerTemplate(markerTemplate);
      magInteractor.setConnectingLineTemplate(lineTemplate);
      installInteractorButton("Unclutter the symbols around the area clicked", //should be translated,but for easier code, marked as//$NON-NLS-1$ 
          "magnify_symbols_action_icon.gif", magInteractor); //$NON-NLS-1$ 
      areaOfInterestPanel = new IlvJAreaOfInterestPanel(view, true, false, false);
      csPanel = new IlvJCoordinateSystemEditorPanel();
      // Setup the components
      viewToolbar.setView(view);
      locator = new IlvJMouseCoordinateViewer();
      locator.setView(view);
      view.setKeepingAspectRatio(true);
      view.setBackground(new Color(80, 180, 240));
      view.setAntialiasing(true);
      view.setSize(new Dimension(600, 600));
      viewScroll.setPreferredSize(view.getSize());
      // create and setup a symbology
      symbology = new IlvSDMEngine();
      URL symbolCss = findURL("data/app6.css");//$NON-NLS-1$
      symbology.setReferenceView(view);
      symbology.setGrapher((IlvGrapher) view.getManager());
      try {
        symbology.setStyleSheets(new String[] { symbolCss.toString() });
      } catch (IlvSDMException e) {
        e.printStackTrace();
      }
//      view.getManager().setSelectionFactory(new IlvMapSelectionFactory());
      // provide feedback when symbols are selected.
      view.getManager().setSelectionFactory(new IlvMapSelectionFactory() {
        public IlvSelection makeSelection(IlvGraphic g) {
          if (g instanceof IlvHalfZoomingGraphic || g instanceof IlvApp6aGraphic){// symbols may be encapsulated.
            return new IlvUnresizeableDrawSelection(g);
          }
          return super.makeSelection(g);
        }
      });
      // geo reference the view
      view.getManager().setNamedProperty(new IlvCoordinateSystemProperty(IlvGeographicCoordinateSystem.WGS84));
      // setup coordinate system panel to reload symbols.
      csPanel.setCoordinateSystem(IlvCoordinateSystemProperty.GetCoordinateSystem(view.getManager()));
      csPanel.addCoordinateSystemChangeListener(new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt) {
          IlvCoordinateSystem system = (IlvCoordinateSystem) evt.getNewValue();
          if (system instanceof IlvProjectedCoordinateSystem) {// JV-4401 - change center of projection to the correct area
              IlvProjectedCoordinateSystem pcs=(IlvProjectedCoordinateSystem)system;
              boolean change=false;
              if(pcs.getProjection().getCentralMeridian()==0) {
                  pcs.getProjection().setCentralMeridian(SimulationContext.getCentralMeridian());
                  change=true;
                }
              if(pcs.getProjection().getCentralParallel()==0) {
                  pcs.getProjection().setCentralParallel(SimulationContext.getCentralParallel());
                  change=true;
                }
              if(change) {
                  csPanel.setCoordinateSystem(pcs);
                  return;
              }
          }
          view.getManager().setNamedProperty(new IlvCoordinateSystemProperty(system));
          symbology.loadData();
          IlvAreaOfInterest aoe = (IlvAreaOfInterest)areaOfInterestPanel.getList().getSelectedValue();
          if (aoe != null) {
                aoe.zoomTo(view);
          } else {
                SwingUtilities.invokeLater(new Runnable() {
                                                        public void run() {
                                                                view.fitTransformerToContent();                                                         
                                                        }                       
                });             
          }
        }
      });
      /* show this symbology on the GUI */
      // add layer tree panel
      layerTreePanel = new IlvLayerTreePanel();
      layerTreePanel.setView(view);
      JToolBar imageToolbar = new JToolBar();
      imageToolbar.setFloatable(false);
      ActionListener BSCListener = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          JButton source = (JButton) e.getSource();
          applyImageBCS(source, 1.1f);
        }
      };
      try {
        brightnessUpButton = new JButton(new ImageIcon(IlvImageUtil.getImageFromFile(getClass(), "more_brightness.gif"))); //$NON-NLS-1$
        brightnessUpButton.setToolTipText("Increase overall brightness"); //should be translated,but for easier code, marked as//$NON-NLS-1$
        brightnessUpButton.addActionListener(BSCListener);
        brightnessDownButton = new JButton(new ImageIcon(IlvImageUtil.getImageFromFile(getClass(), "less_brightness.gif"))); //$NON-NLS-1$
        brightnessDownButton.setToolTipText("Decrease overall brightness"); //should be translated,but for easier code, marked as//$NON-NLS-1$
        brightnessDownButton.addActionListener(BSCListener);
        contrastUpButton = new JButton(new ImageIcon(IlvImageUtil.getImageFromFile(getClass(), "more_contrast.gif"))); //$NON-NLS-1$
        contrastUpButton.setToolTipText("Increase overall contrast"); //should be translated,but for easier code, marked as//$NON-NLS-1$
        contrastUpButton.addActionListener(BSCListener);
        contrastDownButton = new JButton(new ImageIcon(IlvImageUtil.getImageFromFile(getClass(), "less_contrast.gif"))); //$NON-NLS-1$
        contrastDownButton.setToolTipText("Decrease overall contrast");//should be translated,but for easier code, marked as //$NON-NLS-1$
        contrastDownButton.addActionListener(BSCListener);
        saturationUpButton = new JButton(new ImageIcon(IlvImageUtil.getImageFromFile(getClass(), "more_saturation.gif"))); //$NON-NLS-1$
        saturationUpButton.setToolTipText("Increase overall saturation"); //should be translated,but for easier code, marked as//$NON-NLS-1$
        saturationUpButton.addActionListener(BSCListener);
        saturationDownButton = new JButton(new ImageIcon(IlvImageUtil.getImageFromFile(getClass(), "less_saturation.gif"))); //$NON-NLS-1$
        saturationDownButton.setToolTipText("Decrease overall saturation"); //should be translated,but for easier code, marked as//$NON-NLS-1$
        saturationDownButton.addActionListener(BSCListener);
        transparencyUpButton = new JButton(new ImageIcon(IlvImageUtil.getImageFromFile(getClass(), "more_transparency.gif"))); //$NON-NLS-1$
        transparencyUpButton.setToolTipText("Increase overall transparency"); //should be translated,but for easier code, marked as//$NON-NLS-1$
        transparencyUpButton.addActionListener(BSCListener);
        transparencyDownButton = new JButton(new ImageIcon(IlvImageUtil.getImageFromFile(getClass(), "less_transparency.gif"))); //$NON-NLS-1$
        transparencyDownButton.setToolTipText("Decrease overall transparency"); //should be translated,but for easier code, marked as//$NON-NLS-1$
        transparencyDownButton.addActionListener(BSCListener);
        Dimension buttonDim = new Dimension(26, 26);        
        configureComponentSize(brightnessUpButton, buttonDim);
        configureComponentSize(brightnessDownButton, buttonDim);
        configureComponentSize(contrastUpButton, buttonDim);
        configureComponentSize(contrastDownButton, buttonDim);
        configureComponentSize(saturationUpButton, buttonDim);
        configureComponentSize(saturationDownButton, buttonDim);
        configureComponentSize(transparencyUpButton, buttonDim);
        configureComponentSize(transparencyDownButton, buttonDim);
        imageToolbar.add(brightnessUpButton);
        imageToolbar.add(brightnessDownButton);
        imageToolbar.add(contrastUpButton);
        imageToolbar.add(contrastDownButton);
        imageToolbar.add(saturationUpButton);
        imageToolbar.add(saturationDownButton);
        imageToolbar.add(transparencyUpButton);
        imageToolbar.add(transparencyDownButton);
      } catch (IOException e) {
        //
      }
      imageToolbar.addSeparator();
      JLabel gridLabel = new JLabel("Contextual grid ");// should be translated,but for easier code, marked as //$NON-NLS-1$
      gridCombo = new JComboBox(new String[] { "None", "Lat/Lon", "MGRS" });// should be translated,but for easier code, marked as //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
      gridCombo.setToolTipText("Choose the Grid type"); //should be translated,but for easier code, marked as//$NON-NLS-1$
      Dimension comboDim = new Dimension(70, 22);
      gridCombo.setPreferredSize(comboDim);
      gridCombo.setMinimumSize(comboDim);
      gridCombo.setMaximumSize(comboDim);
      imageToolbar.add(gridLabel);
      imageToolbar.add(gridCombo);
      gridCombo.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          int selectedIndex = gridCombo.getSelectedIndex();
          if (gridLayer != null) {
            view.getManager().removeLayer(gridLayer.getIndex(), false);
            gridLayer = null;
          }
          IlvAbstractBaseGrid grid;
          switch (selectedIndex) {
          case 1:
            grid = new IlvLatLonGrid();
            grid.setGridColor(Color.red);
            gridLayer=grid;
            view.getManager().addLayer(gridLayer, -1);
            view.setLayerCached(view.getManager().getLayersCount()-1, true);
           break;
          case 2:
            grid = new IlvMGRSGrid();
            grid.setGridColor(Color.red);
            IlvMGRSGridZone.addAllZones((IlvMGRSGrid) grid);
            gridLayer=grid;
            view.getManager().addLayer(gridLayer, -1);
            view.setLayerCached(view.getManager().getLayersCount()-1, true);
          }
          view.setOptimizedTranslation(selectedIndex==0);
          view.repaint();
        }
      });
      // create the simulation controller GUI
      SimulationController simToolbar = new SimulationController(symbology);
      simToolbar.setFloatable(false);
      // load the initial map file.
      loadInitialData();
      // limit the zoom to correct scales.
      IlvMapScaleLimiter limiter = new IlvMapScaleLimiter(1f / 1000f, (float) (1 / 1E9));
      limiter.setView(view);
      // use the first Area of interest as the bouds where targets will be
      // created.
      IlvAreaOfInterestVector aoe = IlvAreasOfInterestProperty.GetAreasOfInterest(view.getManager());
      if (aoe != null && aoe.size() > 0) {
        IlvRect bounds = aoe.getArea(0).getRectangle();
        SimulationContext.setBounds(bounds.getMinX(), bounds.getMinY(), bounds.getMaxX(), bounds.getMaxY());
      }
      // connect the dynamic theme controller to use the view scale as its
      // reference
      IlvMapStyleController themeControl = IlvMapStyleControllerProperty.GetMapStyleController(view.getManager());
      themeControl.setView(view);
      themeControl.updateCurrentTheme();
      IlvBetterFlowLayout layout = new IlvBetterFlowLayout(FlowLayout.LEADING);
      JPanel toolbarContainer = new JPanel(layout);
      // configure the main window
      getContentPane().add(toolbarContainer, BorderLayout.NORTH);
      toolbarContainer.add(viewToolbar);
      compass.setView(view);
      getContentPane().add(viewScroll, BorderLayout.CENTER);
      final JTabbedPane tabPane = new JTabbedPane();
      tabPane.addTab("Map layers", layerTreePanel);// should be translated,but for easier code, marked as //$NON-NLS-1$
      tabPane.addTab("Areas of Interest", areaOfInterestPanel); // should be translated,but for easier code, marked as //$NON-NLS-1$
      tabPane.addTab("Coordinate System", csPanel); // should be translated,but for easier code, marked as //$NON-NLS-1$
      tabPane.addTab("Symbols",symbologyPanel);// should be translated,but for easier code, marked as //$NON-NLS-1$
      // lazy creation of the symbol tree because it listens to symbol changes and may slow down simulation.
      tabPane.getModel().addChangeListener( new ChangeListener() { 
      public void stateChanged(ChangeEvent e) {
        if(tabPane.getSelectedComponent() == symbologyPanel && symbPanel ==null){
          symbPanel = new MySymbologyTreeView(symbology);
          IlvApp6aSymbologyTreeViewActions app6Actions = new IlvApp6aSymbologyTreeViewActions();
          app6Actions.setLatLonPicker(new IlvCoordinatePanelFactory.CoordPointInputPanel(view, IlvDisplayPreferencesProperty.GetDisplayPreferences(view.getManager()).getCoordinateFormatter()));
          symbPanel.setSymbologyTreeViewActions(app6Actions);
          symbologyPanel.add(symbPanel,BorderLayout.CENTER);
        }
      }
      });
      JPanel tabPanel = new JPanel(new BorderLayout());
      JPanel southPanel=new JPanel();
      southPanel.add(compass);
      southPanel.add(locator);
      tabPanel.add(tabPane, BorderLayout.CENTER);
      tabPanel.add(southPanel, BorderLayout.SOUTH);
      getContentPane().add(tabPanel, BorderLayout.LINE_START);
      final JLabel fpsLabel = new JLabel("FPS:100"); // should be translated,but for easier code, marked as //$NON-NLS-1$
      simToolbar.addSeparator(new Dimension(10, 0));
      Dimension d = fpsLabel.getPreferredSize();
      fpsLabel.setMaximumSize(d);
      fpsLabel.setMinimumSize(d);
      simToolbar.add(fpsLabel);
      toolbarContainer.add(simToolbar);
      toolbarContainer.add(imageToolbar);
      // Add a timer to compute and display the number of Frames(refresh) per
      // second.
      Timer t = new Timer(true);
      t.schedule(new TimerTask() {
        public void run() {
          long time = System.currentTimeMillis();
          final double fps = (1000 * frames) / (time - lastTime);
          frames = 0;
          lastTime = time;
          SwingUtilities.invokeLater(new Runnable() {public void run() {
            fpsLabel.setText("FPS:" + (int) fps);// should be translated,but for easier code, marked as //$NON-NLS-1$
          }});
        }
      }, 1000, 1000);
      lastTime = System.currentTimeMillis();
      }});// event thread runnable
   }

  private void applyImageBCS(JButton source, float multiplier) {
    IlvMapLayerTreeModel ltm = IlvMapLayerTreeProperty.GetMapLayerTreeModel(view.getManager());
    Enumeration e = ltm.getEnumeration();
    while (e.hasMoreElements()) {
      DefaultMutableTreeNode node = (DefaultMutableTreeNode) e.nextElement();
      Object o = node.getUserObject();
      if (o instanceof IlvMapLayer) {
        IlvMapLayer layer = (IlvMapLayer) o;
        IlvMapStyle style = layer.getStyle();
        if (layer.getName().contains("Symbol")) { //$NON-NLS-1$
          // skip symbol layer
          continue;
        }
        if (style != null) {
          if (source == transparencyUpButton) {
            style.setAlpha(style.getAlpha() / multiplier);
          } else if (source == transparencyDownButton) {
            style.setAlpha(Math.min(style.getAlpha() * multiplier, 1.0f));
          } else {
            if (style instanceof IlvRasterStyle) {
              IlvRasterStyle rasterStyle = (IlvRasterStyle) style;
              if (source == brightnessUpButton) {
                rasterStyle.setBrightness(new Double(Math.min(rasterStyle.getBrightness().doubleValue() * multiplier, 2.0)));
              } else if (source == brightnessDownButton) {
                rasterStyle.setBrightness(new Double(rasterStyle.getBrightness().doubleValue() / multiplier));
              } else if (source == contrastUpButton) {
                rasterStyle.setContrast(new Double(Math.min(rasterStyle.getContrast().doubleValue() * multiplier, 2.0)));
              } else if (source == contrastDownButton) {
                rasterStyle.setContrast(new Double(rasterStyle.getContrast().doubleValue() / multiplier));
              } else if (source == saturationUpButton) {
                rasterStyle.setSaturation(new Double(Math.min(rasterStyle.getSaturation().doubleValue() * multiplier, 2.0)));
              } else if (source == saturationDownButton) {
                rasterStyle.setSaturation(new Double(rasterStyle.getSaturation().doubleValue() / multiplier));
              }
            }
          }
        }
      }
    }
    view.invalidateTripleBuffer(false);
    view.repaint();
  }


  /**
   * Loads a shape file.
   */
  private void loadInitialData() {
    URL mapFile = findURL("data/nellis.ivl"); //$NON-NLS-1$
    try {
      IlvDefaultDataPathResolver dpr = new IlvDefaultDataPathResolver(findURL("data").toExternalForm()); //$NON-NLS-1$
      IlvMapDataPathManager.AddDataPathResolver(dpr);
      InputStream stream = new BufferedInputStream(mapFile.openStream());
      // Create map input stream
      IlvMapInputStream mapInput = new IlvMapInputStream(stream, (String) null);
      // Clear current manager
      IlvManager manager = view.getManager();
      // Load the map
      mapInput.read(manager);
      // close the stream
      stream.close();
      // fit the view to its new content
      IlvAreaOfInterestVector vector = IlvAreasOfInterestProperty.GetAreasOfInterest(manager);
      ((IlvAreaOfInterest) vector.get(0)).zoomTo(view);
    } catch (Exception e1) {
      e1.printStackTrace();
    }
  }

  /**
   * Main method
   * @param args (ignored)
   */
  public static void main(String[] args) {
    // Sun recommends that to put the entire GUI initialization into the
    // AWT thread
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        App6aDemo demo = new App6aDemo(false);
        frame.getContentPane().add(demo);
        frame.setTitle("Defense mission monitoring"); //$NON-NLS-1$
        try {
          frame.setIconImage(IlvImageUtil.getImageFromFile(getClass(), "globe.gif")); //$NON-NLS-1$
        } catch (IOException e) {
          // do nothing
        }
        frame.pack();
        frame.setVisible(true);
      }
    });
  }

  private static URL findURL(String resource) {
    return App6aDemo.class.getResource(resource);
  }

  /**
   * Add an interactor on the toolbar.
   * @param tooltip button tooltip.
   * @param imageURL url of button icon.
   * @param interactor interactor to install on button press.
   */
  protected void installInteractorButton(String tooltip, String imageURL, final IlvManagerViewInteractor interactor) {
    Image image = null;
    try {
      image = IlvImageUtil.getImageFromFile(App6aDemo.class, imageURL);
    } catch (IOException e1) {
      e1.printStackTrace();
    }
    final JToggleButton button = new JToggleButton(new ImageIcon(image));
    button.setMargin(new Insets(2, 2, 2, 2));
    if (tooltip != null)
      button.setToolTipText(tooltip);
    viewToolbar.add(button);
    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        if (button.isSelected()) {
          view.setInteractor(interactor);
          view.requestFocus();
        } else if (view.getInteractor() == interactor) {
          view.popInteractor();
        }
      }
    });
    InteractorListener interactorListener = new InteractorListener() {
      public void interactorChanged(InteractorChangedEvent event) {
        boolean isMyInteractor = (event.getNewValue() == interactor);
        if (button.isSelected() != isMyInteractor) {
          button.setSelected(isMyInteractor);
        }
      }
    };
    view.addInteractorListener(interactorListener);
  }
  
  
        /**
         * Returns a tooltip associated to a graphical object by making an HTML table
         * from its IlvAttributeProperty.
         * 
         * @param graphic
         *          Graphical object
         * @return the string to display as a tooltip.
         */
        protected String getToolTip(IlvGraphic graphic) {
                IlvApp6aSymbol symbol =  (IlvApp6aSymbol)graphic.getProperty("IlvSDMObject"); //$NON-NLS-1$
                String speed = (String)symbol.getProperty("SPEED"); //$NON-NLS-1$
                String tooltip;
                String extraInfo ="";//$NON-NLS-1$
        // add location DMS & MGRS properties          
        IlvDMSCoordinateFormatter DMSFormatter = new IlvDMSCoordinateFormatter();
        IlvUTMCoordinateFormatter UTMFormatter = new IlvUTMCoordinateFormatter();
        double olon=symbol.getLongitude();
        double olat=symbol.getLatitude();
        DMSFormatter.setLonLat(olon, olat);
        UTMFormatter.setLonLat(olon, olat);
        String lodms=DMSFormatter.getLongitudeString();
        String ladms=DMSFormatter.getLatitudeString();
        String utm=UTMFormatter.toString();
                
                if (speed != null) {
                        extraInfo = "</TD></TR><TR><TD>SPEED</TD><TD>"+symbol.getProperty("SPEED")+  //$NON-NLS-1$//$NON-NLS-2$
                                                                        "</TD></TR><TR><TD>HEADING</TD><TD>"+symbol.getProperty("DIRECTION_OF_MOVEMENT_INDICATOR")+ //$NON-NLS-1$//$NON-NLS-2$
                                                                        "</TD></TR><TR><TD>ALTITUDE</TD><TD>"+symbol.getProperty("ALTITUDE_OR_DEPTH"); //$NON-NLS-1$//$NON-NLS-2$
                        
                }
                tooltip = "<HTML><TABLE><TR><TD>LONGITUDE</TD><TD>"+lodms+ //$NON-NLS-1$
                                                                                "</TD></TR><TR><TD>LATITUDE</TD><TD>"+ladms+ //$NON-NLS-1$
                                                                                "</TD></TR><TR><TD>UTM COORD.</TD><TD>"+utm+ //$NON-NLS-1$
                                                                                extraInfo +
                                                                                "</TD></TR></TABLE></HTML>"; //$NON-NLS-1$
                return tooltip;
        }
        
        /**
         * Computes the lat/lon of the point on the map.
         * 
         * @param point
         *          location of the mouse on the view.
         * @return the lat/lon coordinates in radians, or null.
         */
        protected IlvCoordinate computeCoordinates(Point point) {
                IlvCoordinate coord;
                IlvPoint pt = new IlvPoint(point.x, point.y);
                view.getTransformer().inverse(pt);
                IlvProjectionUtil.invertY(pt);
                try {
                        IlvCoordinateSystem cs = IlvCoordinateSystemProperty
                                        .GetCoordinateSystem(view.getManager());
                        IlvCoordinateTransformation ct = IlvCoordinateTransformation
                                        .CreateTransformation(cs, IlvGeographicCoordinateSystem.KERNEL);
                        coord = new IlvCoordinate(pt.x, pt.y);
                        ct.transform(coord, coord);
                } catch (IlvCoordinateTransformationException e) {
                        coord = null;
                }
                return coord;
        }
        
        private void configureComponentSize(JComponent comp, Dimension buttonDim) {
    comp.setPreferredSize(buttonDim);
    comp.setMinimumSize(buttonDim);
    comp.setMaximumSize(buttonDim);
  }
  //JV-3814
          Override
  public void destroy() { 
    super.destroy(); 
    // This method is intended to workaround memory management issues 
    // in the Sun JRE. Please refer to the method documentation for more 
    // details and a description of the known issues. 
    ilog.views.util.swing.IlvSwingUtil.cleanupApplet(); 
  } 

}