AddRSSWeatherLayer.cs
RSS Weather layer
AddRSSWeatherLayer.cs
// Copyright 2006 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.
// 

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using ESRI.ArcGIS.ADF.BaseClasses;
using ESRI.ArcGIS.ADF.CATIDs;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Display;

namespace RSSWeatherLayer
{
  /// <summary>
  /// Add a new weather item given a zipCode.
  /// </summary>
  /// <remarks>Should the weather item exist, it will be updated</remarks>
  [ClassInterface(ClassInterfaceType.None)]
  [Guid("C9260965-D3AA-4c28-B55A-023C41F1CA39")]
  [ProgId("RSSWeatherLayer.AddRSSWeatherLayer")]
  [ComVisible(true)]
  public sealed class AddRSSWeatherLayer: BaseCommand
  {
    #region COM Registration Function(s)
    [ComRegisterFunction()]
    [ComVisible(false)]
    static void RegisterFunction(Type registerType)
    {
      // Required for ArcGIS Component Category Registrar support
      ArcGISCategoryRegistration(registerType);

      //
      // TODO: Add any COM registration code here
      //
    }

    [ComUnregisterFunction()]
    [ComVisible(false)]
    static void UnregisterFunction(Type registerType)
    {
      // Required for ArcGIS Component Category Registrar support
      ArcGISCategoryUnregistration(registerType);

      //
      // TODO: Add any COM unregistration code here
      //
    }

