File

projects/wms-framework/src/lib/models/controls/ItemsControlModel.ts

Extends

PresentationFrameworkCollectionModel

Index

Properties
Methods
Accessors

Properties

CollectionChanged
Type : SubscriptionEvent<void>
Default value : new SubscriptionEvent()
syncItems
Type : Function

Function that allows to do sync of the items collection in the model

Private innerCollection
Default value : new SimpleList<T>()
Protected bindingExpressions
Default value : new SimpleDictionary< string, BindingExpression >()
Inherited from DependencyObject
Public BindingValidationError
Default value : new SubscriptionEvent< (sender: any, e: BindingValidationErrorEventArgs) => void >()
Inherited from DependencyObject

Event for validation errors

Public change
Type : SubscriptionEvent<void>
Default value : new SubscriptionEvent()
Inherited from DependencyObject

Infrastructure event for notifying event changes

Public Dispatcher
Type : Dispatcher
Default value : Dispatcher.GetDispatcher()
Inherited from DependencyObject
isEnableSetPropertiesRegistry
Type : boolean
Default value : true
Inherited from DependencyObject

Flag which indicates if the dependency property set mechanism is enable

Public IsInitializingBindings
Type : boolean
Default value : false
Inherited from DependencyObject

Property to determine if bindings are being initialized

previousValidationMessage
Type : string
Default value : ''
Inherited from DependencyObject
Protected properties
Type : object
Default value : {}
Inherited from DependencyObject
Private setPropertiesRegistry
Type : Map<string | boolean>
Default value : new Map()
Inherited from DependencyObject

Registry with dependencies properties which has been set

validationerr
Default value : false
Inherited from DependencyObject
validationMessagesStack
Type : Array<>
Default value : []
Inherited from DependencyObject

Keeps a queue of validation messages registered on the current Dependency Object

Methods

add
add(value: any)

Adds item to the collection

Parameters :
Name Type Optional
value any No
Returns : void
asINotifyCollectionChanged
asINotifyCollectionChanged()
Decorators :
@asExplicitImplementation('System.Collections.Specialized.INotifyCollectionChanged')
clear
clear()

Clears the collection

Returns : void
clearWithoutReset
clearWithoutReset()

Clears the collection without firing the CollectionChange event.

Returns : void
fire
fire(info: CollectionChangeInfo)

Fire event to external handler

Parameters :
Name Type Optional
info CollectionChangeInfo No
Returns : void
insert
insert(index: number, value: any)

Insert item at postion

Parameters :
Name Type Optional
index number No
value any No
Returns : void
remove
remove(value: any)

Removes the first element from the collection which match with the value

Parameters :
Name Type Optional
value any No
Returns : boolean
removeAt
removeAt(index: number)

Removes item in the given index

Parameters :
Name Type Optional
index number No
Returns : void
setWithCollection
setWithCollection(collection: any)

Adds a new collections to the items collection. Clear the items collection before adding the new values.

Parameters :
Name Type Optional
collection any No
Returns : void
contains
contains(value: T)
Parameters :
Name Type Optional
value T No
Returns : boolean
copyTo
copyTo(target: T[], index: number)
Parameters :
Name Type Optional
target T[] No
index number No
Returns : void
getItem
getItem(index: number)
Parameters :
Name Type Optional
index number No
Returns : T
indexOf
indexOf(value: T)
Parameters :
Name Type Optional
value T No
Returns : number
internalAdd
internalAdd(value: T)

Add used for internal processing of added elements to collection without trigger change

Parameters :
Name Type Optional
value T No
Returns : void
setItem
setItem(index: number, value: T)
Parameters :
Name Type Optional
index number No
value T No
Returns : void
sort
sort()
Returns : any
()
Returns : Iterator<T, any, undefined>
Private addRelatedSubscriptionIfRequired
addRelatedSubscriptionIfRequired(event: SubscriptionEvent<any>, theHandler: any, bindingExpression: BindingExpression)
Inherited from DependencyObject
Parameters :
Name Type Optional
event SubscriptionEvent<any> No
theHandler any No
bindingExpression BindingExpression No
Returns : void
Private addSubscriptionForTwoWayBindings
addSubscriptionForTwoWayBindings(dependencyProperty: DependencyProperty, binding: Binding, bindingExpression: BindingExpression)
Inherited from DependencyObject
Parameters :
Name Type Optional
dependencyProperty DependencyProperty No
binding Binding No
bindingExpression BindingExpression No
Returns : void
addsValidationMessage
addsValidationMessage(propKey: Binding | string, message: string)
Inherited from DependencyObject

