adjusted project structure

This commit is contained in:
NaBian committed 2021-09-05 13:26:48 +08:00
1 parent aa7310d495
commit 904b32f986
18 files changed
+79 -212

No files matched your search

@@ -1,15 +0,0 @@
using System.Collections.Generic;
using HandyControl.Data;
namespace HandyControl.Collections
{
public class DateTimeRangeComparer : IComparer<DateTimeRange>
{
public int Compare(DateTimeRange x, DateTimeRange y)
{
if (x.Start > y.Start && x.End > y.End) return 1;
if (x.Start < y.Start && x.End < y.End) return -1;
return 0;
}
}
}
@@ -1,191 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
namespace HandyControl.Collections
{
[Serializable]
public class ManualObservableCollection<T> : Collection<T>, INotifyCollectionChanged, INotifyPropertyChanged
{
private readonly SimpleMonitor _monitor = new();
private const string CountString = "Count";
private const string IndexerName = "Item[]";
private bool _canNotify = true;
public bool CanNotify
{
get => _canNotify;
set
{
_canNotify = value;
if (value)
{
if (_oldCount != Count)
{
OnPropertyChanged(CountString);
}
OnPropertyChanged(IndexerName);
OnCollectionReset();
}
else
{
_oldCount = Count;
}
}
}
private int _oldCount;
public event NotifyCollectionChangedEventHandler CollectionChanged;
public event PropertyChangedEventHandler PropertyChanged;
public ManualObservableCollection()
{
}
// ReSharper disable once AssignNullToNotNullAttribute
public ManualObservableCollection(List<T> list) : base(list != null ? new List<T>(list.Count) : list) => CopyFrom(list);
public ManualObservableCollection(IEnumerable<T> collection)
{
if (collection == null) throw new ArgumentNullException(nameof(collection));
CopyFrom(collection);
}
private void CopyFrom(IEnumerable<T> collection)
{
var items = Items;
if (collection != null)
{
using var enumerator = collection.GetEnumerator();
while (enumerator.MoveNext())
{
items.Add(enumerator.Current);
}
}
}
public void Move(int oldIndex, int newIndex) => MoveItem(oldIndex, newIndex);
protected override void ClearItems()
{
CheckReentrancy();
base.ClearItems();
OnPropertyChanged(CountString);
OnPropertyChanged(IndexerName);
OnCollectionReset();
}
protected override void RemoveItem(int index)
{
CheckReentrancy();
var removedItem = this[index];
base.RemoveItem(index);
OnPropertyChanged(CountString);
OnPropertyChanged(IndexerName);
OnCollectionChanged(NotifyCollectionChangedAction.Remove, removedItem, index);
}
protected override void InsertItem(int index, T item)
{
CheckReentrancy();
base.InsertItem(index, item);
OnPropertyChanged(CountString);
OnPropertyChanged(IndexerName);
OnCollectionChanged(NotifyCollectionChangedAction.Add, item, index);
}
protected override void SetItem(int index, T item)
{
CheckReentrancy();
var originalItem = this[index];
base.SetItem(index, item);
OnPropertyChanged(IndexerName);
OnCollectionChanged(NotifyCollectionChangedAction.Replace, originalItem, item, index);
}
protected virtual void MoveItem(int oldIndex, int newIndex)
{
CheckReentrancy();
var removedItem = this[oldIndex];
base.RemoveItem(oldIndex);
base.InsertItem(newIndex, removedItem);
OnPropertyChanged(IndexerName);
OnCollectionChanged(NotifyCollectionChangedAction.Move, removedItem, newIndex, oldIndex);
}
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (!CanNotify || PropertyChanged == null) return;
PropertyChanged.Invoke(this, e);
}
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (!CanNotify || CollectionChanged == null) return;
using (BlockReentrancy())
{
// ReSharper disable once PossibleNullReferenceException
CollectionChanged(this, e);
}
}
protected IDisposable BlockReentrancy()
{
_monitor.Enter();
return _monitor;
}
protected void CheckReentrancy()
{
if (_monitor.Busy && CollectionChanged != null && CollectionChanged.GetInvocationList().Length > 1)
{
throw new InvalidOperationException("ObservableCollectionReentrancyNotAllowed");
}
}
private void OnPropertyChanged(string propertyName) =>
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
private void OnCollectionChanged(NotifyCollectionChangedAction action, object item, int index) =>
OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index));
private void OnCollectionChanged(NotifyCollectionChangedAction action, object item, int index, int oldIndex) =>
OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index, oldIndex));
private void OnCollectionChanged(NotifyCollectionChangedAction action, object oldItem, object newItem, int index) =>
OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, newItem, oldItem, index));
private void OnCollectionReset() =>
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
private class SimpleMonitor : IDisposable
{
public void Enter() => ++_busyCount;
public void Dispose() => --_busyCount;
public bool Busy => _busyCount > 0;
private int _busyCount;
}
}
}
@@ -0,0 +1,58 @@
using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
namespace HandyControl.Collections
{
[Serializable]
public class ManualObservableCollection<T> : ObservableCollection<T>
{
private const string CountString = "Count";
private const string IndexerName = "Item[]";
private int _oldCount;
private bool _canNotify = true;
public bool CanNotify
{
get => _canNotify;
set
{
_canNotify = value;
if (value)
{
if (_oldCount != Count)
{
OnPropertyChanged(new PropertyChangedEventArgs(CountString));
}
OnPropertyChanged(new PropertyChangedEventArgs(IndexerName));
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
else
{
_oldCount = Count;
}
}
}
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (!CanNotify) return;
base.OnPropertyChanged(e);
}
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (!CanNotify) return;
base.OnCollectionChanged(e);
}
}
}
@@ -0,0 +1,9 @@
namespace HandyControl.Collections
{
public interface IPool<T>
{
T Acquire();
bool Release(T instance);
}
}
@@ -0,0 +1,64 @@
//adapted from https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/util/Pools.java
using System;
namespace HandyControl.Collections
{
public class SimplePool<T> : IPool<T>
{
private readonly object[] _pool;
private int _poolSize;
public SimplePool(int maxPoolSize)
{
if (maxPoolSize <= 0)
{
throw new ArgumentException("The max pool size must be > 0");
}
_pool = new object[maxPoolSize];
}
public virtual T Acquire()
{
if (_poolSize > 0)
{
var lastPooledIndex = _poolSize - 1;
var instance = (T) _pool[lastPooledIndex];
_pool[lastPooledIndex] = null;
_poolSize--;
return instance;
}
return default;
}
public virtual bool Release(T instance)
{
if (IsInPool(instance))
{
throw new Exception("Already in the pool!");
}
if (_poolSize < _pool.Length)
{
_pool[_poolSize] = instance;
_poolSize++;
return true;
}
return false;
}
private bool IsInPool(T instance)
{
for (var i = 0; i < _poolSize; i++)
{
if (Equals(_pool[i], instance))
{
return true;
}
}
return false;
}
}
}
@@ -0,0 +1,28 @@
namespace HandyControl.Collections
{
public class SynchronizedPool<T> : SimplePool<T>
{
private readonly object _lockObj = new();
public SynchronizedPool(int maxPoolSize) : base(maxPoolSize)
{
}
public override T Acquire()
{
lock (_lockObj)
{
return base.Acquire();
}
}
public override bool Release(T element)
{
lock (_lockObj)
{
return base.Release(element);
}
}
}
}
@@ -0,0 +1,336 @@
// adapted from https://www.c-sharpcorner.com/uploadfile/b942f9/implementing-a-double-ended-queue-or-deque-in-c-sharp/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
namespace HandyControl.Collections
{
[Serializable]
public class Deque<T> : IEnumerable<T>, ICollection
{
[NonSerialized]
private object _syncRoot;
private List<T> _front;
private List<T> _back;
private int _frontDeleted;
private int _backDeleted;
public int Capacity => _front.Capacity + _back.Capacity;
public int Count => _front.Count + _back.Count - _frontDeleted - _backDeleted;
public bool IsEmpty => Count == 0;
public IEnumerable<T> Reversed
{
get
{
if (_back.Count - _backDeleted > 0)
{
for (var i = _back.Count - 1; i >= _backDeleted; i--) yield return _back[i];
}
if (_front.Count - _frontDeleted > 0)
{
for (var i = _frontDeleted; i < _front.Count; i++) yield return _front[i];
}
}
}
public Deque()
{
_front = new List<T>();
_back = new List<T>();
}
public Deque(int capacity)
{
if (capacity < 0) throw new ArgumentException("Capacity cannot be negative");
var temp = capacity / 2;
var temp2 = capacity - temp;
_front = new List<T>(temp);
_back = new List<T>(temp2);
}
public Deque(IEnumerable<T> backCollection) : this(backCollection, null)
{
}
public Deque(IEnumerable<T> backCollection, IEnumerable<T> frontCollection)
{
if (backCollection == null && frontCollection == null) throw new ArgumentException("Collections cannot both be null");
_front = frontCollection != null ? new List<T>(frontCollection) : new List<T>();
_back = backCollection != null ? new List<T>(backCollection) : new List<T>();
}
public void AddFirst(T item)
{
if (_frontDeleted > 0 && _front.Count == _front.Capacity)
{
_front.RemoveRange(0, _frontDeleted);
_frontDeleted = 0;
}
_front.Add(item);
}
public void AddLast(T item)
{
if (_backDeleted > 0 && _back.Count == _back.Capacity)
{
_back.RemoveRange(0, _backDeleted);
_backDeleted = 0;
}
_back.Add(item);
}
public void AddRangeFirst(IEnumerable<T> range)
{
if (range == null) return;
foreach (var item in range) AddFirst(item);
}
public void AddRangeLast(IEnumerable<T> range)
{
if (range == null) return;
foreach (var item in range) AddLast(item);
}
public void Clear()
{
_front.Clear();
_back.Clear();
_frontDeleted = 0;
_backDeleted = 0;
}
public bool Contains(T item)
{
for (var i = _frontDeleted; i < _front.Count; i++)
{
if (Equals(_front[i], item)) return true;
}
for (var i = _backDeleted; i < _back.Count; i++)
{
if (Equals(_back[i], item)) return true;
}
return false;
}
public void CopyTo(T[] array, int index)
{
if (array == null) throw new ArgumentNullException("Array cannot be null");
if (index < 0) throw new ArgumentOutOfRangeException("Index cannot be negative");
if (array.Length < index + Count) throw new ArgumentException("Index is invalid");
var i = index;
foreach (var item in this)
{
array[i++] = item;
}
}
public IEnumerator<T> GetEnumerator()
{
if (_front.Count - _frontDeleted > 0)
{
for (var i = _front.Count - 1; i >= _frontDeleted; i--) yield return _front[i];
}
if (_back.Count - _backDeleted > 0)
{
for (var i = _backDeleted; i < _back.Count; i++) yield return _back[i];
}
}
public T PeekFirst()
{
if (_front.Count > _frontDeleted)
{
return _front[_front.Count - 1];
}
if (_back.Count > _backDeleted)
{
return _back[_backDeleted];
}
throw new InvalidOperationException("Can't peek at empty Deque");
}
public T PeekLast()
{
if (_back.Count > _backDeleted)
{
return _back[_back.Count - 1];
}
if (_front.Count > _frontDeleted)
{
return _front[_frontDeleted];
}
throw new InvalidOperationException("Can't peek at empty Deque");
}
public T PopFirst()
{
T result;
if (_front.Count > _frontDeleted)
{
result = _front[_front.Count - 1];
_front.RemoveAt(_front.Count - 1);
}
else if (_back.Count > _backDeleted)
{
result = _back[_backDeleted];
_backDeleted++;
}
else
{
throw new InvalidOperationException("Can't pop empty Deque");
}
return result;
}
public T PopLast()
{
T result;
if (_back.Count > _backDeleted)
{
result = _back[_back.Count - 1];
_back.RemoveAt(_back.Count - 1);
}
else if (_front.Count > _frontDeleted)
{
result = _front[_frontDeleted];
_frontDeleted++;
}
else
{
throw new InvalidOperationException("Can't pop empty Deque");
}
return result;
}
public void Reverse()
{
var temp = _front;
_front = _back;
_back = temp;
var temp2 = _frontDeleted;
_frontDeleted = _backDeleted;
_backDeleted = temp2;
}
public T[] ToArray()
{
if (Count == 0) return new T[0];
var result = new T[Count];
CopyTo(result, 0);
return result;
}
public void TrimExcess()
{
if (_frontDeleted > 0)
{
_front.RemoveRange(0, _frontDeleted);
_frontDeleted = 0;
}
if (_backDeleted > 0)
{
_back.RemoveRange(0, _backDeleted);
_backDeleted = 0;
}
_front.TrimExcess();
_back.TrimExcess();
}
public bool TryPeekFirst(out T item)
{
if (!IsEmpty)
{
item = PeekFirst();
return true;
}
item = default;
return false;
}
public bool TryPeekLast(out T item)
{
if (!IsEmpty)
{
item = PeekLast();
return true;
}
item = default;
return false;
}
public bool TryPopFirst(out T item)
{
if (!IsEmpty)
{
item = PopFirst();
return true;
}
item = default;
return false;
}
public bool TryPopLast(out T item)
{
if (!IsEmpty)
{
item = PopLast();
return true;
}
item = default;
return false;
}
bool ICollection.IsSynchronized => false;
object ICollection.SyncRoot
{
get
{
if (_syncRoot == null)
{
Interlocked.CompareExchange<object>(ref _syncRoot, new object(), null);
}
return _syncRoot;
}
}
void ICollection.CopyTo(Array array, int index) => CopyTo((T[]) array, index);
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}