text: import { __assign, __extends } from "tslib";
  import { clamp, each, filter, get, mix } from '@antv/util';
  import { ellipsisLabel } from '../util/label';
  import { getMatrixByAngle, getMatrixByTranslate } from '../util/matrix';
  import { getStatesStyle } from '../util/state';
  import Theme from '../util/theme';
  import LegendBase from './base';
  var Category = /** @class */ (function (_super) {
      __extends(Category, _super);
      function Category() {
          var _this = _super !== null && _super.apply(this, arguments) || this;
          _this.currentPageIndex = 1;
          _this.totalPagesCnt = 1;
          _this.pageWidth = 0;
          _this.pageHeight = 0;
          _this.startX = 0;
          _this.startY = 0;
          _this.onNavigationBack = function () {
              var itemGroup = _this.getElementByLocalId('item-group');
              if (_this.currentPageIndex > 1) {
                  _this.currentPageIndex -= 1;
                  _this.updateNavigation();
                  var matrix = _this.getCurrentNavigationMatrix();
                  if (_this.get('animate')) {
                      itemGroup.animate({
                          matrix: matrix,
                      }, 100);
                  }
                  else {
                      itemGroup.attr({ matrix: matrix });
                  }
              }
          };
          _this.onNavigationAfter = function () {
              var itemGroup = _this.getElementByLocalId('item-group');
              if (_this.currentPageIndex < _this.totalPagesCnt) {
                  _this.currentPageIndex += 1;
                  _this.updateNavigation();
                  var matrix = _this.getCurrentNavigationMatrix();
                  if (_this.get('animate')) {
                      itemGroup.animate({
                          matrix: matrix,
                      }, 100);
                  }
                  else {
                      itemGroup.attr({ matrix: matrix });
                  }
              }
          };
          return _this;
      }
      Category.prototype.getDefaultCfg = function () {
          var cfg = _super.prototype.getDefaultCfg.call(this);
          return __assign(__assign({}, cfg), { name: 'legend', type: 'category', itemSpacing: 24, maxItemWidth: null, itemWidth: null, itemHeight: null, itemName: {}, itemValue: null, maxWidth: null, maxHeight: null, marker: {}, items: [], itemStates: {}, itemBackground: {}, defaultCfg: {
                  title: {
                      spacing: 5,
                      style: {
                          fill: Theme.textColor,
                          fontSize: 12,
                          textAlign: 'start',
                          textBaseline: 'top',
                      },
                  },
                  background: {
                      padding: 5,
                      style: {
                          stroke: Theme.lineColor,
                      },
                  },
                  itemBackground: {
                      style: {
                          opacity: 0,
                          fill: '#fff',
                      },
                  },
                  itemName: {
                      spacing: 16,
                      style: {
                          fill: Theme.textColor,
                          fontSize: 12,
                          textAlign: 'start',
                          textBaseline: 'middle',
                      },
                  },
                  marker: {
                      spacing: 8,
                      style: {
                          r: 6,
                          symbol: 'circle',
                      },
                  },
                  itemValue: {
                      alignRight: false,
                      formatter: null,
                      style: {
                          fill: Theme.textColor,
                          fontSize: 12,
                          textAlign: 'start',
                          textBaseline: 'middle',
                      },
                  },
                  itemStates: {
                      active: {
                          nameStyle: {
                              opacity: 0.8,
                          },
                      },
                      unchecked: {
                          nameStyle: {
                              fill: Theme.uncheckedColor,
                          },
                          markerStyle: {
                              fill: Theme.uncheckedColor,
                              stroke: Theme.uncheckedColor,
                          },
                      },
                      inactive: {
                          nameStyle: {
                              fill: Theme.uncheckedColor,
                          },
                          markerStyle: {
                              opacity: 0.2,
                          },
                      },
                  },
              } });
      };
      // 实现 IList 接口
      Category.prototype.isList = function () {
          return true;
      };
      /**
       * 获取图例项
       * @return {ListItem[]} 列表项集合
       */
      Category.prototype.getItems = function () {
          return this.get('items');
      };
      /**
       * 设置列表项
       * @param {ListItem[]} items 列表项集合
       */
      Category.prototype.setItems = function (items) {
          this.update({
              items: items,
          });
      };
      /**
       * 更新列表项
       * @param {ListItem} item 列表项
       * @param {object}   cfg  列表项
       */
      Category.prototype.updateItem = function (item, cfg) {
          mix(item, cfg);
          this.clear(); // 由于单个图例项变化，会引起全局变化，所以全部更新
          this.render();
      };
      /**
       * 清空列表
       */
      Category.prototype.clearItems = function () {
          var itemGroup = this.getElementByLocalId('item-group');
          itemGroup && itemGroup.clear();
      };
      /**
       * 设置列表项的状态
       * @param {ListItem} item  列表项
       * @param {string}   state 状态名
       * @param {boolean}  value 状态值, true, false
       */
      Category.prototype.setItemState = function (item, state, value) {
          item[state] = value;
          var itemElement = this.getElementByLocalId("item-" + item.id);
          if (itemElement) {
              var items = this.getItems();
              var index = items.indexOf(item);
              var offsetGroup = this.createOffScreenGroup(); // 离屏的 group
              var newElement = this.drawItem(item, index, this.getItemHeight(), offsetGroup);
              this.updateElements(newElement, itemElement); // 更新整个分组
              this.clearUpdateStatus(itemElement); // 清理更新状态，防止出现 bug
          }
      };
      /**
       * 是否存在指定的状态
       * @param {ListItem} item  列表项
       * @param {boolean} state 状态名
       */
      Category.prototype.hasState = function (item, state) {
          return !!item[state];
      };
      Category.prototype.getItemStates = function (item) {
          var itemStates = this.get('itemStates');
          var rst = [];
          each(itemStates, function (v, k) {
              if (item[k]) {
                  // item.selected
                  rst.push(k);
              }
          });
          return rst;
      };
      /**
       * 清楚所有列表项的状态
       * @param {string} state 状态值
       */
      Category.prototype.clearItemsState = function (state) {
          var _this = this;
          var items = this.getItemsByState(state);
          each(items, function (item) {
              _this.setItemState(item, state, false);
          });
      };
      /**
       * 根据状态获取图例项
       * @param  {string}     state [description]
       * @return {ListItem[]}       [description]
       */
      Category.prototype.getItemsByState = function (state) {
          var _this = this;
          var items = this.getItems();
          return filter(items, function (item) {
              return _this.hasState(item, state);
          });
      };
      // 绘制 legend 的选项
      Category.prototype.drawLegendContent = function (group) {
          this.processItems();
          this.drawItems(group);
      };
      // 防止未设置 id
      Category.prototype.processItems = function () {
          var items = this.get('items');
          each(items, function (item) {
              if (!item.id) {
                  // 如果没有设置 id，默认使用 name
                  item.id = item.name;
              }
          });
      };
      // 绘制所有的图例选项
      Category.prototype.drawItems = function (group) {
          var _this = this;
          var itemContainerGroup = this.addGroup(group, {
              id: this.getElementId('item-container-group'),
              name: 'legend-item-container-group',
          });
          var itemGroup = this.addGroup(itemContainerGroup, {
              id: this.getElementId('item-group'),
              name: 'legend-item-group',
          });
          var itemHeight = this.getItemHeight();
          var itemWidth = this.get('itemWidth');
          var itemSpacing = this.get('itemSpacing');
          var currentPoint = this.get('currentPoint');
          var startX = currentPoint.x;
          var startY = currentPoint.y;
          var layout = this.get('layout');
          var items = this.get('items');
          var wrapped = false;
          var pageWidth = 0;
          var maxWidth = this.get('maxWidth'); // 最大宽度，会导致 layout : 'horizontal' 时自动换行
          var maxHeight = this.get('maxHeight'); // 最大高度，会导致出现分页
          // 暂时不考虑分页
          each(items, function (item, index) {
              var subGroup = _this.drawItem(item, index, itemHeight, itemGroup);
              var bbox = subGroup.getBBox();
              var width = itemWidth || bbox.width;
              if (width > pageWidth) {
                  pageWidth = width;
              }
              if (layout === 'horizontal') {
                  // 如果水平布局
                  if (maxWidth && maxWidth < currentPoint.x + width - startX) {
                      // 检测是否换行
                      wrapped = true;
                      currentPoint.x = startX;
                      currentPoint.y += itemHeight;
                  }
                  _this.moveElementTo(subGroup, currentPoint);
                  currentPoint.x += width + itemSpacing;
              }
              else {
                  // 如果垂直布局
                  if (maxHeight && maxHeight < currentPoint.y + itemHeight - startY) {
                      // 换行
                      wrapped = true;
                      currentPoint.x += pageWidth + itemSpacing;
                      currentPoint.y = startY;
                      pageWidth = 0;
                  }
                  _this.moveElementTo(subGroup, currentPoint);
                  currentPoint.y += itemHeight; // itemSpacing 仅影响水平间距
              }
          });
          if (wrapped && this.get('flipPage')) {
              this.pageHeight = 0;
              this.pageWidth = 0;
              this.totalPagesCnt = 1;
              this.startX = startX;
              this.startY = startY;
              this.adjustNavigation(group, itemGroup);
          }
      };
      // 获取图例项的高度，如果未定义，则按照 name 的高度计算
      Category.prototype.getItemHeight = function () {
          var itemHeight = this.get('itemHeight');
          if (!itemHeight) {
              var nameCfg = this.get('itemName');
              if (nameCfg) {
                  itemHeight = nameCfg.style.fontSize + 8;
              }
          }
          return itemHeight;
      };
      // 绘制 marker
      Category.prototype.drawMarker = function (container, markerCfg, item, itemHeight) {
          var markerAttrs = __assign(__assign(__assign({ x: 0, y: itemHeight / 2 }, markerCfg.style), { symbol: get(item.marker, 'symbol', 'circle') }), get(item.marker, 'style', {}));
          var shape = this.addShape(container, {
              type: 'marker',
              id: this.getElementId("item-" + item.id + "-marker"),
              name: 'legend-item-marker',
              attrs: markerAttrs,
          });
          var bbox = shape.getBBox();
          shape.attr('x', bbox.width / 2); // marker 需要左对齐，所以不能占用左侧的空间
          var _a = shape.attr(), stroke = _a.stroke, fill = _a.fill;
          if (stroke) {
              shape.set('isStroke', true);
          }
          if (fill) {
              shape.set('isFill', true);
          }
          return shape;
      };
      // 绘制文本
      Category.prototype.drawItemText = function (container, textName, cfg, item, itemHeight, xPosition, index) {
          var formatter = cfg.formatter;
          var attrs = __assign({ x: xPosition, y: itemHeight / 2, text: formatter ? formatter(item[textName], item, index) : item[textName] }, cfg.style);
          return this.addShape(container, {
              type: 'text',
              id: this.getElementId("item-" + item.id + "-" + textName),
              name: "legend-item-" + textName,
              attrs: attrs,
          });
      };
      // 绘制图例项
      Category.prototype.drawItem = function (item, index, itemHeight, itemGroup) {
          var groupId = "item-" + item.id;
          // 设置单独的 Group 用于 setClip
          var subContainer = this.addGroup(itemGroup, {
              name: 'legend-item-container',
              id: this.getElementId("item-container-" + groupId),
              delegateObject: {
                  item: item,
                  index: index,
              },
          });
          var subGroup = this.addGroup(subContainer, {
              name: 'legend-item',
              id: this.getElementId(groupId),
              delegateObject: {
                  item: item,
                  index: index,
              },
          });
          var marker = this.get('marker');
          var itemName = this.get('itemName');
          var itemValue = this.get('itemValue');
          var itemBackground = this.get('itemBackground');
          var itemWidth = this.getLimitItemWidth();
          var curX = 0; // 记录当前 x 的位置
          if (marker) {
              var markerShape = this.drawMarker(subGroup, marker, item, itemHeight);
              curX = markerShape.getBBox().maxX + marker.spacing;
          }
          if (itemName) {
              var nameShape = this.drawItemText(subGroup, 'name', itemName, item, itemHeight, curX, index);
              if (itemWidth) {
                  // 设置了 item 的最大宽度限制，并且超出了，进行省略处理
                  ellipsisLabel(true, nameShape, clamp(itemWidth - curX, 0, itemWidth));
              }
              curX = nameShape.getBBox().maxX + itemName.spacing;
          }
          if (itemValue) {
              var valueShape = this.drawItemText(subGroup, 'value', itemValue, item, itemHeight, curX, index);
              if (itemWidth) {
                  if (itemValue.alignRight) {
                      valueShape.attr({
                          textAlign: 'right',
                          x: itemWidth,
                      });
                      ellipsisLabel(true, valueShape, clamp(itemWidth - curX, 0, itemWidth), 'head');
                  }
                  else {
                      ellipsisLabel(true, valueShape, clamp(itemWidth - curX, 0, itemWidth));
                  }
              }
          }
          // 添加透明的背景，便于拾取和包围盒计算
          if (itemBackground) {
              var bbox = subGroup.getBBox();
              var backShape = this.addShape(subGroup, {
                  type: 'rect',
                  name: 'legend-item-background',
                  id: this.getElementId(groupId + "-background"),
                  attrs: __assign({ x: 0, y: 0, width: bbox.width, height: itemHeight }, itemBackground.style),
              });
              backShape.toBack();
          }
          this.applyItemStates(item, subGroup);
          return subGroup;
      };
      // 加上分页器并重新排序 items
      Category.prototype.adjustNavigation = function (container, itemGroup) {
          var _this = this;
          var startX = this.startX;
          var startY = this.startY;
          var layout = this.get('layout');
          var subGroups = itemGroup.findAll(function (item) { return item.get('name') === 'legend-item'; });
          var maxWidth = this.get('maxWidth');
          var maxHeight = this.get('maxHeight');
          var itemWidth = this.get('itemWidth');
          var itemSpacing = this.get('itemSpacing');
          var itemHeight = this.getItemHeight();
          var navigation = this.drawNavigation(container, layout, '00/00', 12);
          var navigationBBox = navigation.getBBox();
          var currentPoint = { x: startX, y: startY };
          var pages = 1;
          var widthLimit = 0;
          var pageWidth = 0;
          var maxItemWidth = 0;
          if (layout === 'horizontal') {
              this.pageHeight = itemHeight;
              each(subGroups, function (item) {
                  var bbox = item.getBBox();
                  var width = itemWidth || bbox.width;
                  if ((widthLimit && widthLimit < currentPoint.x + width + itemSpacing) ||
                      maxWidth < currentPoint.x + width + itemSpacing + navigationBBox.width) {
                      if (pages === 1) {
                          widthLimit = currentPoint.x + itemSpacing;
                          _this.pageWidth = widthLimit;
                          _this.moveElementTo(navigation, {
                              x: maxWidth - itemSpacing - navigationBBox.width - navigationBBox.minX,
                              y: currentPoint.y + itemHeight / 2 - navigationBBox.height / 2 - navigationBBox.minY,
                          });
                      }
                      pages += 1;
                      currentPoint.x = startX;
                      currentPoint.y += itemHeight;
                  }
                  _this.moveElementTo(item, currentPoint);
                  item.getParent().setClip({
                      type: 'rect',
                      attrs: {
                          x: currentPoint.x,
                          y: currentPoint.y,
                          width: width + itemSpacing,
                          height: itemHeight,
                      },
                  });
                  currentPoint.x += width + itemSpacing;
              });
          }
          else {
              each(subGroups, function (item) {
                  var bbox = item.getBBox();
                  if (bbox.width > pageWidth) {
                      pageWidth = bbox.width;
                  }
              });
              maxItemWidth = pageWidth;
              pageWidth += itemSpacing;
              if (maxWidth) {
                  // maxWidth 限制加上
                  pageWidth = Math.min(maxWidth, pageWidth);
                  maxItemWidth = Math.min(maxWidth, maxItemWidth);
              }
              this.pageWidth = pageWidth;
              this.pageHeight = maxHeight - Math.max(navigationBBox.height, itemHeight);
              var cntPerPage_1 = Math.floor(this.pageHeight / itemHeight);
              each(subGroups, function (item, index) {
                  if (index !== 0 && index % cntPerPage_1 === 0) {
                      pages += 1;
                      currentPoint.x += pageWidth;
                      currentPoint.y = startY;
                  }
                  _this.moveElementTo(item, currentPoint);
                  item.getParent().setClip({
                      type: 'rect',
                      attrs: {
                          x: currentPoint.x,
                          y: currentPoint.y,
                          width: pageWidth,
                          height: itemHeight,
                      },
                  });
                  currentPoint.y += itemHeight;
              });
              this.totalPagesCnt = pages;
              this.moveElementTo(navigation, {
                  x: startX + maxItemWidth / 2 - navigationBBox.width / 2 - navigationBBox.minX,
                  y: maxHeight - navigationBBox.height - navigationBBox.minY,
              });
          }
          if (this.pageHeight && this.pageWidth) {
              // 为了使固定的 clip 生效，clip 设置在 itemContainerGroup 上，itemGroup 需要在翻页时会设置 matrix
              itemGroup.getParent().setClip({
                  type: 'rect',
                  attrs: {
                      x: this.startX,
                      y: this.startY,
                      width: this.pageWidth,
                      height: this.pageHeight,
                  },
              });
          }
          this.totalPagesCnt = pages;
          if (this.currentPageIndex > this.totalPagesCnt) {
              this.currentPageIndex = 1;
          }
          this.updateNavigation(navigation);
          // update initial matrix
          itemGroup.attr('matrix', this.getCurrentNavigationMatrix());
      };
      Category.prototype.drawNavigation = function (group, layout, text, size) {
          var currentPoint = { x: 0, y: 0 };
          var subGroup = this.addGroup(group, {
              id: this.getElementId('navigation-group'),
              name: 'legend-navigation',
          });
          var leftArrow = this.drawArrow(subGroup, currentPoint, 'navigation-arrow-left', layout === 'horizontal' ? 'up' : 'left', size);
          leftArrow.on('click', this.onNavigationBack);
          var leftArrowBBox = leftArrow.getBBox();
          currentPoint.x += leftArrowBBox.width + 2;
          var textShape = this.addShape(subGroup, {
              type: 'text',
              id: this.getElementId('navigation-text'),
              name: 'navigation-text',
              attrs: {
                  x: currentPoint.x,
                  y: currentPoint.y + size / 2,
                  text: text,
                  fontSize: 12,
                  fill: '#ccc',
                  textBaseline: 'middle',
              },
          });
          var textBBox = textShape.getBBox();
          currentPoint.x += textBBox.width + 2;
          var rightArrow = this.drawArrow(subGroup, currentPoint, 'navigation-arrow-right', layout === 'horizontal' ? 'down' : 'right', size);
          rightArrow.on('click', this.onNavigationAfter);
          return subGroup;
      };
      Category.prototype.updateNavigation = function (navigation) {
          var text = this.currentPageIndex + "/" + this.totalPagesCnt;
          var textShape = navigation ? navigation.getChildren()[1] : this.getElementByLocalId('navigation-text');
          var leftArrow = navigation
              ? navigation.findById(this.getElementId('navigation-arrow-left'))
              : this.getElementByLocalId('navigation-arrow-left');
          var rightArrow = navigation
              ? navigation.findById(this.getElementId('navigation-arrow-right'))
              : this.getElementByLocalId('navigation-arrow-right');
          var origBBox = textShape.getBBox();
          textShape.attr('text', text);
          var newBBox = textShape.getBBox();
          textShape.attr('x', textShape.attr('x') - (newBBox.width - origBBox.width) / 2);
          leftArrow.attr('opacity', this.currentPageIndex === 1 ? 0.45 : 1);
          leftArrow.attr('cursor', this.currentPageIndex === 1 ? 'not-allowed' : 'pointer');
          rightArrow.attr('opacity', this.currentPageIndex === this.totalPagesCnt ? 0.45 : 1);
          rightArrow.attr('cursor', this.currentPageIndex === this.totalPagesCnt ? 'not-allowed' : 'pointer');
      };
      Category.prototype.drawArrow = function (group, currentPoint, name, direction, size) {
          var x = currentPoint.x, y = currentPoint.y;
          var rotateMap = {
              right: (90 * Math.PI) / 180,
              left: ((360 - 90) * Math.PI) / 180,
              up: 0,
              down: (180 * Math.PI) / 180,
          };
          var shape = this.addShape(group, {
              type: 'path',
              id: this.getElementId(name),
              name: name,
              attrs: {
                  path: [['M', x + size / 2, y], ['L', x, y + size], ['L', x + size, y + size], ['Z']],
                  fill: '#000',
                  cursor: 'pointer',
              },
          });
          shape.attr('matrix', getMatrixByAngle({ x: x + size / 2, y: y + size / 2 }, rotateMap[direction]));
          return shape;
      };
      Category.prototype.getCurrentNavigationMatrix = function () {
          var _a = this, currentPageIndex = _a.currentPageIndex, pageWidth = _a.pageWidth, pageHeight = _a.pageHeight;
          var layout = this.get('layout');
          var translate = layout === 'horizontal'
              ? {
                  x: 0,
                  y: pageHeight * (1 - currentPageIndex),
              }
              : {
                  x: pageWidth * (1 - currentPageIndex),
                  y: 0,
              };
          return getMatrixByTranslate(translate);
      };
      // 附加状态对应的样式
      Category.prototype.applyItemStates = function (item, subGroup) {
          var states = this.getItemStates(item);
          var hasStates = states.length > 0;
          if (hasStates) {
              var children = subGroup.getChildren();
              var itemStates_1 = this.get('itemStates');
              each(children, function (element) {
                  var name = element.get('name');
                  var elName = name.split('-')[2]; // marker, name, value
                  var statesStyle = getStatesStyle(item, elName, itemStates_1);
                  if (statesStyle) {
                      element.attr(statesStyle);
                      if (elName === 'marker' && !(element.get('isStroke') && element.get('isFill'))) {
                          // 如果 marker 是单填充或者单描边的话，就不要额外添加 stroke 或这 fill 属性，否则会影响 unchecked 后的显示
                          if (element.get('isStroke')) {
                              element.attr('fill', null);
                          }
                          if (element.get('isFill')) {
                              element.attr('stroke', null);
                          }
                      }
                  }
              });
          }
      };
      // 获取 itemWidth 的最终设置
      Category.prototype.getLimitItemWidth = function () {
          var itemWidth = this.get('itemWidth');
          var maxItemWidth = this.get('maxItemWidth');
          if (maxItemWidth) {
              // 设置了最大宽度
              if (itemWidth) {
                  maxItemWidth = itemWidth <= maxItemWidth ? itemWidth : maxItemWidth;
              }
          }
          else if (itemWidth) {
              maxItemWidth = itemWidth;
          }
          return maxItemWidth;
      };
      return Category;
  }(LegendBase));
  export default Category;
  //# sourceMappingURL=category.js.map