Adds a new validation message associated to a binding or a property name

Parameters :
Name Type Optional
propKey Binding | string No
message string No
Returns : void
Private beginSubscribeToMultiPropertyPathChanges
beginSubscribeToMultiPropertyPathChanges(context: any, binding: Binding, dependencyProperty: DependencyProperty, bindingExpression: BindingExpression)
Inherited from DependencyObject
Parameters :
Name Type Optional
context any No
binding Binding No
dependencyProperty DependencyProperty No
bindingExpression BindingExpression No
Returns : void
Private checkForSubscriptoinToDataErrorInfo
checkForSubscriptoinToDataErrorInfo(currentContext: any, binding: Binding, propertyToSubscribe: string, bindingExpression: BindingExpression)
Inherited from DependencyObject
Parameters :
Name Type Optional
currentContext any No
binding Binding No
propertyToSubscribe string No
bindingExpression BindingExpression No
Returns : void
Public clearValue
clearValue(property: DependencyProperty)
Inherited from DependencyObject

Clears the dependency property value

Parameters :
Name Type Optional
property DependencyProperty No
Returns : void
Equals
Equals(obj: any)
Inherited from DependencyObject

Compares this dependency object agains another object.

Parameters :
Name Type Optional
obj any No
Returns : boolean

{boolean}

GetChild
GetChild(idx: number)
Inherited from DependencyObject

Gets the child element at the index position

Parameters :
Name Type Optional
idx number No
Returns : DependencyObject

{DependencyObject}

GetChildrenCount
GetChildrenCount()
Inherited from DependencyObject

Method o know the amount of children the parent has

Returns : number

{number}

GetHashCode
GetHashCode()
Inherited from DependencyObject

Gets a hash code for this dependency object.

Returns : number

{number}

Public getValue
getValue(property: DependencyProperty)
Inherited from DependencyObject

Gets the value of a dependency property

Parameters :
Name Type Optional
property DependencyProperty No
Returns : any
Private handleErrorsOnContext
handleErrorsOnContext(errorCtxt: INotifyDataErrorInfo, args: DataErrorsChangedEventArgs)
Inherited from DependencyObject

Check and register possible errors in an error context

Parameters :
Name Type Optional
errorCtxt INotifyDataErrorInfo No
args DataErrorsChangedEventArgs No
Returns : void
Public IsPropertySet
IsPropertySet(propertyName: string)
Inherited from DependencyObject

Indicates if the property has been already set.

Parameters :
Name Type Optional
propertyName string No
Returns : any
Private performDataErrorValidationIfRequired
performDataErrorValidationIfRequired(binding: Binding, theBindingContext: any)
Inherited from DependencyObject

Performs validation on model if the model implementes IDataErrorINfo

Parameters :
Name Type Optional
binding Binding No
theBindingContext any No
Returns : void
Private performRemoveValidationIfInValidationError
performRemoveValidationIfInValidationError(binding: Binding)
Inherited from DependencyObject

Performs the remove validation if the InValidationError is true

Parameters :
Name Type Optional
binding Binding No
Returns : void
Public performTargetObjectBindingUpdate
performTargetObjectBindingUpdate(dependencyProperty: DependencyProperty, binding: Binding)
Inherited from DependencyObject

Updates the target object value associated to the binding.

Parameters :
Name Type Optional
dependencyProperty DependencyProperty No
binding Binding No
Returns : void
Private preprocessValue
preprocessValue(property: DependencyProperty, value: any)
Inherited from DependencyObject

Preprocess value to be set to dependency property

