mirror of
https://github.com/esiur/esiur-dart.git
synced 2026-04-03 17:58:21 +00:00
157 lines
3.4 KiB
Dart
157 lines
3.4 KiB
Dart
|
|
import '../Core/IEventHandler.dart';
|
|
|
|
import '../Core/IDestructible.dart';
|
|
import 'Codec.dart';
|
|
import 'dart:collection';
|
|
|
|
class AutoList<T, ST> extends IDestructible with IterableMixin<T> {
|
|
List<T> _list = <T>[];
|
|
|
|
ST? _state;
|
|
late bool _removableList;
|
|
|
|
void sort(int Function(T, T)? compare) {
|
|
_list.sort(compare);
|
|
}
|
|
|
|
Iterator<T> get iterator => _list.iterator;
|
|
|
|
/// <summary>
|
|
/// Convert AutoList to array
|
|
/// </summary>
|
|
/// <returns>Array</returns>
|
|
//List<T> toList()
|
|
//{
|
|
// list.OrderBy()
|
|
// return _list;
|
|
//}
|
|
|
|
/// Create a new instance of AutoList
|
|
/// <param name="state">State object to be included when an event is raised.</param>
|
|
AutoList([ST? state, List<T>? values]) {
|
|
this._state = state;
|
|
this._removableList = Codec.implementsInterface<T, IDestructible>();
|
|
|
|
if (values != null) addRange(values);
|
|
|
|
register("modified");
|
|
register("added");
|
|
register("removed");
|
|
register("cleared");
|
|
}
|
|
|
|
T operator [](int index) {
|
|
return _list[index];
|
|
}
|
|
|
|
void operator []=(int index, T value) {
|
|
var oldValue = _list[index];
|
|
|
|
if (_removableList) {
|
|
if (oldValue != null)
|
|
(oldValue as IDestructible).off("destroy", _itemDestroyed);
|
|
if (value != null) (value as IEventHandler).on("destroy", _itemDestroyed);
|
|
}
|
|
|
|
//lock (syncRoot)
|
|
_list[index] = value;
|
|
|
|
emitArgs("modified", [_state, index, oldValue, value]);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add item to the list
|
|
/// </summary>
|
|
void add(T value) {
|
|
if (_removableList) if (value != null)
|
|
(value as IDestructible).on("destroy", _itemDestroyed);
|
|
|
|
// lock (syncRoot)
|
|
_list.add(value);
|
|
|
|
emitArgs("add", [_state, value]);
|
|
}
|
|
|
|
|
|
// T? first(bool Function(T element) selector) {
|
|
// final res = _list.where(selector);
|
|
// return res.isEmpty ? null : res.first;
|
|
// }
|
|
|
|
/// <summary>
|
|
/// Add an array of items to the list
|
|
/// </summary>
|
|
void addRange(List<T> values) {
|
|
values.forEach((x) => add(x));
|
|
}
|
|
|
|
void _itemDestroyed(T sender) {
|
|
remove(sender);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clear the list
|
|
/// </summary>
|
|
void clear() {
|
|
if (_removableList)
|
|
_list.forEach((x) => (x as IDestructible).off("destroy", _itemDestroyed));
|
|
|
|
// lock (syncRoot)
|
|
_list.clear();
|
|
|
|
emitArgs("cleared", [_state]);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Remove an item from the list
|
|
/// <param name="value">Item to remove</param>
|
|
/// </summary>
|
|
void remove(T value) {
|
|
if (!_list.contains(value)) return;
|
|
|
|
if (_removableList) if (value != null)
|
|
(value as IDestructible).off("destroy", _itemDestroyed);
|
|
|
|
//lock (syncRoot)
|
|
_list.remove(value);
|
|
|
|
emitArgs("removed", [_state, value]);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Number of items in the list
|
|
/// </summary>
|
|
get count => _list.length;
|
|
get length => _list.length;
|
|
|
|
/// <summary>
|
|
/// Check if an item exists in the list
|
|
/// </summary>
|
|
/// <param name="value">Item to check if exists</param>
|
|
//contains(T value) => _list.contains(value);
|
|
|
|
/// <summary>
|
|
/// Check if any item of the given array is in the list
|
|
/// </summary>
|
|
/// <param name="values">Array of items</param>
|
|
bool containsAny(dynamic values) {
|
|
if (values is List<T>) {
|
|
for (var v in values) {
|
|
if (_list.contains(v)) return true;
|
|
}
|
|
} else if (values is AutoList<T, ST>) {
|
|
for (var v in values._list) {
|
|
if (_list.contains(v)) return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
@override
|
|
void destroy() {
|
|
clear();
|
|
}
|
|
}
|