**** A utility class that emulates a COM Collection object. 'Collection' is designed to be subclassed.** ** For Fancom to instantiate the collection subclass it needs a ctor similar to:** ** new makeFromDispatch(Dispatch dispatch) : super(dispatch, MyCollectionType#) { }** ** The collection type should be a valid Fancom type or a Fancom surrogate.** ** Subclasses my override methods to narrow the return types:** ** override MyType? item(Int index) {** super.item(index)** }** ** When doing so, ensure the return type is declared as nullable. See ** [Covariance, value types, and nullability]`http://fantom.org/sidewalk/topic/611#c13742`** ** If calculated properties are ever allowed to be in Mixins, this class could be converted to a ** Mixin. See [Mixin Calculated Fields]`http://fantom.org/sidewalk/topic/2110`** abstractclass Collection {** The COM Collection componentprotected Dispatch dispatch {private set }** The type of the collectionprotected Type collectionType** The name of the COM property which returns the collection countprotected Str countPropertyName := "Count"** The name of the COM method which returns an item in the collectionprotected Str itemMethodName := "Item"** Set to '1' for collections that are 1 based protected Int countOffset := 0** Makes a COM Collection of the given type protectednew makeFromDispatch(Dispatch dispatch, Type collectionType){this.dispatch = dispatchthis.collectionType = collectionType}// ---- Properties ----------------------------------------------------------------------------** Returns the count of objects in the collection. Int? count { get { dispatch.getProperty(countPropertyName).asInt }private set {}}// ---- Methods -------------------------------------------------------------------------------** Returns a member of the collection specified by its index.** ** Override to provide a narrowed return type:** ** ** virtual Obj? item(Int index){return dispatch.call(itemMethodName, index).asType(collectionType)}** Calls the specified function for every item in the collectionvirtual Void each(|Obj?, Int| callback){ count := this.countif(count == null)return min := countOffset max := countOffset + countfor(i := min; i < max; ++i){ callback(item(i), i)}}** Returns the first item in the collection for which 'callback' returns 'true'. If 'callback' ** returns 'false' for every item, then return 'null'.** ** This method is lazy and *does not* pre-call `#item` for every member in the collection. virtual Obj? find(|Obj? v, Int index-> Bool| callback){ count := this.countif(count == null)returnnull min := countOffset max := countOffset + countfor(i := min; i < max; ++i){ obj := item(i)if(callback(obj, i))return obj}returnnull}}