Parameters :
Name Type Optional
property DependencyProperty No
value any No
Returns : any
Private recreateSubscriptionsForMultiPropertyBindingPath
recreateSubscriptionsForMultiPropertyBindingPath(currentContext: any, outerContext: any, properties: string[], propertyIndex: number, dependencyProperty: DependencyProperty, bindingExpression: BindingExpression, subscriptionsForCurrentBindingPath: Array<>)
Inherited from DependencyObject
Parameters :
Name Type Optional
currentContext any No
outerContext any No
properties string[] No
propertyIndex number No
dependencyProperty DependencyProperty No
bindingExpression BindingExpression No
subscriptionsForCurrentBindingPath Array<> No
Returns : void
Private registerSetPropertyIfRequired
registerSetPropertyIfRequired(name: string)
Inherited from DependencyObject

Register set property if required

Parameters :
Name Type Optional
name string No
Returns : void
Private removeSubscriptionsForMultiPropertyBindingPath
removeSubscriptionsForMultiPropertyBindingPath(subscriptionsForCurrentBindingPath: [], propertyIndex: number)
Inherited from DependencyObject
Parameters :
Name Type Optional
subscriptionsForCurrentBindingPath [] No
propertyIndex number No
Returns : void
removeValidationMessage
removeValidationMessage(propKey: Binding | string)
Inherited from DependencyObject

Removes a validation message associated to a binding or a property name

Parameters :
Name Type Optional
propKey Binding | string No
Returns : void
SetBinding
SetBinding(dependencyProperty: DependencyProperty, binding: Binding)
Inherited from DependencyObject

Sets a binding to the specified property at runtime

Parameters :
Name Type Optional Description
dependencyProperty DependencyProperty No

property to bind

binding Binding No

binding object

Returns : void
Public setValue
setValue(property: DependencyProperty, value: any)
Inherited from DependencyObject

Sets the value for a dependency property

Parameters :
Name Type Optional
property DependencyProperty No
value any No
Returns : void
Public setValueForScopedRegion
setValueForScopedRegion(property: DependencyProperty, value: any, scopedRegionManager: IRegionManager)
Inherited from DependencyObject

Sets the value for a dependency property. This is a workaround to support Scoped Region Managers. A research is required to find out the way to get the application region Manager when scoped region managers are used (when creating the DelayedRegionBehavior, the correct scoped region manager must be passed as an argument).

Parameters :
Name Type Optional
property DependencyProperty No
value any No
scopedRegionManager IRegionManager No
Returns : void
Protected shouldPreventDefaultSourceUpdate
shouldPreventDefaultSourceUpdate(dependencyProperty: DependencyProperty, binding: BindingExpression)
Inherited from DependencyObject
Parameters :
Name Type Optional
dependencyProperty DependencyProperty No
binding BindingExpression No
Returns : boolean
Private subscribeToBindingPathChanges
subscribeToBindingPathChanges(context: any, binding: Binding, dependencyProperty: DependencyProperty, bindingExpression: BindingExpression)
Inherited from DependencyObject
Parameters :
Name Type Optional
context any No
binding Binding No
dependencyProperty DependencyProperty No
bindingExpression BindingExpression No
Returns : void
Private subscribeToErrorsChangedInModel
subscribeToErrorsChangedInModel(errorCtxt: INotifyDataErrorInfo, propertyToSubscribe: string, bindingExpression: BindingExpression)
Inherited from DependencyObject
Parameters :
Name Type Optional
errorCtxt INotifyDataErrorInfo No
propertyToSubscribe string No
bindingExpression BindingExpression No
Returns : void
Private subscribeToPropertyChanges
subscribeToPropertyChanges(currentContext: any, outerContext: any, properties: string[], propertyIndex: number, dependencyProperty: DependencyProperty, bindingExpression: BindingExpression, subscriptionsForCurrentBindingPath: Array<>)
Inherited from DependencyObject
Parameters :
Name Type Optional
currentContext any No
outerContext any No
properties string[] No
propertyIndex number No
dependencyProperty DependencyProperty No
bindingExpression BindingExpression No
subscriptionsForCurrentBindingPath Array<> No
Returns : void
Private updateSourceOfBinding
updateSourceOfBinding(binding: Binding, outerContext: any, dependencyProperty: DependencyProperty)
Inherited from DependencyObject

