| 
/* 
 | 
* Licensed to the Apache Software Foundation (ASF) under one 
 | 
* or more contributor license agreements.  See the NOTICE file 
 | 
* distributed with this work for additional information 
 | 
* regarding copyright ownership.  The ASF licenses this file 
 | 
* to you under the Apache License, Version 2.0 (the 
 | 
* "License"); you may not use this file except in compliance 
 | 
* with the License.  You may obtain a copy of the License at 
 | 
* 
 | 
*   http://www.apache.org/licenses/LICENSE-2.0 
 | 
* 
 | 
* Unless required by applicable law or agreed to in writing, 
 | 
* software distributed under the License is distributed on an 
 | 
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
 | 
* KIND, either express or implied.  See the License for the 
 | 
* specific language governing permissions and limitations 
 | 
* under the License. 
 | 
*/ 
 | 
  
 | 
  
 | 
/** 
 | 
 * AUTO-GENERATED FILE. DO NOT MODIFY. 
 | 
 */ 
 | 
  
 | 
/* 
 | 
* Licensed to the Apache Software Foundation (ASF) under one 
 | 
* or more contributor license agreements.  See the NOTICE file 
 | 
* distributed with this work for additional information 
 | 
* regarding copyright ownership.  The ASF licenses this file 
 | 
* to you under the Apache License, Version 2.0 (the 
 | 
* "License"); you may not use this file except in compliance 
 | 
* with the License.  You may obtain a copy of the License at 
 | 
* 
 | 
*   http://www.apache.org/licenses/LICENSE-2.0 
 | 
* 
 | 
* Unless required by applicable law or agreed to in writing, 
 | 
* software distributed under the License is distributed on an 
 | 
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
 | 
* KIND, either express or implied.  See the License for the 
 | 
* specific language governing permissions and limitations 
 | 
* under the License. 
 | 
*/ 
 | 
import * as zrUtil from 'zrender/lib/core/util.js'; 
 | 
import BoundingRect from 'zrender/lib/core/BoundingRect.js'; 
 | 
import * as visualSolution from '../../visual/visualSolution.js'; 
 | 
import { makeBrushCommonSelectorForSeries } from './selector.js'; 
 | 
import * as throttleUtil from '../../util/throttle.js'; 
 | 
import BrushTargetManager from '../helper/BrushTargetManager.js'; 
 | 
var STATE_LIST = ['inBrush', 'outOfBrush']; 
 | 
var DISPATCH_METHOD = '__ecBrushSelect'; 
 | 
var DISPATCH_FLAG = '__ecInBrushSelectEvent'; 
 | 
; 
 | 
export function layoutCovers(ecModel) { 
 | 
  ecModel.eachComponent({ 
 | 
    mainType: 'brush' 
 | 
  }, function (brushModel) { 
 | 
    var brushTargetManager = brushModel.brushTargetManager = new BrushTargetManager(brushModel.option, ecModel); 
 | 
    brushTargetManager.setInputRanges(brushModel.areas, ecModel); 
 | 
  }); 
 | 
} 
 | 
/** 
 | 
 * Register the visual encoding if this modules required. 
 | 
 */ 
 | 
