using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Timers;
namespace SharpMap.Layers
{
///
/// Types of layer collections
///
public enum LayerCollectionType
{
///
/// Layer collection for layers with datasources that are more or less static (e.g ShapeFiles)
///
Static,
///
/// Layer collection for layers with datasources that update frequently (e.g. moving vehicle)
///
Variable,
///
/// Layer collection for layers are completely opaque and serve as Background (e.g. WMS, OSM)
///
Background,
}
///
/// Signature of function to handle VariableLayerCollectionRequery event
///
/// The sender of the event
/// The arguments, EventArgs.Empty in all cases
public delegate void VariableLayerCollectionRequeryHandler(object sender, EventArgs e);
///
/// Layer collection
///
/// TODO:REEVALUEATE
[Serializable]
public class VariableLayerCollection : LayerCollection
{
//private readonly LayerCollection _variableLayers;
//[NonSerialized]
//private Timer _timer;
private volatile bool _isQuerying;
//[NonSerialized]
//private EventHandler _handler;
private bool _pause;
///
/// Method to restart the internal Timer
///
public void TouchTimer()
{
// check for pending re-draw (eg after map pan/zoom completed)
//if (_timer.Enabled) return;
if (_isQuerying) return;
//_timer.Start();
foreach (var lyr in this)
{
if (lyr is ILayerEx lyrEx)
lyrEx.RaiseRenderRequired();
}
System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(OnRequery));
}
///
/// Method called when deserializing this object.
///
///
[OnDeserializing]
public void OnDeserializing(StreamingContext context)
{
//_timer = new Timer();
}
///
/// Event fired every to force requery;
///
public event VariableLayerCollectionRequeryHandler VariableLayerCollectionRequery;
///
/// Creates an instance of this class
///
/// Layer collection that holds layers with data sources updating frequently
public VariableLayerCollection(LayerCollection variableLayers)
{
AddCollection(variableLayers);
//_variableLayers = variableLayers;
//if (_handler == null)
//{
// //_timer = new Timer();
// //_timer.Interval = 500;
// //_timer.Elapsed += new ElapsedEventHandler(TimerElapsed);
//}
}
private void TimerElapsed(object sender, ElapsedEventArgs e)
{
OnRequery(null);
}
///
protected override void InsertItem(int index, ILayer layer)
{
if (layer == null)
throw new ArgumentNullException("layer", "The passed argument is null or not an ILayer");
lock (((ICollection)this).SyncRoot)
{
TestLayerPresent(this, layer);
base.InsertItem(index, layer);
}
}
/*
protected override void OnAddingNew(System.ComponentModel.AddingNewEventArgs e)
{
ILayer newLayer = (e.NewObject as ILayer);
if (newLayer == null) throw new ArgumentNullException("value", "The passed argument is null or not an ILayer");
TestLayerPresent(_variableLayers, newLayer);
base.OnAddingNew(e);
}
*/
private static void TestLayerPresent(IEnumerable layers, ILayer newLayer)
{
foreach (var layer in layers)
{
var comparison = String.Compare(layer.LayerName,
newLayer.LayerName, StringComparison.CurrentCultureIgnoreCase);
if (comparison == 0) throw new DuplicateLayerException(newLayer.LayerName);
}
}
private void OnRequery(object obj)
{
// if pan/zoom operation in progress then retry on next _timer.Elapsed
if (Pause) return;
// check for race condition when timer has been stopped while event has just been submitted on threadpool.QueueUserWorkItem
//if (!_timer.Enabled) return;
if (_isQuerying) return;
//_timer.Stop();
_isQuerying = true;
VariableLayerCollectionRequery?.Invoke(this, EventArgs.Empty);
_isQuerying = false;
}
///
/// Gets/sets the interval in which to update layers
///
public double Interval
{
get
{
return 0;//_timer.Interval;
}
set
{
// map sets Interval == 0 when disposing, to prevent race condition
/*
if (value <= 0)
_timer.Stop();
else
_timer.Interval = value;
*/
}
}
///
/// Gets/Sets whether this collection should currently be updated or not
///
public bool Pause
{
get { return _pause; }
set { _pause = value; }
}
}
}