Updates the source of a binding

Parameters :
Name Type Optional
binding Binding No
outerContext any No
dependencyProperty DependencyProperty No
Returns : void

Accessors

CollectionChanged_INotifyCollectionChanged
getCollectionChanged_INotifyCollectionChanged()

Internal access for explicit implemented property

import { Control } from '../../basecomponentmodel/Control';
import { Dependency } from '../../basecomponentmodel/Dependency';
import { DependencyObject } from '../../basecomponentmodel/DependencyObject';
import { DependencyProperty } from '../../basecomponentmodel/DependencyProperty';
import { DependencyPropertyChangedEventArgs } from '../../basecomponentmodel/DependencyPropertyChangedEventArgs';
import { FrameworkElement } from '../../basecomponentmodel/FrameworkElement';
import { tryToConvertType } from '../../baseframework/ReflectionSupport';
import {
  CollectionChangeAction,
  CollectionChangeInfo,
  IComparer,
  IList,
  INotifyCollectionChanged,
  SimpleList,
} from '../../baseframework/collections';
import { ReflectionHelper } from '../../baseframework/ReflectionSupport';
import { asExplicitImplementation } from '../../decorators/AsExplicitImplementation';
import { ClassInfo } from '../../decorators/ClassInfo';
import { AngularComponentId } from '../../helpers/AngularComponentId';
import { SubscriptionEvent } from '../../utils/SubscriptionEvent';

/**
 * Model class to represent Image component
 *
 * @export
 * @class ItemsControlModel
 * @extends {Control}
 * @wType System.Windows.Controls.ItemsControl
 * @wType Telerik.Windows.Controls.ItemsControl
 */
export class ItemsControlModel extends Control {
  /**
   * DisplayMemberPathProperty dependency property
   *
   * @static
   * @type {DependencyProperty}
   * @memberof ItemsControlModel
   */
  static DisplayMemberPathProperty: DependencyProperty = new DependencyProperty(
    'DisplayMemberPath',
    null,
    null
  );

  /**
   * ItemsPanelProperty dependency property
   *
   * @static
   * @type {DependencyProperty}
   * @memberof ItemsControlModel
   */
  static ItemsPanelProperty: DependencyProperty = new DependencyProperty(
    'ItemsPanel',
    null,
    null
  );

  /**
   * ItemsSourceProperty dependency property
   *
   * @static
   * @type {DependencyProperty}
   * @memberof ItemsControlModel
   */
  static ItemsSourceProperty: DependencyProperty = new DependencyProperty(
    'ItemsSource',
    null,
    ItemsControlModel.ItemsSourceCallback
  );

  /**
   * ItemTemplateProperty dependency property
   *
   * @static
   * @type {DependencyProperty}
   * @memberof ItemsControlModel
   */
  static ItemTemplateProperty: DependencyProperty = new DependencyProperty(
    'ItemTemplate',
    null,
    null
  );

  /**
   * Force sync items collection
   *
   * @memberof ItemsControlModel
   */
  public forceSyncItemsWithItemsSource() {
    if (this.ItemsSource) {
      this.setItemsProperty(this.ItemsSource);
    }
  }

  private itemContainerGenerator: any = null;

  /**
   * Call this method to fill the items property
   *
   * @private
   * @param {*} collection
   * @memberof ItemsControlModel
   */
  private setItemsProperty(collection: any) {
    this.items.clear();
    if (collection) {
      this.items.setWithCollection(collection);
    }
  }

  /**
   * Call this method to fill the items property
   *
   * @private
   * @param {*} collection
   * @memberof ItemsControlModel
   */
  private setItemsPropertyEvent(
    collection: any,
    info: CollectionChangeInfo = null
  ): void {
    if (info) {
      this.propagateCollectionChanges(collection, info);
    } else {
      this.rebuildCollection(collection);
    }
  }