export default function brushVisual(ecModel, api, payload) { 
 | 
  var brushSelected = []; 
 | 
  var throttleType; 
 | 
  var throttleDelay; 
 | 
  ecModel.eachComponent({ 
 | 
    mainType: 'brush' 
 | 
  }, function (brushModel) { 
 | 
    payload && payload.type === 'takeGlobalCursor' && brushModel.setBrushOption(payload.key === 'brush' ? payload.brushOption : { 
 | 
      brushType: false 
 | 
    }); 
 | 
  }); 
 | 
  layoutCovers(ecModel); 
 | 
  ecModel.eachComponent({ 
 | 
    mainType: 'brush' 
 | 
  }, function (brushModel, brushIndex) { 
 | 
    var thisBrushSelected = { 
 | 
      brushId: brushModel.id, 
 | 
      brushIndex: brushIndex, 
 | 
      brushName: brushModel.name, 
 | 
      areas: zrUtil.clone(brushModel.areas), 
 | 
      selected: [] 
 | 
    }; 
 | 
    // Every brush component exists in event params, convenient 
 | 
    // for user to find by index. 
 | 
    brushSelected.push(thisBrushSelected); 
 | 
    var brushOption = brushModel.option; 
 | 
    var brushLink = brushOption.brushLink; 
 | 
    var linkedSeriesMap = []; 
 | 
    var selectedDataIndexForLink = []; 
 | 
    var rangeInfoBySeries = []; 
 | 
    var hasBrushExists = false; 
 | 
    if (!brushIndex) { 
 | 
      // Only the first throttle setting works. 
 | 
      throttleType = brushOption.throttleType; 
 | 
      throttleDelay = brushOption.throttleDelay; 
 | 
    } 
 | 
    // Add boundingRect and selectors to range. 
 | 
    var areas = zrUtil.map(brushModel.areas, function (area) { 
 | 
      var builder = boundingRectBuilders[area.brushType]; 
 | 
      var selectableArea = zrUtil.defaults({ 
 | 
        boundingRect: builder ? builder(area) : void 0 
 | 
      }, area); 
 | 
      selectableArea.selectors = makeBrushCommonSelectorForSeries(selectableArea); 
 | 
      return selectableArea; 
 | 
    }); 
 | 
    var visualMappings = visualSolution.createVisualMappings(brushModel.option, STATE_LIST, function (mappingOption) { 
 | 
      mappingOption.mappingMethod = 'fixed'; 
 | 
    }); 
 | 
    zrUtil.isArray(brushLink) && zrUtil.each(brushLink, function (seriesIndex) { 
 | 
      linkedSeriesMap[seriesIndex] = 1; 
 | 
    }); 
 | 
    function linkOthers(seriesIndex) { 
 | 
      return brushLink === 'all' || !!linkedSeriesMap[seriesIndex]; 
 | 
    } 
 | 
    // If no supported brush or no brush on the series, 
 | 
    // all visuals should be in original state. 
 | 
    function brushed(rangeInfoList) { 
 | 
      return !!rangeInfoList.length; 
 | 
    } 
 | 
    /** 
 | 
     * Logic for each series: (If the logic has to be modified one day, do it carefully!) 
 | 
     * 
 | 
     * ( brushed ┬ && ┬hasBrushExist ┬ && linkOthers  ) => StepA: ┬record, ┬ StepB: ┬visualByRecord. 
 | 
     *   !brushed┘    ├hasBrushExist ┤                            └nothing,┘        ├visualByRecord. 
 | 
     *                └!hasBrushExist┘                                              └nothing. 
 | 
     * ( !brushed  && ┬hasBrushExist ┬ && linkOthers  ) => StepA:  nothing,  StepB: ┬visualByRecord. 
 | 
     *                └!hasBrushExist┘                                              └nothing. 
 | 
     * ( brushed ┬ &&                     !linkOthers ) => StepA:  nothing,  StepB: ┬visualByCheck. 
 | 
     *   !brushed┘                                                                  └nothing. 
 | 
     * ( !brushed  &&                     !linkOthers ) => StepA:  nothing,  StepB:  nothing. 
 | 
     */ 
 | 
    // Step A 
 | 
    ecModel.eachSeries(function (seriesModel, seriesIndex) { 
 | 
      var rangeInfoList = rangeInfoBySeries[seriesIndex] = []; 
 | 
      seriesModel.subType === 'parallel' ? stepAParallel(seriesModel, seriesIndex) : stepAOthers(seriesModel, seriesIndex, rangeInfoList); 
 | 
    }); 
 | 
    function stepAParallel(seriesModel, seriesIndex) { 
 | 
      var coordSys = seriesModel.coordinateSystem; 
 | 
      hasBrushExists = hasBrushExists || coordSys.hasAxisBrushed(); 
 | 
      linkOthers(seriesIndex) && coordSys.eachActiveState(seriesModel.getData(), function (activeState, dataIndex) { 
 | 
        activeState === 'active' && (selectedDataIndexForLink[dataIndex] = 1); 
 | 
      }); 
 | 
    } 
 | 
    function stepAOthers(seriesModel, seriesIndex, rangeInfoList) { 
 | 
      if (!seriesModel.brushSelector || brushModelNotControll(brushModel, seriesIndex)) { 
 | 
        return; 
 | 
      } 
 | 
      zrUtil.each(areas, function (area) { 
 | 
        if (brushModel.brushTargetManager.controlSeries(area, seriesModel, ecModel)) { 
 | 
          rangeInfoList.push(area); 
 | 
        } 
 | 
        hasBrushExists = hasBrushExists || brushed(rangeInfoList); 
 | 
      }); 
 | 
      if (linkOthers(seriesIndex) && brushed(rangeInfoList)) { 
 | 
        var data_1 = seriesModel.getData(); 
 | 
        data_1.each(function (dataIndex) { 
 | 
          if (checkInRange(seriesModel, rangeInfoList, data_1, dataIndex)) { 
 | 
            selectedDataIndexForLink[dataIndex] = 1; 
 | 
          } 
 | 
        }); 
 | 
      } 
 | 
    } 
 | 
    // Step B 
 | 
    ecModel.eachSeries(function (seriesModel, seriesIndex) { 
 | 
      var seriesBrushSelected = { 
 | 
        seriesId: seriesModel.id, 
 | 
        seriesIndex: seriesIndex, 
 | 
        seriesName: seriesModel.name, 
 | 
        dataIndex: [] 
 | 
      }; 
 | 
      // Every series exists in event params, convenient 
 | 
      // for user to find series by seriesIndex. 
 | 
      thisBrushSelected.selected.push(seriesBrushSelected); 
 | 
      var rangeInfoList = rangeInfoBySeries[seriesIndex]; 
 | 
      var data = seriesModel.getData(); 
 | 
      var getValueState = linkOthers(seriesIndex) ? function (dataIndex) { 
 | 
        return selectedDataIndexForLink[dataIndex] ? (seriesBrushSelected.dataIndex.push(data.getRawIndex(dataIndex)), 'inBrush') : 'outOfBrush'; 
 | 
      } : function (dataIndex) { 
 | 
        return checkInRange(seriesModel, rangeInfoList, data, dataIndex) ? (seriesBrushSelected.dataIndex.push(data.getRawIndex(dataIndex)), 'inBrush') : 'outOfBrush'; 
 | 
      }; 
 | 
      // If no supported brush or no brush, all visuals are in original state. 
 | 
      (linkOthers(seriesIndex) ? hasBrushExists : brushed(rangeInfoList)) && visualSolution.applyVisual(STATE_LIST, visualMappings, data, getValueState); 
 | 
    }); 
 | 
  }); 
 | 
  dispatchAction(api, throttleType, throttleDelay, brushSelected, payload); 
 | 
} 
 | 
; 
 | 
function dispatchAction(api, throttleType, throttleDelay, brushSelected, payload) { 
 | 
  // This event will not be triggered when `setOpion`, otherwise dead lock may 
 | 
  // triggered when do `setOption` in event listener, which we do not find 
 | 
  // satisfactory way to solve yet. Some considered resolutions: 
 | 
  // (a) Diff with prevoius selected data ant only trigger event when changed. 
 | 
  // But store previous data and diff precisely (i.e., not only by dataIndex, but 
 | 
  // also detect value changes in selected data) might bring complexity or fragility. 
 | 
  // (b) Use spectial param like `silent` to suppress event triggering. 
 | 
  // But such kind of volatile param may be weird in `setOption`. 
 | 
  if (!payload) { 
 | 
    return; 
 | 
  } 
 | 
  var zr = api.getZr(); 
 | 
  if (zr[DISPATCH_FLAG]) { 
 | 
    return; 
 | 
  } 
 | 
  if (!zr[DISPATCH_METHOD]) { 
 | 
    zr[DISPATCH_METHOD] = doDispatch; 
 | 
  } 
 | 
  var fn = throttleUtil.createOrUpdate(zr, DISPATCH_METHOD, throttleDelay, throttleType); 
 | 
  fn(api, brushSelected); 
 | 
} 
 | 
function doDispatch(api, brushSelected) { 
 | 
  if (!api.isDisposed()) { 
 | 
    var zr = api.getZr(); 
 | 
    zr[DISPATCH_FLAG] = true; 
 | 
    api.dispatchAction({ 
 | 
      type: 'brushSelect', 
 | 
      batch: brushSelected 
 | 
    }); 
 | 
    zr[DISPATCH_FLAG] = false; 
 | 
  } 
 | 
} 
 | 
function checkInRange(seriesModel, rangeInfoList, data, dataIndex) { 
 | 
  for (var i = 0, len = rangeInfoList.length; i < len; i++) { 
 | 
    var area = rangeInfoList[i]; 
 | 
    if (seriesModel.brushSelector(dataIndex, data, area.selectors, area)) { 
 | 
      return true; 
 | 
    } 
 | 
  } 
 | 
} 
 | 
function brushModelNotControll(brushModel, seriesIndex) { 
 | 
  var seriesIndices = brushModel.option.seriesIndex; 
 | 
  return seriesIndices != null && seriesIndices !== 'all' && (zrUtil.isArray(seriesIndices) ? zrUtil.indexOf(seriesIndices, seriesIndex) < 0 : seriesIndex !== seriesIndices); 
 | 
} 
 | 
var boundingRectBuilders = { 
 | 
  rect: function (area) { 
 | 
    return getBoundingRectFromMinMax(area.range); 
 | 
  }, 
 | 
  polygon: function (area) { 
 | 
    var minMax; 
 | 
    var range = area.range; 
 | 
    for (var i = 0, len = range.length; i < len; i++) { 
 | 
      minMax = minMax || [[Infinity, -Infinity], [Infinity, -Infinity]]; 
 | 
      var rg = range[i]; 
 | 
      rg[0] < minMax[0][0] && (minMax[0][0] = rg[0]); 
 | 
      rg[0] > minMax[0][1] && (minMax[0][1] = rg[0]); 
 | 
      rg[1] < minMax[1][0] && (minMax[1][0] = rg[1]); 
 | 
      rg[1] > minMax[1][1] && (minMax[1][1] = rg[1]); 
 | 
    } 
 | 
    return minMax && getBoundingRectFromMinMax(minMax); 
 | 
  } 
 | 
}; 
 | 
function getBoundingRectFromMinMax(minMax) { 
 | 
  return new BoundingRect(minMax[0][0], minMax[1][0], minMax[0][1] - minMax[0][0], minMax[1][1] - minMax[1][0]); 
 | 
} 
 |