'use strict' ; import type Axis from '../Axis' ; import type Chart from '../../Chart/Chart' ; import type ColorAxis from './ColorAxis' ; import type ColorType from '../../Color/ColorType' ; import type Fx from '../../Animation/Fx' ; import type Legend from '../../Legend/Legend' ; import type Point from '../../Series/Point' ; import type Series from '../../Series/Series' ; import type SeriesOptions from '../../Series/SeriesOptions' ; import type TreemapSeries from '../../../Series/Treemap/TreemapSeries' ; import Color from '../../Color/Color.js' ; const { parse : color } = Color ; import U from '../../Utilities.js' ; const { addEvent , extend , merge , pick , splat } = U ; declare module '../../Series/PointLike' { interface PointLike { requires setVisible ( vis ? ) : void ; } } declare module '../../Series/SeriesLike' { interface SeriesLike { requires translateColors ( ) : void ; } } namespace ColorAxisComposition { export interface PointComposition extends Point { series : SeriesComposition ; value ? : ( number | null ) ; setVisible ( vis ? ) : void ; } export interface SeriesComposition extends Series { colorAxis : ColorAxis ; data : Array < PointComposition > ; points : Array < PointComposition > ; options : SeriesCompositionOptions ; optionalAxis ? : string ; translateColors ( ) : void ; } export interface SeriesCompositionOptions extends SeriesOptions { nullColor ? : ColorType ; } const composedClasses = [ ] ; let ColorAxisClass ; private export function compose ( ColorAxisType , ChartClass , FxClass , LegendClass , SeriesClass ) { if ( ! ColorAxisClass ) { ColorAxisClass = ColorAxisType ; } if ( composedClasses . indexOf ( ChartClass ) === - 1 ) { composedClasses . push ( ChartClass ) ; const chartProto = ChartClass . prototype ; chartProto . collectionsWithUpdate . push ( 'colorAxis' ) ; chartProto . collectionsWithInit . colorAxis = [ chartProto . addColorAxis ] ; addEvent ( ChartClass , 'afterGetAxes' , onChartAfterGetAxes ) ; wrapChartCreateAxis ( ChartClass ) ; } if ( composedClasses . indexOf ( FxClass ) === - 1 ) { composedClasses . push ( FxClass ) ; const fxProto = FxClass . prototype ; fxProto . fillSetter = wrapFxFillSetter ; fxProto . strokeSetter = wrapFxStrokeSetter ; } if ( composedClasses . indexOf ( LegendClass ) === - 1 ) { composedClasses . push ( LegendClass ) ; addEvent ( LegendClass , 'afterGetAllItems' , onLegendAfterGetAllItems ) ; addEvent ( LegendClass , 'afterColorizeItem' , onLegendAfterColorizeItem ) ; addEvent ( LegendClass , 'afterUpdate' , onLegendAfterUpdate ) ; } if ( composedClasses . indexOf ( SeriesClass ) === - 1 ) { composedClasses . push ( SeriesClass ) ; extend ( SeriesClass . prototype , { optionalAxis : 'colorAxis' , translateColors : seriesTranslateColors } ) ; extend ( SeriesClass . prototype . pointClass . prototype , { setVisible : pointSetVisible } ) ; addEvent ( SeriesClass , 'afterTranslate' , onSeriesAfterTranslate ) ; addEvent ( SeriesClass , 'bindAxes' , onSeriesBindAxes ) ; } } private function onChartAfterGetAxes ( this ) { const options = this . options ; this . colorAxis = [ ] ; if ( options . colorAxis ) { options . colorAxis = splat ( options . colorAxis ) ; options . colorAxis . forEach ( ( axisOptions , i ) : void => { axisOptions . index = i ; new ColorAxisClass ( this , axisOptions ) ; } ) ; } } private function onLegendAfterGetAllItems ( this , e ) { const colorAxes = this . chart . colorAxis || [ ] , destroyItem = ( item ) : void => { const i = e . allItems . indexOf ( item ) ; if ( i !== - 1 ) { this . destroyItem ( e . allItems [ i ] ) ; e . allItems . splice ( i , 1 ) ; } } ; let colorAxisItems = [ ] as Array < ( ColorAxis | ColorAxis . LegendItemObject ) > , options , i ; colorAxes . forEach ( function ( colorAxis ) : void { options = colorAxis . options ; if ( options && options . showInLegend ) { if ( options . dataClasses && options . visible ) { colorAxisItems = colorAxisItems . concat ( colorAxis . getDataClassLegendSymbols ( ) ) ; } else if ( options . visible ) { colorAxisItems . push ( colorAxis ) ; } colorAxis . series . forEach ( function ( series ) : void { if ( ! series . options . showInLegend || options . dataClasses ) { if ( series . options . legendType === 'point' ) { series . points . forEach ( function ( point ) : void { destroyItem ( point ) ; } ) ; } else { destroyItem ( series ) ; } } } ) ; } } ) ; i = colorAxisItems . length ; while ( i -- ) { e . allItems . unshift ( colorAxisItems [ i ] ) ; } } private function onLegendAfterColorizeItem ( this , e ) { if ( e . visible && e . item . legendColor ) { ( e . item . legendSymbol as any ) . attr ( { fill : e . item . legendColor } ) ; } } private function onLegendAfterUpdate ( this ) { const colorAxes = this . chart . colorAxis ; if ( colorAxes ) { colorAxes . forEach ( function ( colorAxis ) : void { colorAxis . update ( { } , arguments [ 2 ] ) ; } ) ; } } private function onSeriesAfterTranslate ( this ) { if ( this . chart . colorAxis && this . chart . colorAxis . length || ( this as TreemapSeries ) . colorAttribs ) { this . translateColors ( ) ; } } private function onSeriesBindAxes ( this ) { const axisTypes = this . axisTypes ; if ( ! axisTypes ) { this . axisTypes = [ 'colorAxis' ] ; } else if ( axisTypes . indexOf ( 'colorAxis' ) === - 1 ) { axisTypes . push ( 'colorAxis' ) ; } } private function param { boolean } visible export function pointSetVisible ( this , vis ? ) { const point = this , method = vis ? 'show' : 'hide' ; point . visible = point . options . visible = Boolean ( vis ) ; [ 'graphic' , 'dataLabel' ] . forEach ( function ( key ) : void { if ( ( point as any ) [ key ] ) { ( point as any ) [ key ] [ method ] ( ) ; } } ) ; this . series . buildKDTree ( ) ; } private function function seriesTranslateColors ( this ) { const series = this , points = this . data . length ? this . data : this . points , nullColor = this . options . nullColor , colorAxis = this . colorAxis , colorKey = this . colorKey ; points . forEach ( ( point ) : void => { const value = point . getNestedProperty ( colorKey ) as number , color = point . options . color || ( point . isNull || point . value === null ? nullColor : ( colorAxis && typeof value !== 'undefined' ) ? colorAxis . toColor ( value , point ) : point . color || series . color ) ; if ( color && point . color !== color ) { point . color = color ; if ( series . options . legendType === 'point' && point . legendItem ) { series . chart . legend . colorizeItem ( point , point . visible ) ; } } } ) ; } private function wrapChartCreateAxis ( ChartClass ) { const superCreateAxis = ChartClass . prototype . createAxis ; ChartClass . prototype . createAxis = function ( type , options ) : ( Axis | ColorAxis ) { if ( type !== 'colorAxis' ) { return superCreateAxis . apply ( this , arguments ) ; } const axis = new ColorAxisClass ( this , merge ( options . axis , { index : ( this as AnyRecord ) [ type ] . length , isX : false } ) ) ; this . isDirtyLegend = true ; this . axes . forEach ( function ( axis ) : void { axis . series = [ ] ; } ) ; this . series . forEach ( function ( series ) : void { series . bindAxes ( ) ; series . isDirtyData = true ; } ) ; if ( pick ( options . redraw , true ) ) { this . redraw ( options . animation ) ; } return axis ; } ; } private function wrapFxFillSetter ( this ) { this . elem . attr ( 'fill' , color ( this . start as any ) . tweenTo ( color ( this . end as any ) , this . pos ) , void 0 , true ) ; } private function wrapFxStrokeSetter ( this ) { this . elem . attr ( 'stroke' , color ( this . start as any ) . tweenTo ( color ( this . end as any ) , this . pos ) , void 0 , true ) ; } } export default ColorAxisComposition ;