// COPYRIGHT (C) Tom. ALL RIGHTS RESERVED. // THE AntdUI PROJECT IS AN WINFORM LIBRARY LICENSED UNDER THE Apache-2.0 License. // LICENSED UNDER THE Apache License, VERSION 2.0 (THE "License") // YOU MAY NOT USE THIS FILE EXCEPT IN COMPLIANCE WITH THE License. // YOU MAY OBTAIN A COPY OF THE LICENSE AT // // http://www.apache.org/licenses/LICENSE-2.0 // // UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE // DISTRIBUTED UNDER THE LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. // SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING PERMISSIONS AND // LIMITATIONS UNDER THE License. // GITEE: https://gitee.com/antdui/AntdUI // GITHUB: https://github.com/AntdUI/AntdUI // CSDN: https://blog.csdn.net/v_132 // QQ: 17379620 using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; namespace AntdUI { public class iCollection : IList, IList { #region 刷新UI public Action? action; public Action? action_add, action_del; void PropertyChanged(T value) { if (value is NotifyProperty notify) { notify.PropertyChanged += (a, b) => { action?.Invoke(false); }; } } #endregion List list; public iCollection() { list = new List(); } public iCollection(int capacity) { list = new List(capacity); } public iCollection(IEnumerable collection) { list = new List(collection); } public T this[int index] { get => list[index]; set { if (action_add == null && action_del == null) list[index] = value; else { action_del?.Invoke(list[index]); list[index] = value; action_add?.Invoke(value); } PropertyChanged(value); } } object? IList.this[int index] { get => list[index]; set { if (value is T item) { if (action_add == null && action_del == null) list[index] = item; else { action_del?.Invoke(list[index]); list[index] = item; action_add?.Invoke(item); } PropertyChanged(item); } } } #region 原生 #region 列表 public IEnumerator GetEnumerator() { for (int i = 0; i < list.Count; i++) yield return list[i]; } IEnumerator IEnumerable.GetEnumerator() { for (int i = 0; i < list.Count; i++) yield return list[i]; } public T[] ToArray() => list.ToArray(); public void ForEach(Action action) => list.ForEach(action); public bool TrueForAll(Predicate match) => list.TrueForAll(match); #endregion public int Count => list.Count; public bool IsReadOnly => false; public bool IsFixedSize => false; public bool IsSynchronized => true; public object SyncRoot => this; #region 添加 public void Add(T item) { list.Add(item); PropertyChanged(item); action_add?.Invoke(item); action?.Invoke(true); } public int Add(object? value) { if (value is T item) { list.Add(item); PropertyChanged(item); action_add?.Invoke(item); action?.Invoke(true); } return list.Count; } public void AddRange(IEnumerable collection) { list.AddRange(collection); foreach (var item in collection) { PropertyChanged(item); action_add?.Invoke(item); } action?.Invoke(true); } public void Insert(int index, T item) { list.Insert(index, item); PropertyChanged(item); action_add?.Invoke(item); action?.Invoke(true); } public void Insert(int index, object? value) { if (value is T item) { list.Insert(index, item); action_add?.Invoke(item); } } public void InsertRange(int index, IEnumerable collection) { list.InsertRange(index, collection); foreach (var item in collection) { PropertyChanged(item); action_add?.Invoke(item); } action?.Invoke(true); } #endregion #region 判断/查找 public bool Contains(T item) => list.Contains(item); public bool Contains(object? value) { if (value is T item) return list.Contains(item); return false; } public int IndexOf(object? value) { if (value is T item) return list.IndexOf(item); return -1; } public int IndexOf(T item) => list.IndexOf(item); public int IndexOf(T item, int index) => list.IndexOf(item, index); public int IndexOf(T item, int index, int count) => list.IndexOf(item, index, count); public int LastIndexOf(T item) => list.LastIndexOf(item); public int LastIndexOf(T item, int index) => list.LastIndexOf(item, index); public int LastIndexOf(T item, int index, int count) => list.LastIndexOf(item, index, count); public bool Exists(Predicate match) => list.Exists(match); public T? Find(Predicate match) => list.Find(match); public List FindAll(Predicate match) => list.FindAll(match); public int FindIndex(Predicate match) => list.FindIndex(match); public int FindIndex(int startIndex, Predicate match) => list.FindIndex(startIndex, match); public int FindIndex(int startIndex, int count, Predicate match) => list.FindIndex(startIndex, count, match); public T? FindLast(Predicate match) => list.FindLast(match); public int FindLastIndex(Predicate match) => list.FindLastIndex(match); public int FindLastIndex(int startIndex, Predicate match) => list.FindLastIndex(startIndex, match); public int FindLastIndex(int startIndex, int count, Predicate match) => list.FindLastIndex(startIndex, count, match); public List GetRange(int index, int count) => list.GetRange(index, count); #endregion #region 删除 public void Clear() { if (action_del != null) { foreach (var item in list) action_del?.Invoke(item); } list.Clear(); action?.Invoke(true); } public void Remove(object? value) { if (value is T item) { list.Remove(item); action_del?.Invoke(item); action?.Invoke(true); } } public bool Remove(T item) { bool flag = list.Remove(item); if (flag) { action_del?.Invoke(item); action?.Invoke(true); } return flag; } public void RemoveAt(int index) { if (action_del != null) { try { action_del?.Invoke(list[index]); } catch { } } list.RemoveAt(index); action?.Invoke(true); } public int RemoveAll(Predicate match) { int i = list.RemoveAll(match); action?.Invoke(true); return i; } public void RemoveRange(int index, int count) { list.RemoveRange(index, count); action?.Invoke(true); } #endregion public void Reverse() => list.Reverse(); public void Reverse(int index, int count) => list.Reverse(index, count); public void Sort() => list.Sort(); public void Sort(IComparer comparer) => list.Sort(comparer); public void Sort(Comparison comparison) => list.Sort(comparison); public void Sort(int index, int count, IComparer comparer) => list.Sort(index, count, comparer); public void CopyTo(T[] array) => list.CopyTo(array); public void CopyTo(T[] array, int arrayIndex) => list.CopyTo(array, arrayIndex); public void CopyTo(int index, T[] array, int arrayIndex, int count) => list.CopyTo(index, array, arrayIndex, count); public int BinarySearch(T item) => list.BinarySearch(item); public int BinarySearch(T item, IComparer comparer) => list.BinarySearch(item, comparer); public int BinarySearch(int index, int count, T item, IComparer comparer) => list.BinarySearch(index, count, item, comparer); public void CopyTo(Array array, int index) { //list.CopyTo(array, index); } #endregion } public class BaseCollection : IList { public Action? action; void PropertyChanged(object value) { if (value is NotifyProperty notify) { notify.PropertyChanged += (a, b) => { action?.Invoke(false); }; } } public virtual object? this[int index] { get => get(index); set => set(index, value); } object? get(int index) { if (list == null || index < 0 || index >= count) return default; return list[index]; } void set(int index, object? value) { if (value == null || list == null || index < 0 || index >= count) return; list[index] = value; PropertyChanged(value); } public int Add(object? value) { if (value == null) return -1; EnsureSpace(1)[count++] = value; PropertyChanged(value); action?.Invoke(true); return IndexOf(value); } public void AddRange(object[] items) { var m_arrItem = EnsureSpace(items.Length); foreach (var item in items) { m_arrItem[count++] = item; PropertyChanged(item); } action?.Invoke(true); } public void AddRange(IList items) { var m_arrItem = EnsureSpace(items.Count); foreach (var item in items) { m_arrItem[count++] = item; PropertyChanged(item); } action?.Invoke(true); } public void Clear() { count = 0; list = null; action?.Invoke(true); } public bool Contains(object? value) { if (value == null) return false; return IndexOf(value) != -1; } public void CopyTo(Array array, int index) { if (list == null) return; Array.Copy(list, 0, array, index, count); } public IEnumerator GetEnumerator() { for (int i = 0, Len = count; i < Len; i++) yield return list[i]; } public int IndexOf(object? value) { if (list == null || value == null) return -1; return Array.IndexOf(list, value); } public void Insert(int index, object? value) { if (value == null || index < 0 || index >= count) return; var m_arrItem = EnsureSpace(1); for (int i = count; i > index; i--) m_arrItem[i] = m_arrItem[i - 1]; m_arrItem[index] = value; count++; PropertyChanged(value); action?.Invoke(true); } public void Remove(object? value) { int index = IndexOf(value); if (index > -1) RemoveAt(index); } public void RemoveAt(int index) { if (list == null || index < 0 || index >= count) return; count--; for (int i = index, Len = count; i < Len; i++) list[i] = list[i + 1]; action?.Invoke(true); } #region 核心 object[]? list; object[] EnsureSpace(int elements) { if (list == null) list = new object[Math.Max(elements, 4)]; else if (count + elements > list.Length) { var arrTemp = new object[Math.Max(count + elements, list.Length * 2)]; list.CopyTo(arrTemp, 0); list = arrTemp; } return list; } public bool IsFixedSize => false; public bool IsReadOnly => false; public int Count => count; public bool IsSynchronized => true; public object SyncRoot => this; int count = 0; #endregion } public class AntList : IList { public AntList() { } public AntList(int capacity) { EnsureSpace(capacity); } public AntList(IList collection) { EnsureSpace(collection.Count); AddRange(collection); } #region 通知 public Action? action; #endregion public T this[int index] { get { if (list == null || index < 0 || index >= count) throw new Exception("Null List"); return list[index]; } set { if (value == null || list == null || index < 0 || index >= count) return; list[index] = value; action?.Invoke("edit", index); } } #region 添加 public void Add(T item) { if (item == null) return; int index = count++; EnsureSpace(1)[index] = item; action?.Invoke("add", index); } public void AddRange(T[] items) { var m_arrItem = EnsureSpace(items.Length); var list = new List(items.Length); foreach (var item in items) { int index = count++; list.Add(index); m_arrItem[index] = item; } action?.Invoke("add", list.ToArray()); } public void AddRange(IList items) { var m_arrItem = EnsureSpace(items.Count); var list = new List(items.Count); foreach (var item in items) { int index = count++; list.Add(index); m_arrItem[index] = item; } action?.Invoke("add", list.ToArray()); } #endregion public void Clear() { count = 0; list = null; action?.Invoke("del", "all"); } public bool Contains(T item) { if (item == null) return false; return IndexOf(item) != -1; } public void CopyTo(T[] array, int index) { if (list == null) return; Array.Copy(list, 0, array, index, count); } public int IndexOf(T item) { if (list == null || item == null) return -1; return Array.IndexOf(list, item); } public void Insert(int index, T item) { if (item == null || index < 0 || (index >= count && count > 0)) return; var m_arrItem = EnsureSpace(1); for (int i = count; i > index; i--) m_arrItem[i] = m_arrItem[i - 1]; m_arrItem[index] = item; count++; action?.Invoke("add", index); } public bool Remove(T item) { int index = IndexOf(item); if (index > -1) { RemoveAt(index); return true; } return false; } public void RemoveAt(int index) { if (list == null || index < 0 || index >= count) return; count--; for (int i = index, Len = count; i < Len; i++) list[i] = list[i + 1]; action?.Invoke("del", index); } public IEnumerator GetEnumerator() { for (int i = 0, Len = count; i < Len; i++) yield return list[i]; } IEnumerator IEnumerable.GetEnumerator() { for (int i = 0, Len = count; i < Len; i++) yield return list[i]; } public int Count => count; public bool IsReadOnly => false; #region 核心 int count = 0; T[]? list; T[] EnsureSpace(int elements) { if (list == null) list = new T[Math.Max(elements, 4)]; else if (count + elements > list.Length) { var arrTemp = new T[Math.Max(count + elements, list.Length * 2)]; list.CopyTo(arrTemp, 0); list = arrTemp; } return list; } #endregion } public class AntItem : NotifyProperty { public AntItem(string k) { key = k; } public AntItem(string k, object? v) { key = k; value = v; } public string key { get; set; } object? _value = null; public object? value { get => _value; set { if (_value == value) return; _value = value; OnPropertyChanged(key); } } public bool Try(out T val) { if (_value is T v) { val = v; return true; } val = default; return false; } } public class NotifyProperty : INotifyPropertyChanged { public event PropertyChangedEventHandler? PropertyChanged; #if NET40 public void OnPropertyChanged(string propertyName) #else public void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string? propertyName = null) #endif { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }