import { Dispatch } from 'redux' ; import { Axis } from 'vega' ; import { CompiledBinding } from '.' ; import { State } from '../../store' ; import { AxisRecord , Guide , GuideType , LegendRecord } from '../../store/factory/Guide' ; import { addGuide } from '../guideActions' ; import { addAxisToGroup , addLegendToGroup } from './helperActions' ; import { assignId } from '../../util/counter' ; import { ThunkDispatch } from 'redux-thunk' ; const imutils = require ( '../../util/immutable-utils' ) , getIn = imutils . getIn , getInVis = imutils . getInVis ; const CTYPE = { x : GuideType . Axis , y : GuideType . Axis , color : GuideType . Legend , size : GuideType . Legend , shape : GuideType . Legend } ; const SWAP_ORIENT = { left : 'right' , right : 'left' , top : 'bottom' , bottom : 'top' } ; param { Function } dispatch param { ImmutableMap } state param { Object } parsed returns { void } export default function parseGuides ( dispatch , state , parsed ) { const channel = parsed . channel , map = parsed . map , guideType = CTYPE [ channel ] , scaleId = map . scales [ channel ] , group = parsed . output ; if ( ! guideType || ! scaleId ) { return ; } if ( guideType === GuideType . Axis ) { findOrCreateAxis ( dispatch , state , parsed , scaleId , group . axes ) ; } else { findOrCreateLegend ( dispatch , state , parsed , scaleId , group . legends ) ; } } param { Function } dispatch param { ImmutableMap } state param { Object } parsed param { number } scaleId param { Object } defs returns { void } function findOrCreateAxis ( dispatch , state , parsed , scaleId , defs ) { const map = parsed . map , mark = parsed . mark , parentId = mark . _parent , scale = getInVis ( state , `scales.${ scaleId }` ) , axes = getInVis ( state , `marks.${ parentId }.axes` ) ; let foundAxis = false , count = 0 , prevOrient ; const def = defs . find ( axis => map . scales [ axis . scale ] === scaleId && axis . title ) ; axes . forEach ( ( axisId ) => { const axis = getInVis ( state , `guides.${ axisId }` ) ; if ( ! axis ) { return ; } if ( String ( axis . scale ) === String ( scaleId ) ) { foundAxis = true ; } if ( axis . orient === def . orient ) { ++ count ; prevOrient = axis . orient ; } if ( SWAP_ORIENT [ axis . orient ] === def . orient ) { ++ count ; } } ) ; if ( foundAxis ) { return ; } if ( count < 2 ) { let axis = Guide ( GuideType . Axis , parsed . channel , scaleId ) as AxisRecord ; axis = axis . mergeDeep ( { title : def . title , orient : count === 1 && prevOrient ? SWAP_ORIENT [ prevOrient ] : def . orient || axis . orient , encode : def . encode } ) ; const axisId = assignId ( dispatch , state ) ; axis = axis . merge ( { _id : axisId } ) ; dispatch ( addGuide ( axis ) ) ; dispatch ( addAxisToGroup ( axisId , parentId ) ) ; } } param { Function } dispatch param { ImmutableMap } state param { Object } parsed param { number } scaleId param { Object } defs returns { void } function findOrCreateLegend ( dispatch , state , parsed , scaleId , defs ) { const map = parsed . map , mark = parsed . mark , property = parsed . property , parentId = mark . _parent , legends = getInVis ( state , `marks.${ parentId }.legends` ) ; let foundLegend = false ; const def = defs . find ( legend => map . scales [ legend [ property ] ] === scaleId ) ; legends . some ( function ( legendId ) { const legend = getInVis ( state , `guides.${ legendId }` ) ; if ( legend ) { return ( foundLegend = foundLegend || legend . get ( property ) === scaleId ) ; } } ) ; if ( ! foundLegend ) { let legend = Guide ( GuideType . Legend , property , scaleId ) as LegendRecord ; legend = legend . deleteIn ( [ 'encode' , 'symbols' , property ] ) ; legend = legend . mergeDeep ( { title : def . title , encode : def . encode } ) ; const legendId = assignId ( dispatch , state ) ; legend = legend . merge ( { _id : legendId } ) ; dispatch ( addGuide ( legend ) ) ; dispatch ( addLegendToGroup ( legendId , parentId ) ) ; } }