/**
 * A variety of convenience methods for maintaining a current selection
 */ import { ArrayExt } from '@lumino/algorithm' ; import { ISignal , Signal } from '@lumino/signaling' ; export class Selection < T > { constructor ( sequence , options = { } ) { this . _array = sequence ; this . _insertBehavior = options . insertBehavior || 'select-item-if-needed' ; this . _removeBehavior = options . removeBehavior || 'select-item-after' ; } /**
     * A signal emitted when the current item is changed.
     *
     * #### Notes
     * This signal is emitted when the currently selected item is changed either
     * through user or programmatic interaction.
     *
     * Notably, this signal is not emitted when the index of the current item
     * changes due to other items being inserted, removed, or moved, but the
     * current item remains the same. It is only emitted when the actual current
     * item is changed.
     */ get selectionChanged ( ) : ISignal < Selection < T > , Selection . ISelectionChangedArgs < T > > { return this . _selectionChanged ; } param index param oldValue adjustSelectionForSet ( index ) { const pi = this . index ; const pv = this . value ; if ( index !== pi ) { return ; } this . _updateSelectedValue ( ) ; const cv = this . value ; this . _previousValue = null ; if ( pv !== cv ) { this . _selectionChanged . emit ( { previousIndex : pi , previousValue : pv , currentIndex : pi , currentValue : cv , } ) ; } } /**
     * Get the currently selected item.
     *
     * #### Notes
     * This will be `null` if no item is selected.
     */ get value ( ) : T | null { return this . _value ; } /**
     * Set the currently selected item.
     *
     * #### Notes
     * If the item does not exist in the vector, the currentValue will be set to
     * `null`. This selects the first entry equal to the desired item.
     */ set value ( value ) { if ( value === null || this . _array === null ) { this . index = null ; } else { this . index = ArrayExt . firstIndexOf ( this . _array , value ) ; } } /**
     * Get the index of the currently selected item.
     *
     * #### Notes
     * This will be `null` if no item is selected.
     */ get index ( ) : number | null { return this . _index ; } param index set index ( index ) { let i ; if ( index !== null && this . _array !== null ) { i = Math . floor ( index ) ; if ( i < 0 || i >= this . _array . length ) { i = null ; } } else { i = null ; } if ( this . _index === i ) { return ; } const pi = this . _index ; const pv = this . _value ; this . _index = i ; this . _updateSelectedValue ( ) ; this . _previousValue = pv ; this . _selectionChanged . emit ( { previousIndex : pi , previousValue : pv , currentIndex : i , currentValue : this . _value , } ) ; } /**
     * Get the selection behavior when inserting a tab.
     */ get insertBehavior ( ) : Selection . InsertBehavior { return this . _insertBehavior ; } /**
     * Set the selection behavior when inserting a tab.
     */ set insertBehavior ( value ) { this . _insertBehavior = value ; } /**
     * Get the selection behavior when removing a tab.
     */ get removeBehavior ( ) : Selection . RemoveBehavior { return this . _removeBehavior ; } /**
     * Set the selection behavior when removing a tab.
     */ set removeBehavior ( value ) { this . _removeBehavior = value ; } param i param j adjustSelectionForInsert ( i , item ) { const cv = this . _value ; const ci = this . _index ; const bh = this . _insertBehavior ; if ( bh === 'select-item' || ( bh === 'select-item-if-needed' && ci === null ) ) { this . _index = i ; this . _value = item ; this . _previousValue = cv ; this . _selectionChanged . emit ( { previousIndex : ci , previousValue : cv , currentIndex : i , currentValue : item , } ) ; return ; } if ( ci !== null && ci >= i ) { this . _index ! ++ ; } } /**
     * Clear the selection and history.
     */ clearSelection ( ) { const pi = this . _index ; const pv = this . _value ; this . _index = null ; this . _value = null ; this . _previousValue = null ; if ( pi === null ) { return ; } this . _selectionChanged . emit ( { previousIndex : pi , previousValue : pv , currentIndex : this . _index , currentValue : this . _value , } ) ; } param i param item adjustSelectionForRemove ( i , item ) { if ( this . _index === null ) { return ; } const ci = this . _index ; const bh = this . _removeBehavior ; if ( ci !== i ) { if ( ci > i ) { this . _index ! -- ; } return ; } if ( ! this . _array || this . _array . length === 0 ) { this . _index = null ; this . _value = null ; this . _previousValue = null ; this . _selectionChanged . emit ( { previousIndex : i , previousValue : item , currentIndex : this . _index , currentValue : this . _value , } ) ; return ; } if ( bh === 'select-item-after' ) { this . _index = Math . min ( i , this . _array . length - 1 ) ; this . _updateSelectedValue ( ) ; this . _previousValue = null ; this . _selectionChanged . emit ( { previousIndex : i , previousValue : item , currentIndex : this . _index , currentValue : this . _value , } ) ; return ; } if ( bh === 'select-item-before' ) { this . _index = Math . max ( 0 , i - 1 ) ; this . _updateSelectedValue ( ) ; this . _previousValue = null ; this . _selectionChanged . emit ( { previousIndex : i , previousValue : item , currentIndex : this . _index , currentValue : this . _value , } ) ; return ; } if ( bh === 'select-previous-item' ) { if ( this . _previousValue ) { this . value = this . _previousValue ; } else { this . _index = Math . min ( i , this . _array . length - 1 ) ; this . _updateSelectedValue ( ) ; } this . _previousValue = null ; this . _selectionChanged . emit ( { previousIndex : i , previousValue : item , currentIndex : this . _index , currentValue : this . value , } ) ; return ; } this . _index = null ; this . _value = null ; this . _previousValue = null ; this . _selectionChanged . emit ( { previousIndex : i , previousValue : item , currentIndex : this . _index , currentValue : this . _value , } ) ; } /**
     * Set the current value based on the current index.
     */ private _updateSelectedValue ( ) { const i = this . _index ; this . _value = i !== null && this . _array ? this . _array [ i ] : null ; } private _array : ReadonlyArray < T > | null = null ; private _index : number | null ; private _value : T | null = null ; private _previousValue : T | null = null ; private _insertBehavior : Selection . InsertBehavior ; private _removeBehavior : Selection . RemoveBehavior ; private _selectionChanged = new Signal < Selection < T > , Selection . ISelectionChangedArgs < T > > ( this ) ; } export namespace Selection { /**
     * An options object for creating a tab bar.
     */ export interface IOptions { /**
         * The selection behavior when inserting a tab.
         *
         * The default is `'select-tab-if-needed'`.
         */ insertBehavior ? : Selection . InsertBehavior ; /**
         * The selection behavior when removing a tab.
         *
         * The default is `'select-tab-after'`.
         */ removeBehavior ? : Selection . RemoveBehavior ; } /**
     * The arguments object for the `currentChanged` signal.
     */ export interface ISelectionChangedArgs < T > { /**
         * The previously selected index.
         */ previousIndex : number | null ; /**
         * The previous selected item.
         */ previousValue : T | null ; /**
         * The currently selected index.
         */ currentIndex : number | null ; /**
         * The currently selected item.
         */ currentValue : T | null ; } /**
     * A type alias for the selection behavior on item insert.
     */ export type InsertBehavior = 'none' | 'select-item' | 'select-item-if-needed' ; /**
     * A type alias for the selection behavior on item remove.
     */ export type RemoveBehavior = 'none' | 'select-item-after' | 'select-item-before' | 'select-previous-item' ; }