RSS Weather layer
CustomLayerBase.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.Collections;
using System.Data;
using System.Runtime.InteropServices;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Display;
namespace RSSWeatherLayer
{
/// <summary>
/// Summary description for clsCustomLayer.
/// </summary>
public abstract class CustomLayerBase : ILayer, IGeoDataset, IPersistVariant, ILayerGeneralProperties, IEnumerable, IDisposable
{
#region Class members
/// <summary>
/// Keep the layer's extent. Returned by the ILayer::Extent property
/// </summary>
/// <remarks>The extent should be spatial-referenced to the DateFrame's spatial reference.
/// </remarks>
protected IEnvelope m_extent = null;
/// <summary>
/// Store the layer's underlying data spatial reference. Returned by IGeoDataset::SpatialReference.
/// </summary>
/// <remarks>This spatial reference should not be reprojected. In your inheriting
/// class you will need to have another parameter that will keep the DataFrame's spatial reference
/// that would use to reproject the geometries and the extent of the layer.</remarks>
protected ISpatialReference m_spatialRef = null;
/// <summary>
/// Layer's name. Returned by ILayer::Name property
/// </summary>
protected string m_sName;
/// <summary>
/// Flag which determines whether the layers is visible. Returned by ILayer::Visible
/// </summary>
/// <remarks>You should use this member in your inherited class in the Draw method.</remarks>
protected bool m_visible;
/// <summary>
/// determines whether the layers is cached
/// </summary>
protected bool m_IsCached;
/// <summary>
/// Flag thich determine whether the layer is valid (connected to its data source, has valid information etc.).
/// Returned by ILAyer::Valid.
/// </summary>
/// <remarks>You can use this flag to determine for example whether the layer can be available or not.</remarks>
protected bool m_bValid = true;
/// <summary>
/// Keep the maximum scale value at which the layer will display
/// </summary>
protected double m_MaximumScale;
/// <summary>
/// Keep the minimum scale value at which the layer will display
/// </summary>
protected double m_MinimumScale;
/// <summary>
/// determines whether the layers is supposed to show its MapTips
/// </summary>
protected bool m_ShowTips;
/// <summary>
/// The data structure for the custom layer
/// </summary>
/// <remarks>By default, the DataTable gets initialized in the BaseClass Ctor with an ID column
/// which is AutoIncremented. The BaseClass also support enumerator which is actually en enumerator of
/// the table as well as a direct indexer.</remarks>
protected DataTable m_table;
#endregion
#region CTor
/// <summary>
/// Default Ctor
/// </summary>
public CustomLayerBase()
{
m_sName = string.Empty;
m_visible = true;
m_IsCached = false;
m_MaximumScale = 0;
m_MinimumScale = 0;
m_table = new DataTable("RECORDS");
m_table.Columns.Add("ID", typeof(long));
}
#endregion
#region IGeoDataset Members
/// <summary>
///The layers geodataset extent which is a union of the extents of all
/// the items of the layer
/// </summary>
/// <remarks>In your inheriting class, consider the following code to calculate the layer's extent:
/// <code>
/// public override IEnvelope Extent
///{
/// get
/// {
/// m_extent = GetLayerExtent();
/// if (null == m_extent )
/// return null;
///
/// IEnvelope env = ((IClone)m_extent ).Clone() as IEnvelope;
/// if(null != m_layerSpatialRef)
/// env.Project(m_layerSpatialRef);
///
/// return env;
/// }
///}
/// private IEnvelope GetLayerExtent()
///{
/// if (null == base.m_spRef)
/// {
/// base.m_spRef = CreateGeographicSpatialReference();
/// }
///
/// IEnvelope env = new EnvelopeClass();
/// env.SpatialReference = base.m_spRef;
/// IPoint point = new PointClass();
/// point.SpatialReference = m_spRef;
/// foreach (DataRow r in m_table.Rows)
/// {
/// point.Y = Convert.ToDouble(r["Y"]);
/// point.X = Convert.ToDouble(r["X"]);
///
/// env.Union(point.Envelope);
/// }
///
/// return env;
///}
/// </code>
/// </remarks>
virtual public IEnvelope Extent
{
get
{
return m_extent;
}
}
/// <summary>
/// The spatial reference of the underlying data.
/// </summary>
/// <remarks>The property must return the underlying data spatial reference and
/// must not reporoject it into the layer's spatial reference </remarks>
virtual public ISpatialReference SpatialReference
{
get
{
return m_spatialRef;
}
}
#endregion
#region IPersistVariant Members
/// <summary>
/// The ID of the object.
/// </summary>
virtual public UID ID
{
get
{
// TODO: Add clsCustomLayer.ID getter implementation
return null;
}
}
/// <summary>
/// Loads the object properties from the stream.
/// </summary>
/// <param name="Stream"></param>
/// <remarks>The Load method must read the data from the stream in the same order the data was
/// written to the stream in the Save method.
/// Streams are sequential; you mut ensure that your data is saved and loaded in the correct order,
/// so that the correct data is written to the correct member.
/// </remarks>
virtual public void Load(IVariantStream Stream)
{
// TODO: Add clsCustomLayer.Load implementation
}
/// <summary>
/// Saves the object properties to the stream.
/// </summary>
/// <param name="Stream"></param>
virtual public void Save(IVariantStream Stream)
{
// TODO: Add clsCustomLayer.Save implementation
}
#endregion
#region ILayer Members
#region Properties
/// <summary>
/// Indicates if the layer shows map tips.
/// </summary>
/// <remarks>Indicates whether or not map tips are shown for the layer.
/// If set to True, then map tips will be shown for the layer.
/// You can determine the text that will be shown via TipText.
///</remarks>
virtual public bool ShowTips
{
get
{
return m_ShowTips;
}
set
{
m_ShowTips = value;
}
}
/// <summary>
/// The default area of interest for the layer. Returns the spatial-referenced extent of the layer.
/// </summary>
virtual public IEnvelope AreaOfInterest
{
get
{
return m_extent;
}
}
/// <summary>
/// Indicates if the layer is currently visible.
/// </summary>
virtual public bool Visible
{
get
{
return m_visible;
}
set
{
m_visible = value;
}
}
/// <summary>
/// Indicates if the layer needs its own display cache.
/// </summary>
/// <remarks>This property indicates whether or not the layer requires its own display cache.
/// If this property is True, then the Map will use a separate display cache for the layer so
/// that it can be refreshed indpendently of other layers.</remarks>
virtual public bool Cached
{
get
{
return m_IsCached;
}
set
{
m_IsCached = value;
}
}
/// <summary>
/// Minimum scale (representative fraction) at which the layer will display.
/// </summary>
/// <remarks>Specifies the minimum scale at which the layer will be displayed.
/// This means that if you zoom out beyond this scale, the layer will not display.
/// For example, specify 1000 to have the layer not display when zoomed out beyond 1:1000.</remarks>
virtual public double MinimumScale
{
get
{
return m_MinimumScale;
}
set
{
m_MinimumScale = value;
}
}
/// <summary>
/// Indicates if the layer is currently valid.
/// </summary>
/// <remarks>The valid property indicates if the layer is currently valid.
/// Layers that reference feature classes are valid when they hold a reference to a valid feature class.
/// The property does not however validate the integrity of the feature classes reference to the database.
/// Therefore, in rare situations if a datasource is removed after a layer is initialized,
/// the layer will report itself as valid but query attempts to the data source will error due to the lack
/// of underlying data.</remarks>
virtual public bool Valid
{
get
{
return m_bValid;
}
}
/// <summary>
/// The Layer name.
/// </summary>
virtual public string Name
{
get
{
return m_sName;
}
set
{
m_sName = value;
}
}
/// <summary>
/// Maximum scale (representative fraction) at which the layer will display.
/// </summary>
/// <remarks>Specifies the maximum scale at which the layer will be displayed.
/// This means that if you zoom in beyond this scale, the layer will not display.
/// For example, specify 500 to have the layer not display when zoomed in beyond 1:500.</remarks>
virtual public double MaximumScale
{
get
{
return m_MaximumScale;
}
set
{
m_MaximumScale = value;
}
}
/// <summary>
/// Supported draw phases.
/// </summary>
/// <remarks>Indicates the draw phases supported by the layer (esriDPGeography, esriDPAnnotation,
/// esriDPSelection, or any combination of the three).
/// The supported draw phases are defined by esriDrawPhase.
/// When multiple draw phases are supported, the sum of the constants is used.
/// For example, if SupportedDrawPhases = 3 then the layer supports drawing in the geography and annotation phases.</remarks>
public int SupportedDrawPhases
{
get
{
return (int)esriDrawPhase.esriDPGeography;
}
}
/// <summary>
/// Spatial reference for the layer.
/// </summary>
///<remarks>This property is only used for map display, setting this property does not
///change the spatial reference of the layer's underlying data.
///The ArcGIS framework uses this property to pass the spatial reference from the map
///to the layer in order to support on-the-fly projection.</remarks>
ISpatialReference ESRI.ArcGIS.Carto.ILayer.SpatialReference
{
set
{
m_spatialRef = value;
}
}
#endregion
#region Methods
/// <summary>
/// Map tip text at the specified location.
/// </summary>
/// <param name="X"></param>
/// <param name="Y"></param>
/// <param name="Tolerance"></param>
/// <returns>The text string that gets displayed as a map tip if ShowTips = true.</returns>
virtual public string get_TipText(double X, double Y, double Tolerance)
{
return null;
}
/// <summary>
/// Draws the layer to the specified display for the given draw phase.
/// </summary>
/// <param name="drawPhase"></param>
/// <param name="Display"></param>
/// <param name="trackCancel"></param>
/// <remarks>This method draws the layer to the Display for the specified DrawPhase.
/// Use the TrackCancel object to allow the drawing of the layer to be interrupted by the user.
/// In order to implement you inheriting class, you must override this method</remarks>
public abstract void Draw(esriDrawPhase drawPhase, IDisplay Display, ITrackCancel trackCancel);
#endregion
#endregion
#region ILayerGeneralProperties Members
/// <summary>
/// Last maximum scale setting used by layer.
/// </summary>
virtual public double LastMaximumScale
{
get
{
return 0;
}
}
/// <summary>
/// Last minimum scale setting used by layer.
/// </summary>
virtual public double LastMinimumScale
{
get
{
return 0;
}
}
/// <summary>
/// Description for the layer.
/// </summary>
virtual public string LayerDescription
{
get
{
return null;
}
set
{
}
}
#endregion
#region Data Structure basic functionality
/// <summary>
/// Create a new item (does not add it to the layer)
/// </summary>
/// <returns></returns>
virtual public DataRow NewItem()
{
return m_table.NewRow();
}
/// <summary>
/// Add an item to the layer
/// </summary>
/// <param name="row"></param>
virtual public void AddItem(DataRow row)
{
m_table.Rows.Add(row);
}
/// <summary>
/// Add an item to the Layer
/// </summary>
/// <param name="values"></param>
virtual public void AddItem(object[] values)
{
m_table.Rows.Add(values);
}
/// <summary>
/// Query for items in the layer
/// </summary>
/// <param name="queryFilter">WHERE clause</param>
/// <returns></returns>
virtual public DataRow[] Select(string queryFilter)
{
return m_table.Select(queryFilter);
}
/// <summary>
/// Remove all items in the layer
/// </summary>
virtual public void Clear()
{
m_table.Rows.Clear();
}
/// <summary>
/// Remove the item from the layer
/// </summary>
/// <param name="row">The row to remove</param>
virtual public void RemoveItem(DataRow row)
{
m_table.Rows.Remove(row);
}
//indexer. Pass an index and return a record
public DataRow this[int index]
{
get
{
return m_table.Rows[index];
}
}
/// <summary>
/// return the number of geometries in the layer
/// </summary>
public int NumOfRecords
{
get
{
return m_table.Rows.Count;
}
}
#endregion
#region IEnumerable Members
/// <summary>
/// Allow users to directly enumerate through the layer's records
/// </summary>
/// <returns></returns>
public IEnumerator GetEnumerator()
{
return m_table.Rows.GetEnumerator();
}
#endregion
#region IDisposable Members
/// <summary>
/// Dispose the layer
/// </summary>
public void Dispose()
{
m_extent = null;
m_spatialRef = null;
}
#endregion
}
}