  public items: ItemsCollectionModel;

  /**
   * Items source
   *
   * @type {Iterable<any>}
   * @memberof ItemsControlModel
   */
  @Dependency(ItemsControlModel.ItemsSourceProperty)
  public ItemsSource: Iterable<any>;

  /**
   * The items panel
   *
   * @type {*}
   * @memberof ItemsControlModel
   */
  @Dependency(ItemsControlModel.ItemsPanelProperty)
  public ItemsPanel: any;

  /**
   * The display member path
   *
   * @type {string}
   * @memberof ItemsControlModel
   */
  @Dependency(ItemsControlModel.DisplayMemberPathProperty)
  public DisplayMemberPath: string;

  /**
   * The item template
   *
   * @type {*}
   * @memberof ItemsControlModel
   */
  @Dependency(ItemsControlModel.ItemTemplateProperty)
  public ItemTemplate: any;

  /**
   * Identifies the angular component associated with the model
   *
   * @type {string}
   * @memberof ItemsControlModel
   */
  public AngularComponentId = AngularComponentId.itemsControl;

  /**
   * Rebuild collection without triggering
   * reset event and restore the items
   *
   * @private
   * @param {*} collection
   * @memberof ItemsControlModel
   */
  private rebuildCollection(collection: any, info: any = null) {
    this.items.clearWithoutReset();
    /* istanbul ignore else */
    if (collection) {
      this.items.setWithCollection(collection);
    }
    /* istanbul ignore else */
    if (info) {
      this.items.fire(info);
    }
  }

  /**
   *  Gets or sets the item container generator
   *
   * @type {*}
   * @memberof ItemsControlModel
   */
  public get ItemContainerGenerator(): any {
    return this.itemContainerGenerator;
  }
  public set ItemContainerGenerator(v: any) {
    this.itemContainerGenerator = v;
  }

  /**
   * Return the amount of children the parent has
   *
   * @return {*}  {number}
   * @memberof ItemsControlModel
   * @wIgnore
   */
  GetChildrenCount(): number {
    return this.items.count;
  }

  /**
   * Gets the child element at the index position
   *
   * @param {number} idx
   * @return {*}  {DependencyObject}
   * @memberof ItemsControlModel
   * @wIgnore
   */
  GetChild(idx: number): DependencyObject {
    return this.items.getItem(idx);
  }

  constructor() {
    super();
    this.items = new ItemsCollectionModel();
    this.SetUpHierarchyListeners(this.items);
  }

  /**
   * Subscription for the CollectionChanged event of the items source (if exists)
   *
   * @memberof ItemsControlModel
   */
  private collectionChangedSubscription: (e: any, args: any) => void;

  /**
   * Reference to callbar called whenever the ItemsSource have changed.
   *
   * @private
   * @type {INotifyCollectionChanged}
   * @memberof ItemsControlModel
   */
  private valueConvertRef: INotifyCollectionChanged;

  /**
   * Reference to subscription when the model is initilized.
   *
   * @private
   * @type {INotifyCollectionChanged}
   * @memberof ItemsControlModel
   */
  private itemsCollectionListenerRef: INotifyCollectionChanged;

  /**
   * Called when the component is being destroyed, clear some handlers attach to this model.
   *
   * @type {void}
   * @memberof ItemsControlModel
   */
  OnDestroy(): void {
    super.OnDestroy();
    this.valueConvertRef?.CollectionChanged.removeHandler(
      this.collectionChangedSubscription,
      this
    );
    this.itemsCollectionListenerRef?.CollectionChanged.removeHandler(
      this.ValidateInfo,
      this
    );
    this.collectionChangedSubscription = null;
  }