    #region ArcGIS Component Category Registrar generated code
    /// <summary>
    /// Required method for ArcGIS Component Category registration -
    /// Do not modify the contents of this method with the code editor.
    /// </summary>
    private static void ArcGISCategoryRegistration(Type registerType)
    {
      string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID);
      ControlsCommands.Register(regKey);
      MxCommands.Register(regKey);

    }
    /// <summary>
    /// Required method for ArcGIS Component Category unregistration -
    /// Do not modify the contents of this method with the code editor.
    /// </summary>
    private static void ArcGISCategoryUnregistration(Type registerType)
    {
      string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID);
      ControlsCommands.Unregister(regKey);
      MxCommands.Unregister(regKey);

    }

    #endregion
    #endregion

    //class members
    private IHookHelper               m_pHookHelper     = null;
    private RSSWeatherLayerClass      m_weatherLayer    = null;
    private bool                      m_bOnce            = true;
    private bool                      m_bConnected      = false;
    private IInvalidArea3              m_invlidArea      = null;
    private IPoint                    m_point            = null;

    public AddRSSWeatherLayer()
    {
      base.m_category = "Weather";
      base.m_caption = "Add RSS Weather Layer";
      base.m_message = "Add RSS Weather Layer";
      base.m_toolTip = "Add RSS Weather Layer";
      base.m_name = base.m_category + "_" + base.m_caption;

      try
      {
        string bitmapResourceName = GetType().Name + ".bmp";
        base.m_bitmap = new Bitmap(GetType(), bitmapResourceName);
      }
      catch (Exception ex)
      {
        System.Diagnostics.Trace.WriteLine(ex.Message, "Invalid Bitmap");
      }
    }

    #region Overriden Class Methods

    /// <summary>
    /// Occurs when this command is created
    /// </summary>
    /// <param name="hook">Instance of the application</param>
    public override void OnCreate(object hook)
    {
      //Instantiate the hook helper
      if (m_pHookHelper == null)
        m_pHookHelper = new HookHelperClass ();

      //set the hook
      m_pHookHelper.Hook = hook;

      m_invlidArea = new InvalidAreaClass();
      
      m_point = new PointClass();

      //set verbose events in order to listen to ItemDeleted event
      ((IViewManager)m_pHookHelper.FocusMap).VerboseEvents = true;
      
      //hook the ItemDeleted event in order to track removal of the layer from the TOC
      ((IActiveViewEvents_Event)m_pHookHelper.FocusMap).ItemDeleted += new IActiveViewEvents_ItemDeletedEventHandler(OnItemDeleted);
    }

    /// <summary>
    /// Occurs when this command is clicked
    /// </summary>
    public override void OnClick()
    {
      try
      {        
        if(!m_bConnected)
        {
          //set the display for the InvalidArea member
          m_invlidArea.Display = m_pHookHelper.ActiveView.ScreenDisplay;

          //check first that the layer was added to the globe
          if(m_bOnce == true)
          {  
            //instantiate the layer
            m_weatherLayer = new RSSWeatherLayerClass();
            m_bOnce = false;
          }
          //test whether the layer has been added to the map
          bool bLayerHasBeenAdded = false;
          ILayer layer = null;

          if(m_pHookHelper.FocusMap.LayerCount != 0)
          {
            IEnumLayer layers = m_pHookHelper.FocusMap.get_Layers(null, false);
            layers.Reset();
            layer = layers.Next();
            while(layer != null)
            {
              if(layer is RSSWeatherLayerClass)
              {
                bLayerHasBeenAdded = true;
                break;
              }
              layer = layers.Next();
            }
          }

          //add the layer to the map
          if(!bLayerHasBeenAdded)
          {
            layer = (ILayer)m_weatherLayer;
            layer.Name = "RSS Weather Layer";
            try
            {
              m_pHookHelper.FocusMap.AddLayer(layer);
              //wires layer's events
              m_weatherLayer.OnWeatherItemAdded += new WeatherItemAdded(OnWeatherItemAdded);
              m_weatherLayer.OnWeatherItemsUpdated += new WeatherItemsUpdated(OnWeatherItemsUpdated);
            }
            catch(Exception ex)
            {
              System.Diagnostics.Trace.WriteLine("Failed" + ex.Message);
            }
          }

          //connect to the service
          m_weatherLayer.Connect();
        }
        else
        {
          //disconnect from the service
          m_weatherLayer.Disconnect();
        
          //delete the layer
          m_pHookHelper.FocusMap.DeleteLayer(m_weatherLayer);

          //dispose the layer
          m_weatherLayer = null;
          m_bOnce = true;
        }


        m_bConnected = !m_bConnected;
      }
      catch(Exception ex)
      {
        System.Diagnostics.Trace.WriteLine(ex.Message);
      }
    }

    /// <summary>
    /// Indicates whether or not this command is checked. 
    /// </summary>
    public override bool Checked
    {
      get
      {
        return m_bConnected;
      }
    }

    #endregion

    /// <summary>
    /// weather layer ItemAdded event handler
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="args"></param>
    /// <remarks>gets fired when an item is added to the table</remarks>
    private void OnWeatherItemAdded(object sender, WeatherItemEventArgs args)
    {
      //get the coordinate of the middle of the area needed to be refreshed from the event argument
      m_point.X = args.mapX;
      m_point.Y = args.mapY;
      m_invlidArea.Add(m_point);
      
      //refresh the symbol area only
      short cacheId = m_pHookHelper.ActiveView.get_ScreenCacheID(esriViewDrawPhase.esriViewGeography, m_weatherLayer);
      m_invlidArea.InvalidateEx(cacheId, Math.Max(args.IconWidth, args.IconHeight));
      m_pHookHelper.ActiveView.ScreenDisplay.UpdateWindow();
    }

    /// <summary>
    /// Weather layer ItemsUpdated event handler
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="args"></param>
    /// <remarks>gets fired when the update thread finish updating all the items in the table</remarks>
    private void OnWeatherItemsUpdated(object sender, EventArgs args)
    {
      //refresh the display
      m_pHookHelper.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, m_weatherLayer, m_pHookHelper.ActiveView.Extent);
    }

    /// <summary>
    /// Listen to ActiveViewEvents.ItemDeleted in order to track whether the layer has been 
    /// removed from the TOC
    /// </summary>
    /// <param name="Item"></param>
    void OnItemDeleted(object Item)
    {
      //test that the deleted layer is RSSWeatherLayerClass
      if (Item is RSSWeatherLayerClass)
      {
        if (m_bConnected && null != m_weatherLayer)
        {
          m_bConnected = false;

          //disconnect from the service
          m_weatherLayer.Disconnect();

          //dispose the layer
          m_weatherLayer = null;
          m_bOnce = true;
        }
      }
    }
  }
}