kopia lustrzana https://github.com/dl2alf/AirScout
542 wiersze
17 KiB
C#
542 wiersze
17 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.ComponentModel;
|
|
|
|
namespace GMap.NET.ObjectModel
|
|
{
|
|
public delegate void NotifyCollectionChangedEventHandler(object sender, NotifyCollectionChangedEventArgs e);
|
|
|
|
public interface INotifyCollectionChanged
|
|
{
|
|
// Events
|
|
event NotifyCollectionChangedEventHandler CollectionChanged;
|
|
}
|
|
|
|
public interface INotifyPropertyChanged
|
|
{
|
|
// Events
|
|
event PropertyChangedEventHandler PropertyChanged;
|
|
}
|
|
|
|
public enum NotifyCollectionChangedAction
|
|
{
|
|
Add,
|
|
Remove,
|
|
Replace,
|
|
Move,
|
|
Reset
|
|
}
|
|
|
|
public class NotifyCollectionChangedEventArgs : EventArgs
|
|
{
|
|
// Fields
|
|
private NotifyCollectionChangedAction _action;
|
|
private IList _newItems;
|
|
private int _newStartingIndex;
|
|
private IList _oldItems;
|
|
private int _oldStartingIndex;
|
|
|
|
// Methods
|
|
public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action)
|
|
{
|
|
this._newStartingIndex = -1;
|
|
this._oldStartingIndex = -1;
|
|
if(action != NotifyCollectionChangedAction.Reset)
|
|
{
|
|
throw new ArgumentException("WrongActionForCtor", "action");
|
|
}
|
|
this.InitializeAdd(action, null, -1);
|
|
}
|
|
|
|
public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList changedItems)
|
|
{
|
|
this._newStartingIndex = -1;
|
|
this._oldStartingIndex = -1;
|
|
if(((action != NotifyCollectionChangedAction.Add) && (action != NotifyCollectionChangedAction.Remove)) && (action != NotifyCollectionChangedAction.Reset))
|
|
{
|
|
throw new ArgumentException("MustBeResetAddOrRemoveActionForCtor", "action");
|
|
}
|
|
if(action == NotifyCollectionChangedAction.Reset)
|
|
{
|
|
if(changedItems != null)
|
|
{
|
|
throw new ArgumentException("ResetActionRequiresNullItem", "action");
|
|
}
|
|
this.InitializeAdd(action, null, -1);
|
|
}
|
|
else
|
|
{
|
|
if(changedItems == null)
|
|
{
|
|
throw new ArgumentNullException("changedItems");
|
|
}
|
|
this.InitializeAddOrRemove(action, changedItems, -1);
|
|
}
|
|
}
|
|
|
|
public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object changedItem)
|
|
{
|
|
this._newStartingIndex = -1;
|
|
this._oldStartingIndex = -1;
|
|
if(((action != NotifyCollectionChangedAction.Add) && (action != NotifyCollectionChangedAction.Remove)) && (action != NotifyCollectionChangedAction.Reset))
|
|
{
|
|
throw new ArgumentException("MustBeResetAddOrRemoveActionForCtor", "action");
|
|
}
|
|
if(action == NotifyCollectionChangedAction.Reset)
|
|
{
|
|
if(changedItem != null)
|
|
{
|
|
throw new ArgumentException("ResetActionRequiresNullItem", "action");
|
|
}
|
|
this.InitializeAdd(action, null, -1);
|
|
}
|
|
else
|
|
{
|
|
this.InitializeAddOrRemove(action, new object[] { changedItem }, -1);
|
|
}
|
|
}
|
|
|
|
public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList newItems, IList oldItems)
|
|
{
|
|
this._newStartingIndex = -1;
|
|
this._oldStartingIndex = -1;
|
|
if(action != NotifyCollectionChangedAction.Replace)
|
|
{
|
|
throw new ArgumentException("WrongActionForCtor", "action");
|
|
}
|
|
if(newItems == null)
|
|
{
|
|
throw new ArgumentNullException("newItems");
|
|
}
|
|
if(oldItems == null)
|
|
{
|
|
throw new ArgumentNullException("oldItems");
|
|
}
|
|
this.InitializeMoveOrReplace(action, newItems, oldItems, -1, -1);
|
|
}
|
|
|
|
public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList changedItems, int startingIndex)
|
|
{
|
|
this._newStartingIndex = -1;
|
|
this._oldStartingIndex = -1;
|
|
if(((action != NotifyCollectionChangedAction.Add) && (action != NotifyCollectionChangedAction.Remove)) && (action != NotifyCollectionChangedAction.Reset))
|
|
{
|
|
throw new ArgumentException("MustBeResetAddOrRemoveActionForCtor", "action");
|
|
}
|
|
if(action == NotifyCollectionChangedAction.Reset)
|
|
{
|
|
if(changedItems != null)
|
|
{
|
|
throw new ArgumentException("ResetActionRequiresNullItem", "action");
|
|
}
|
|
if(startingIndex != -1)
|
|
{
|
|
throw new ArgumentException("ResetActionRequiresIndexMinus1", "action");
|
|
}
|
|
this.InitializeAdd(action, null, -1);
|
|
}
|
|
else
|
|
{
|
|
if(changedItems == null)
|
|
{
|
|
throw new ArgumentNullException("changedItems");
|
|
}
|
|
if(startingIndex < -1)
|
|
{
|
|
throw new ArgumentException("IndexCannotBeNegative", "startingIndex");
|
|
}
|
|
this.InitializeAddOrRemove(action, changedItems, startingIndex);
|
|
}
|
|
}
|
|
|
|
public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object changedItem, int index)
|
|
{
|
|
this._newStartingIndex = -1;
|
|
this._oldStartingIndex = -1;
|
|
if(((action != NotifyCollectionChangedAction.Add) && (action != NotifyCollectionChangedAction.Remove)) && (action != NotifyCollectionChangedAction.Reset))
|
|
{
|
|
throw new ArgumentException("MustBeResetAddOrRemoveActionForCtor", "action");
|
|
}
|
|
if(action == NotifyCollectionChangedAction.Reset)
|
|
{
|
|
if(changedItem != null)
|
|
{
|
|
throw new ArgumentException("ResetActionRequiresNullItem", "action");
|
|
}
|
|
if(index != -1)
|
|
{
|
|
throw new ArgumentException("ResetActionRequiresIndexMinus1", "action");
|
|
}
|
|
this.InitializeAdd(action, null, -1);
|
|
}
|
|
else
|
|
{
|
|
this.InitializeAddOrRemove(action, new object[] { changedItem }, index);
|
|
}
|
|
}
|
|
|
|
public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object newItem, object oldItem)
|
|
{
|
|
this._newStartingIndex = -1;
|
|
this._oldStartingIndex = -1;
|
|
if(action != NotifyCollectionChangedAction.Replace)
|
|
{
|
|
throw new ArgumentException("WrongActionForCtor", "action");
|
|
}
|
|
this.InitializeMoveOrReplace(action, new object[] { newItem }, new object[] { oldItem }, -1, -1);
|
|
}
|
|
|
|
public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList newItems, IList oldItems, int startingIndex)
|
|
{
|
|
this._newStartingIndex = -1;
|
|
this._oldStartingIndex = -1;
|
|
if(action != NotifyCollectionChangedAction.Replace)
|
|
{
|
|
throw new ArgumentException("WrongActionForCtor", "action");
|
|
}
|
|
if(newItems == null)
|
|
{
|
|
throw new ArgumentNullException("newItems");
|
|
}
|
|
if(oldItems == null)
|
|
{
|
|
throw new ArgumentNullException("oldItems");
|
|
}
|
|
this.InitializeMoveOrReplace(action, newItems, oldItems, startingIndex, startingIndex);
|
|
}
|
|
|
|
public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList changedItems, int index, int oldIndex)
|
|
{
|
|
this._newStartingIndex = -1;
|
|
this._oldStartingIndex = -1;
|
|
if(action != NotifyCollectionChangedAction.Move)
|
|
{
|
|
throw new ArgumentException("WrongActionForCtor", "action");
|
|
}
|
|
if(index < 0)
|
|
{
|
|
throw new ArgumentException("IndexCannotBeNegative", "index");
|
|
}
|
|
this.InitializeMoveOrReplace(action, changedItems, changedItems, index, oldIndex);
|
|
}
|
|
|
|
public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object changedItem, int index, int oldIndex)
|
|
{
|
|
this._newStartingIndex = -1;
|
|
this._oldStartingIndex = -1;
|
|
if(action != NotifyCollectionChangedAction.Move)
|
|
{
|
|
throw new ArgumentException("WrongActionForCtor", "action");
|
|
}
|
|
if(index < 0)
|
|
{
|
|
throw new ArgumentException("IndexCannotBeNegative", "index");
|
|
}
|
|
object[] newItems = new object[] { changedItem };
|
|
this.InitializeMoveOrReplace(action, newItems, newItems, index, oldIndex);
|
|
}
|
|
|
|
public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object newItem, object oldItem, int index)
|
|
{
|
|
this._newStartingIndex = -1;
|
|
this._oldStartingIndex = -1;
|
|
if(action != NotifyCollectionChangedAction.Replace)
|
|
{
|
|
throw new ArgumentException("WrongActionForCtor", "action");
|
|
}
|
|
this.InitializeMoveOrReplace(action, new object[] { newItem }, new object[] { oldItem }, index, index);
|
|
}
|
|
|
|
private void InitializeAdd(NotifyCollectionChangedAction action, IList newItems, int newStartingIndex)
|
|
{
|
|
this._action = action;
|
|
#if !PocketPC
|
|
this._newItems = (newItems == null) ? null : ArrayList.ReadOnly(newItems);
|
|
#else
|
|
this._newItems = (newItems == null) ? null : newItems;
|
|
#endif
|
|
this._newStartingIndex = newStartingIndex;
|
|
}
|
|
|
|
private void InitializeAddOrRemove(NotifyCollectionChangedAction action, IList changedItems, int startingIndex)
|
|
{
|
|
if(action == NotifyCollectionChangedAction.Add)
|
|
{
|
|
this.InitializeAdd(action, changedItems, startingIndex);
|
|
}
|
|
else if(action == NotifyCollectionChangedAction.Remove)
|
|
{
|
|
this.InitializeRemove(action, changedItems, startingIndex);
|
|
}
|
|
else
|
|
{
|
|
throw new ArgumentException(string.Format("InvariantFailure, Unsupported action: {0}", action.ToString()));
|
|
}
|
|
}
|
|
|
|
private void InitializeMoveOrReplace(NotifyCollectionChangedAction action, IList newItems, IList oldItems, int startingIndex, int oldStartingIndex)
|
|
{
|
|
this.InitializeAdd(action, newItems, startingIndex);
|
|
this.InitializeRemove(action, oldItems, oldStartingIndex);
|
|
}
|
|
|
|
private void InitializeRemove(NotifyCollectionChangedAction action, IList oldItems, int oldStartingIndex)
|
|
{
|
|
this._action = action;
|
|
#if !PocketPC
|
|
this._oldItems = (oldItems == null) ? null : ArrayList.ReadOnly(oldItems);
|
|
#else
|
|
this._oldItems = (oldItems == null) ? null : oldItems;
|
|
#endif
|
|
this._oldStartingIndex = oldStartingIndex;
|
|
}
|
|
|
|
// Properties
|
|
public NotifyCollectionChangedAction Action
|
|
{
|
|
get
|
|
{
|
|
return this._action;
|
|
}
|
|
}
|
|
|
|
public IList NewItems
|
|
{
|
|
get
|
|
{
|
|
return this._newItems;
|
|
}
|
|
}
|
|
|
|
public int NewStartingIndex
|
|
{
|
|
get
|
|
{
|
|
return this._newStartingIndex;
|
|
}
|
|
}
|
|
|
|
public IList OldItems
|
|
{
|
|
get
|
|
{
|
|
return this._oldItems;
|
|
}
|
|
}
|
|
|
|
public int OldStartingIndex
|
|
{
|
|
get
|
|
{
|
|
return this._oldStartingIndex;
|
|
}
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public class ObservableCollection<T> : Collection<T>, INotifyCollectionChanged, INotifyPropertyChanged
|
|
{
|
|
// Fields
|
|
private SimpleMonitor _monitor;
|
|
private const string CountString = "Count";
|
|
private const string IndexerName = "Item[]";
|
|
|
|
// Events
|
|
[field: NonSerialized]
|
|
public virtual event NotifyCollectionChangedEventHandler CollectionChanged;
|
|
|
|
[field: NonSerialized]
|
|
protected event PropertyChangedEventHandler PropertyChanged;
|
|
|
|
event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
|
|
{
|
|
add
|
|
{
|
|
PropertyChanged += value;
|
|
}
|
|
remove
|
|
{
|
|
PropertyChanged -= value;
|
|
}
|
|
}
|
|
|
|
// Methods
|
|
public ObservableCollection()
|
|
{
|
|
this._monitor = new SimpleMonitor();
|
|
}
|
|
|
|
public ObservableCollection(IEnumerable<T> collection)
|
|
{
|
|
this._monitor = new SimpleMonitor();
|
|
if(collection == null)
|
|
{
|
|
throw new ArgumentNullException("collection");
|
|
}
|
|
this.CopyFrom(collection);
|
|
}
|
|
|
|
public ObservableCollection(List<T> list)
|
|
: base((list != null) ? new List<T>(list.Count) : list)
|
|
{
|
|
this._monitor = new SimpleMonitor();
|
|
this.CopyFrom(list);
|
|
}
|
|
|
|
protected IDisposable BlockReentrancy()
|
|
{
|
|
this._monitor.Enter();
|
|
return this._monitor;
|
|
}
|
|
|
|
protected void CheckReentrancy()
|
|
{
|
|
if((this._monitor.Busy && (this.CollectionChanged != null)) && (this.CollectionChanged.GetInvocationList().Length > 1))
|
|
{
|
|
throw new InvalidOperationException("ObservableCollectionReentrancyNotAllowed");
|
|
}
|
|
}
|
|
|
|
protected override void ClearItems()
|
|
{
|
|
this.CheckReentrancy();
|
|
base.ClearItems();
|
|
this.OnPropertyChanged(CountString);
|
|
this.OnPropertyChanged(IndexerName);
|
|
this.OnCollectionReset();
|
|
}
|
|
|
|
private void CopyFrom(IEnumerable<T> collection)
|
|
{
|
|
IList<T> items = base.Items;
|
|
if((collection != null) && (items != null))
|
|
{
|
|
using(IEnumerator<T> enumerator = collection.GetEnumerator())
|
|
{
|
|
while(enumerator.MoveNext())
|
|
{
|
|
items.Add(enumerator.Current);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override void InsertItem(int index, T item)
|
|
{
|
|
this.CheckReentrancy();
|
|
base.InsertItem(index, item);
|
|
this.OnPropertyChanged(CountString);
|
|
this.OnPropertyChanged(IndexerName);
|
|
this.OnCollectionChanged(NotifyCollectionChangedAction.Add, item, index);
|
|
}
|
|
|
|
public void Move(int oldIndex, int newIndex)
|
|
{
|
|
this.MoveItem(oldIndex, newIndex);
|
|
}
|
|
|
|
protected virtual void MoveItem(int oldIndex, int newIndex)
|
|
{
|
|
this.CheckReentrancy();
|
|
T item = base[oldIndex];
|
|
base.RemoveItem(oldIndex);
|
|
base.InsertItem(newIndex, item);
|
|
this.OnPropertyChanged(IndexerName);
|
|
this.OnCollectionChanged(NotifyCollectionChangedAction.Move, item, newIndex, oldIndex);
|
|
}
|
|
|
|
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
|
|
{
|
|
if(this.CollectionChanged != null)
|
|
{
|
|
using(this.BlockReentrancy())
|
|
{
|
|
this.CollectionChanged(this, e);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnCollectionChanged(NotifyCollectionChangedAction action, object item, int index)
|
|
{
|
|
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index));
|
|
}
|
|
|
|
private void OnCollectionChanged(NotifyCollectionChangedAction action, object item, int index, int oldIndex)
|
|
{
|
|
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index, oldIndex));
|
|
}
|
|
|
|
private void OnCollectionChanged(NotifyCollectionChangedAction action, object oldItem, object newItem, int index)
|
|
{
|
|
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, newItem, oldItem, index));
|
|
}
|
|
|
|
private void OnCollectionReset()
|
|
{
|
|
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
|
}
|
|
|
|
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
|
|
{
|
|
if(this.PropertyChanged != null)
|
|
{
|
|
this.PropertyChanged(this, e);
|
|
}
|
|
}
|
|
|
|
private void OnPropertyChanged(string propertyName)
|
|
{
|
|
this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
|
|
}
|
|
|
|
protected override void RemoveItem(int index)
|
|
{
|
|
this.CheckReentrancy();
|
|
T item = base[index];
|
|
base.RemoveItem(index);
|
|
this.OnPropertyChanged(CountString);
|
|
this.OnPropertyChanged(IndexerName);
|
|
this.OnCollectionChanged(NotifyCollectionChangedAction.Remove, item, index);
|
|
}
|
|
|
|
protected override void SetItem(int index, T item)
|
|
{
|
|
this.CheckReentrancy();
|
|
T oldItem = base[index];
|
|
base.SetItem(index, item);
|
|
this.OnPropertyChanged(IndexerName);
|
|
this.OnCollectionChanged(NotifyCollectionChangedAction.Replace, oldItem, item, index);
|
|
}
|
|
|
|
// Nested Types
|
|
[Serializable]
|
|
private class SimpleMonitor : IDisposable
|
|
{
|
|
// Fields
|
|
private int _busyCount;
|
|
|
|
// Methods
|
|
public void Dispose()
|
|
{
|
|
this._busyCount--;
|
|
}
|
|
|
|
public void Enter()
|
|
{
|
|
this._busyCount++;
|
|
}
|
|
|
|
// Properties
|
|
public bool Busy
|
|
{
|
|
get
|
|
{
|
|
return (this._busyCount > 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|