  /**
   * On ItemsSource changed handler
   *
   * @param {DependencyPropertyChangedEventArgs} args
   * @memberof ItemsControlModel
   * @wIgnore
   */
  public OnItemsSourceChanged(args: DependencyPropertyChangedEventArgs) {
    // deregister previous handler
    if (args.OldValue && this.collectionChangedSubscription) {
      this.valueConvertRef = tryToConvertType<INotifyCollectionChanged>(
        args.OldValue,
        ReflectionHelper.getInterfaceRuntimeTypeInfo(
          'System.Collections.Specialized.INotifyCollectionChanged'
        )
      );
      this.valueConvertRef?.CollectionChanged.removeHandler(
        this.collectionChangedSubscription,
        this
      );
      this.collectionChangedSubscription = null;
    }

    // adds new handler
    try {
      this.valueConvertRef = tryToConvertType<INotifyCollectionChanged>(
        args.NewValue,
        ReflectionHelper.getInterfaceRuntimeTypeInfo(
          'System.Collections.Specialized.INotifyCollectionChanged'
        )
      );
      if (this.valueConvertRef) {
        this.collectionChangedSubscription =
          this.valueConvertRef.CollectionChanged.addHandler(
            this.setItemsPropertyEvent,
            this
          );
      }
      this.setItemsProperty(args.NewValue);
    } catch (error) {
      this.setItemsProperty(args.NewValue);
    }
  }

  /**
   * ItemsSource dependency property callback
   *
   * @static
   * @param {DependencyObject} sender
   * @param {DependencyPropertyChangedEventArgs} args
   * @memberof ItemsControlModel
   * @wIgnore
   */
  public static ItemsSourceCallback(
    sender: DependencyObject,
    args: DependencyPropertyChangedEventArgs
  ) {
    if (sender instanceof ItemsControlModel) {
      sender.OnItemsSourceChanged(args);
    }
  }

  /**
   *  Sets the listeners for the items property
   *
   * @param {Iterable<any>} value
   * @memberof ItemsControlModel
   */
  private SetUpHierarchyListeners(value: Iterable<any>) {
    this.itemsCollectionListenerRef =
      tryToConvertType<INotifyCollectionChanged>(
        value,
        ReflectionHelper.getInterfaceRuntimeTypeInfo(
          'System.Collections.Specialized.INotifyCollectionChanged'
        )
      );
    this.itemsCollectionListenerRef?.CollectionChanged.addHandler(
      this.ValidateInfo,
      this
    );
  }

  /**
   *  Validates the listener information for the items modifed
   *
   * @param {CollectionChangeInfo} info
   * @memberof ItemsControlModel
   */
  private ValidateInfo(_: any, info: CollectionChangeInfo) {
    if (info.action == CollectionChangeAction.Add) {
      for (const item of info.NewItems) {
        if (item instanceof FrameworkElement) {
          item.Parent = this;
        }
      }
    } else if (
      (info.action == CollectionChangeAction.Reset && info.OldItems) ||
      info.action == CollectionChangeAction.Remove
    ) {
      for (const item of info.OldItems) {
        if (item instanceof FrameworkElement) {
          item.Parent = null;
        }
      }
    }
  }

  /**
   * Applies the changes in bound collection to this { ItemsConttrolModel } internal
   * collection
   *
   * @private
   * @param {CollectionChangeInfo} info the { @link CollectionChangeInfo } object containing the
   * changes in bound collection
   * @memberof ItemsControlModel
   */
  private propagateCollectionChanges(
    collection: any,
    info: CollectionChangeInfo
  ) {
    switch (info.action) {
      case CollectionChangeAction.Add:
      case CollectionChangeAction.Replace:
        let i = info.NewStartingIndex;
        for (const e of info.NewItems) {
          if (info.action === CollectionChangeAction.Add) {
            this.items.insert(i++, e);
          } else {
            this.items.setItem(i++, e);
            this.items.fire(info);
          }
        }
        break;
      case CollectionChangeAction.Remove:
        for (let index = 0; index < info.OldItems.count; index++) {
          this.items.removeAt(info.OldStartingIndex);
        }
        break;
      case CollectionChangeAction.Reset:
        this.rebuildCollection(collection, info);
        break;
    }
  }
}

