import type { IEventListener , ISequence } from '../internal' ; import { Category , toolbar } from './annotations' ; import { DEFAULT_CATEGORICAL_COLOR_FUNCTION } from './CategoricalColorMappingFunction' ; import Column , { dirty , dirtyCaches , dirtyHeader , dirtyValues , groupRendererChanged , labelChanged , metaDataChanged , rendererTypeChanged , summaryRendererChanged , visibilityChanged , widthChanged , DEFAULT_COLOR , } from './Column' ; import type { ICategoricalColumn , ICategoricalColumnDesc , ICategoricalFilter , ICategory , ICategoricalColorMappingFunction , } from './ICategoricalColumn' ; import { IDataRow , IGroup , ICompareValue , ITypeFactory , ECompareValueType } from './interfaces' ; import { missingGroup } from './missing' ; import type { dataLoaded } from './ValueColumn' ; import ValueColumn from './ValueColumn' ; import { toCategories , isCategoryIncluded , isEqualCategoricalFilter , toCompareCategoryValue , toGroupCompareCategoryValue , } from './internalCategorical' ; asMemberOf event export declare function colorMappingChanged_CC ( previous , current ) ; asMemberOf event export declare function filterChanged_CC ( previous , current ) ; /**
 * column for categorical values
 */ @ toolbar ( 'rename' , 'clone' , 'sort' , 'sortBy' , 'group' , 'groupBy' , 'sortGroupBy' , 'filterCategorical' , 'colorMappedCategorical' ) @ Category ( 'categorical' ) export default class CategoricalColumn extends ValueColumn < string > implements ICategoricalColumn { static readonly EVENT_FILTER_CHANGED = 'filterChanged' ; static readonly EVENT_COLOR_MAPPING_CHANGED = 'colorMappingChanged' ; readonly categories : ICategory [ ] ; private colorMapping : ICategoricalColorMappingFunction ; private readonly lookup = new Map < string , Readonly < ICategory > > ( ) ; type { null } private private currentFilter : ICategoricalFilter | null = null ; constructor ( id , desc ) { super ( id , desc ) ; this . categories = toCategories ( desc ) ; this . categories . forEach ( ( d ) => this . lookup . set ( d . name , d ) ) ; this . colorMapping = DEFAULT_CATEGORICAL_COLOR_FUNCTION ; } protected createEventList ( ) { return super . createEventList ( ) . concat ( [ CategoricalColumn . EVENT_FILTER_CHANGED , CategoricalColumn . EVENT_COLOR_MAPPING_CHANGED ] ) ; } on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) { return super . on ( type as any , listener ) ; } getValue ( row ) { const v = this . getCategory ( row ) ; return v ? v . name : null ; } getCategory ( row ) { const v = super . getValue ( row ) ; if ( ! v ) { return null ; } const vs = String ( v ) ; return this . lookup . has ( vs ) ? this . lookup . get ( vs ) ! : null ; } get dataLength ( ) { return this . categories . length ; } get labels ( ) { return this . categories . map ( ( d ) => d . label ) ; } getLabel ( row ) { const v = this . getCategory ( row ) ; return v ? v . label : '' ; } getCategories ( row ) { const v = this . getCategory ( row ) ; return [ v ] ; } getValues ( row ) { const v = this . getCategory ( row ) ; return this . categories . map ( ( d ) => d === v ) ; } getLabels ( row ) { return this . getValues ( row ) . map ( String ) ; } getMap ( row ) { const cats = this . categories ; return this . getValues ( row ) . map ( ( value , i ) => ( { key : cats [ i ] . label , value } ) ) ; } getMapLabel ( row ) { const cats = this . categories ; return this . getLabels ( row ) . map ( ( value , i ) => ( { key : cats [ i ] . label , value } ) ) ; } getSet ( row ) { const cat = this . getCategory ( row ) ; const r = new Set < ICategory > ( ) ; if ( cat ) { r . add ( cat ) ; } return r ; } iterCategory ( row ) { return [ this . getCategory ( row ) ] ; } dump ( toDescRef ) { const r = super . dump ( toDescRef ) ; r . filter = this . currentFilter ; r . colorMapping = this . colorMapping . toJSON ( ) ; return r ; } restore ( dump , factory ) { super . restore ( dump , factory ) ; this . colorMapping = factory . categoricalColorMappingFunction ( dump . colorMapping , this . categories ) ; if ( typeof dump . filter === 'undefined' ) { this . currentFilter = null ; return ; } const bak = dump . filter ; if ( typeof bak === 'string' || Array . isArray ( bak ) ) { this . currentFilter = { filter : bak , filterMissing : false } ; } else { this . currentFilter = bak ; } } getColor ( row ) { const v = this . getCategory ( row ) ; return v ? this . colorMapping . apply ( v ) : DEFAULT_COLOR ; } getColorMapping ( ) { return this . colorMapping . clone ( ) ; } setColorMapping ( mapping ) { if ( this . colorMapping . eq ( mapping ) ) { return ; } this . fire ( [ CategoricalColumn . EVENT_COLOR_MAPPING_CHANGED , Column . EVENT_DIRTY_VALUES , Column . EVENT_DIRTY_CACHES , Column . EVENT_DIRTY_HEADER , Column . EVENT_DIRTY , ] , this . colorMapping . clone ( ) , ( this . colorMapping = mapping ) ) ; } isFiltered ( ) { return this . currentFilter != null ; } filter ( row , valueCache ? ) { return isCategoryIncluded ( this . currentFilter , valueCache !== undefined ? valueCache : this . getCategory ( row ) ) ; } getFilter ( ) { return this . currentFilter == null ? null : Object . assign ( { } , this . currentFilter ) ; } setFilter ( filter ) { if ( isEqualCategoricalFilter ( this . currentFilter , filter ) ) { return ; } this . fire ( [ CategoricalColumn . EVENT_FILTER_CHANGED , Column . EVENT_DIRTY_VALUES , Column . EVENT_DIRTY ] , this . currentFilter , ( this . currentFilter = filter ) ) ; } clearFilter ( ) { const was = this . isFiltered ( ) ; this . setFilter ( null ) ; return was ; } toCompareValue ( row , valueCache ? ) { return toCompareCategoryValue ( valueCache !== undefined ? valueCache : this . getCategory ( row ) ) ; } toCompareValueType ( ) { return ECompareValueType . FLOAT_ASC ; } group ( row , valueCache ? ) { const cat = valueCache !== undefined ? valueCache : this . getCategory ( row ) ; if ( ! cat ) { return Object . assign ( { } , missingGroup ) ; } return { name : cat . label , color : cat . color } ; } toCompareGroupValue ( rows , _group , valueCache ? ) { return toGroupCompareCategoryValue ( rows , this , valueCache ) ; } toCompareGroupValueType ( ) { return [ ECompareValueType . FLOAT , ECompareValueType . STRING ] ; } getGroupRenderer ( ) { const current = super . getGroupRenderer ( ) ; if ( current === this . desc . type && this . isGroupedBy ( ) >= 0 ) { return 'catdistributionbar' ; } return current ; } }