export abstract class PresentationFrameworkCollectionModel<T>
  extends DependencyObject
  implements IList<T>
{
  private innerCollection = new SimpleList<T>();
  getItem(index: number): T {
    return this.innerCollection.getItem(index);
  }

  setItem(index: number, value: T) {
    this.innerCollection.setItem(index, value);
    this.change.fire(['Count']);
  }

  indexOf(value: T): number {
    return this.innerCollection.indexOf(value);
  }

  insert(index: number, value: T) {
    this.innerCollection.insert(index, value);
    this.change.fire(['Count']);
  }

  removeAt(index: number) {
    this.innerCollection.removeAt(index);
    this.change.fire(['Count']);
  }

  get count(): number {
    return this.innerCollection.count;
  }
  sort();

  sort(comparer: IComparer<T>);

  sort(comparer?) {
    this.innerCollection.sort(comparer);
  }

  add(value: T): void {
    this.internalAdd(value);
    this.change.fire(['Count']);
  }

  /**
   * Add used for internal processing of added elements to collection without trigger change
   *
   * @param {T} value
   * @memberof PresentationFrameworkCollectionModel
   */
  internalAdd(value: T): void {
    if (
      value &&
      value instanceof Object &&
      value.hasOwnProperty &&
      value.hasOwnProperty('Parent')
    ) {
      // eslint-disable-next-line @typescript-eslint/dot-notation
      value['Parent'] = this;
    }
    this.innerCollection.add(value);
  }

  clear(): void {
    const count = this.innerCollection.count;
    this.innerCollection.clear();
    if (count !== this.innerCollection.count) {
      this.change.fire(['Count']);
    }
  }

  contains(value: T): boolean {
    return this.innerCollection.contains(value);
  }

  remove(value: T): boolean {
    const result = this.innerCollection.remove(value);
    this.change.fire(['Count']);
    return result;
  }

  copyTo(target: T[], index: number): void {
    this.innerCollection.copyTo(target, index);
  }
  [Symbol.iterator](): Iterator<T, any, undefined> {
    return this.innerCollection[Symbol.iterator]();
  }
  get internalArray(): T[] {
    return this.innerCollection.internalArray;
  }
}

@ClassInfo({
  classId: 'ItemsCollectionModel',
  implements: ['System.Collections.Specialized.INotifyCollectionChanged'],
})
/**
 * Items Collection Model
 *
 * @export
 * @class ItemsCollectionModel
 * @extends {PresentationFrameworkCollectionModel<any>}
 */
export class ItemsCollectionModel extends PresentationFrameworkCollectionModel<any> {
  /**
   * Function that allows to do sync of the items collection in the model
   *
   * @memberof ItemsCollectionModel
   */
  syncItems: Function;

  /**
   * Collection changed subsccription event
   *
   * @memberof ItemsCollectionModel
   */
  #CollectionChanged: SubscriptionEvent<
    (e: any, args: CollectionChangeInfo) => void
  > = new SubscriptionEvent();

  /**
   * Internal access for explicit implemented property
   *
   * @readonly
   * @memberof ItemsCollectionModel
   */
  get CollectionChanged_INotifyCollectionChanged(): SubscriptionEvent<
    (e: any, args: CollectionChangeInfo) => void
  > {
    return this.#CollectionChanged;
  }

  /**
   * Insert item at postion
   *
   * @param {number} index
   * @param {*} value
   * @memberof ItemsCollectionModel
   */
  insert(index: number, value: any) {
    if (index <= this.internalArray.length && index >= 0) {
      super.insert(index, value);
      const info = new CollectionChangeInfo(CollectionChangeAction.Add);
      const newItems = new SimpleList();
      newItems.add(value);
      info.NewItems = newItems;
      info.NewStartingIndex = index;
      this.#CollectionChanged.fire([this, info]);
      this.syncItems?.();
    } else {
      throw new Error(
        'Specified argument was out of the range of valid values.'
      );
    }
  }

  /**
   * Removes item in the given index
   *
   * @param {number} index
   * @memberof ItemsCollectionModel
   */
  removeAt(index: number) {
    if (index < this.internalArray.length && index >= 0) {
      const itemToRemove = super.getItem(index);
      super.removeAt(index);
      const info = new CollectionChangeInfo(CollectionChangeAction.Remove);
      const oldItems = new SimpleList();
      oldItems.add(itemToRemove);
      info.OldItems = oldItems;
      info.OldStartingIndex = index;
      this.#CollectionChanged.fire([this, info]);
      this.syncItems?.();
    } else {
      throw new Error(
        'Specified argument was out of the range of valid values.'
      );
    }
  }

  /**
   * Adds item to the collection
   *
   * @param {*} value
   * @memberof ItemsCollectionModel
   */
  add(value: any): void {
    super.add(value);
    const info = new CollectionChangeInfo(CollectionChangeAction.Add);
    const newItems = new SimpleList();
    newItems.add(value);
    info.NewItems = newItems;
    info.NewStartingIndex = this.internalArray.length - 1;
    this.#CollectionChanged.fire([this, info]);
    this.syncItems?.();
  }

  /**
   * Adds a new collections to the items collection.
   * Clear the items collection before adding the new values.
   *
   * @param {*} collection
   * @memberof ItemsCollectionModel
   */
  setWithCollection(collection: any): void {
    for (const item of collection) {
      super.internalAdd(item);
    }
    this.change.fire(['Count']);
    this.syncItems?.();
  }

  /**
   * Clears the collection without firing the CollectionChange event.
   *
   * @memberof ItemsCollectionModel
   */
  clearWithoutReset() {
    super.clear();
    this.syncItems?.();
  }

  /**
   * Clears the collection
   *
   * @memberof ItemsCollectionModel
   */
  clear(): void {
    const currentValues = this.internalArray.map((e) => e);
    super.clear();
    const info = new CollectionChangeInfo(CollectionChangeAction.Reset);
    info.OldItems = new SimpleList(currentValues);
    this.#CollectionChanged.fire([this, info]);
    this.syncItems?.();
  }

  /**
   * Fire event to external handler
   *
   * @param {CollectionChangeInfo} info
   * @memberof ItemsCollectionModel
   */
  fire(info: CollectionChangeInfo): void {
    this.#CollectionChanged.fire([this, info]);
  }

  /**
   * Removes the first element from the collection which match with the value
   *
   * @param {*} value
   * @returns {boolean}
   * @memberof ItemsCollectionModel
   */
  remove(value: any): boolean {
    const removeItemIndex = super.indexOf(value);
    if (removeItemIndex > -1) {
      super.removeAt(removeItemIndex);
      const info = new CollectionChangeInfo(CollectionChangeAction.Remove);
      const oldItems = new SimpleList();
      oldItems.add(value);
      info.OldItems = oldItems;
      info.OldStartingIndex = removeItemIndex;
      this.#CollectionChanged.fire([this, info]);
      this.syncItems?.();
      return true;
    }
    return false;
  }

  @asExplicitImplementation(
    'System.Collections.Specialized.INotifyCollectionChanged'
  )
  asINotifyCollectionChanged(): INotifyCollectionChanged {
    return new ItemsCollectionModel_INotifyCollectionChangedWrapper(this);
  }
}

class ItemsCollectionModel_INotifyCollectionChangedWrapper
  implements INotifyCollectionChanged
{
  /**
   * Collection changed subsccription event
   *
   * @memberof ItemsCollectionModel
   */
  get CollectionChanged(): SubscriptionEvent<
    (e: any, args: CollectionChangeInfo) => void
  > {
    return this.instance.CollectionChanged_INotifyCollectionChanged;
  }

  /**
   * Used to recognize if the class is an explicit implementation
   *
   * @memberof ItemsCollectionModel_INotifyCollectionChangedWrapper
   */
  isExplicitInterfaceImplementationWrapper = true;

  /**
   *Creates an instance of ItemsCollectionModel_INotifyCollectionChangedWrapper.
   *
   * @param {ItemsCollectionModel} instance
   * @memberof ItemsCollectionModel_INotifyCollectionChangedWrapper
   */
  constructor(public instance: ItemsCollectionModel) {}
}

result-matching ""

    No results matching ""