
/*
* 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.
 */

import { __extends } from "tslib";
import { bind, each, indexOf, curry, extend, retrieve, normalizeCssArray } from 'zrender/esm/core/util';
import * as graphic from '../../util/graphic';
import { getECData } from '../../util/ecData';
import { isHighDownDispatcher, setAsHighDownDispatcher, setDefaultStateProxy, enableHoverFocus } from '../../util/states';
import DataDiffer from '../../data/DataDiffer';
import * as helper from '../helper/treeHelper';
import Breadcrumb from './Breadcrumb';
import RoamController from '../../component/helper/RoamController';
import BoundingRect from 'zrender/esm/core/BoundingRect';
import * as matrix from 'zrender/esm/core/matrix';
import * as animationUtil from '../../util/animation';
import makeStyleMapper from '../../model/mixin/makeStyleMapper';
import ChartView from '../../view/Chart';
import Displayable from 'zrender/esm/graphic/Displayable';
import { makeInner } from '../../util/model';
import { windowOpen } from '../../util/format';
import { setLabelStyle, getLabelStatesModels } from '../../label/labelStyle';
var Group = graphic.Group;
var Rect = graphic.Rect;
var DRAG_THRESHOLD = 3;
var PATH_LABEL_NOAMAL = 'label';
var PATH_UPPERLABEL_NORMAL = 'upperLabel';
var Z_BASE = 10;
var Z_BG = 1;
var Z_CONTENT = 2;
var getStateItemStyle = makeStyleMapper([['fill', 'color'], ['stroke', 'strokeColor'], ['lineWidth', 'strokeWidth'], ['shadowBlur'], ['shadowOffsetX'], ['shadowOffsetY'], ['shadowColor']]);

var getItemStyleNormal = function (model) {
  var itemStyle = getStateItemStyle(model);
  itemStyle.stroke = itemStyle.fill = itemStyle.lineWidth = null;
  return itemStyle;
};

var inner = makeInner();

var TreemapView = function (_super) {
  __extends(TreemapView, _super);

  function TreemapView() {
    var _this = _super !== null && _super.apply(this, arguments) || this;

    _this.type = TreemapView.type;
    _this._state = 'ready';
    _this._storage = createStorage();
    return _this;
  }

  TreemapView.prototype.render = function (seriesModel, ecModel, api, payload) {
    var models = ecModel.findComponents({
      mainType: 'series',
      subType: 'treemap',
      query: payload
    });

    if (indexOf(models, seriesModel) < 0) {
      return;
    }

    this.seriesModel = seriesModel;
    this.api = api;
    this.ecModel = ecModel;
    var types = ['treemapZoomToNode', 'treemapRootToNode'];
    var targetInfo = helper.retrieveTargetInfo(payload, types, seriesModel);
    var payloadType = payload && payload.type;
    var layoutInfo = seriesModel.layoutInfo;
    var isInit = !this._oldTree;
    var thisStorage = this._storage;
    var reRoot = payloadType === 'treemapRootToNode' && targetInfo && thisStorage ? {
      rootNodeGroup: thisStorage.nodeGroup[targetInfo.node.getRawIndex()],
      direction: payload.direction
    } : null;

    var containerGroup = this._giveContainerGroup(layoutInfo);

    var renderResult = this._doRender(containerGroup, seriesModel, reRoot);

    !isInit && (!payloadType || payloadType === 'treemapZoomToNode' || payloadType === 'treemapRootToNode') ? this._doAnimation(containerGroup, renderResult, seriesModel, reRoot) : renderResult.renderFinally();

    this._resetController(api);

    this._renderBreadcrumb(seriesModel, api, targetInfo);
  };

  TreemapView.prototype._giveContainerGroup = function (layoutInfo) {
    var containerGroup = this._containerGroup;

    if (!containerGroup) {
      containerGroup = this._containerGroup = new Group();

      this._initEvents(containerGroup);

      this.group.add(containerGroup);
    }

    containerGroup.x = layoutInfo.x;
    containerGroup.y = layoutInfo.y;
    return containerGroup;
  };

  TreemapView.prototype._doRender = function (containerGroup, seriesModel, reRoot) {
    var thisTree = seriesModel.getData().tree;
    var oldTree = this._oldTree;
    var lastsForAnimation = createStorage();
    var thisStorage = createStorage();
    var oldStorage = this._storage;
    var willInvisibleEls = [];

    function doRenderNode(thisNode, oldNode, parentGroup, depth) {
      return renderNode(seriesModel, thisStorage, oldStorage, reRoot, lastsForAnimation, willInvisibleEls, thisNode, oldNode, parentGroup, depth);
    }

    dualTravel(thisTree.root ? [thisTree.root] : [], oldTree && oldTree.root ? [oldTree.root] : [], containerGroup, thisTree === oldTree || !oldTree, 0);
    var willDeleteEls = clearStorage(oldStorage);
    this._oldTree = thisTree;
    this._storage = thisStorage;
    return {
      lastsForAnimation: lastsForAnimation,
      willDeleteEls: willDeleteEls,
      renderFinally: renderFinally
    };

    function dualTravel(thisViewChildren, oldViewChildren, parentGroup, sameTree, depth) {
      if (sameTree) {
        oldViewChildren = thisViewChildren;
        each(thisViewChildren, function (child, index) {
          !child.isRemoved() && processNode(index, index);
        });
      } else {
        new DataDiffer(oldViewChildren, thisViewChildren, getKey, getKey).add(processNode).update(processNode).remove(curry(processNode, null)).execute();
      }

      function getKey(node) {
        return node.getId();
      }

      function processNode(newIndex, oldIndex) {
        var thisNode = newIndex != null ? thisViewChildren[newIndex] : null;
        var oldNode = oldIndex != null ? oldViewChildren[oldIndex] : null;
        var group = doRenderNode(thisNode, oldNode, parentGroup, depth);
        group && dualTravel(thisNode && thisNode.viewChildren || [], oldNode && oldNode.viewChildren || [], group, sameTree, depth + 1);
      }
    }

    function clearStorage(storage) {
      var willDeleteEls = createStorage();
      storage && each(storage, function (store, storageName) {
        var delEls = willDeleteEls[storageName];
        each(store, function (el) {
          el && (delEls.push(el), inner(el).willDelete = true);
        });
      });
      return willDeleteEls;
    }

    function renderFinally() {
      each(willDeleteEls, function (els) {
        each(els, function (el) {
          el.parent && el.parent.remove(el);
        });
      });
      each(willInvisibleEls, function (el) {
        el.invisible = true;
        el.dirty();
      });
    }
  };

  TreemapView.prototype._doAnimation = function (containerGroup, renderResult, seriesModel, reRoot) {
    if (!seriesModel.get('animation')) {
      return;
    }

    var duration = seriesModel.get('animationDurationUpdate');
    var easing = seriesModel.get('animationEasing');
    var animationWrap = animationUtil.createWrap();
    each(renderResult.willDeleteEls, function (store, storageName) {
      each(store, function (el, rawIndex) {
        if (el.invisible) {
          return;
        }

        var parent = el.parent;
        var target;
        var innerStore = inner(parent);

        if (reRoot && reRoot.direction === 'drillDown') {
          target = parent === reRoot.rootNodeGroup ? {
            shape: {
              x: 0,
              y: 0,
              width: innerStore.nodeWidth,
              height: innerStore.nodeHeight
            },
            style: {
              opacity: 0
            }
          } : {
            style: {
              opacity: 0
            }
          };
        } else {
          var targetX = 0;
          var targetY = 0;

          if (!innerStore.willDelete) {
            targetX = innerStore.nodeWidth / 2;
            targetY = innerStore.nodeHeight / 2;
          }

          target = storageName === 'nodeGroup' ? {
            x: targetX,
            y: targetY,
            style: {
              opacity: 0
            }
          } : {
            shape: {
              x: targetX,
              y: targetY,
              width: 0,
              height: 0
            },
            style: {
              opacity: 0
            }
          };
        }

        target && animationWrap.add(el, target, duration, easing);
      });
    });
    each(this._storage, function (store, storageName) {
      each(store, function (el, rawIndex) {
        var last = renderResult.lastsForAnimation[storageName][rawIndex];
        var target = {};

        if (!last) {
          return;
        }

        if (el instanceof graphic.Group) {
          if (last.oldX != null) {
            target.x = el.x;
            target.y = el.y;
            el.x = last.oldX;
            el.y = last.oldY;
          }
        } else {
          if (last.oldShape) {
            target.shape = extend({}, el.shape);
            el.setShape(last.oldShape);
          }

          if (last.fadein) {
            el.setStyle('opacity', 0);
            target.style = {
              opacity: 1
            };
          } else if (el.style.opacity !== 1) {
            target.style = {
              opacity: 1
            };
          }
        }

        animationWrap.add(el, target, duration, easing);
      });
    }, this);
    this._state = 'animating';
    animationWrap.done(bind(function () {
      this._state = 'ready';
      renderResult.renderFinally();
    }, this)).start();
  };

  TreemapView.prototype._resetController = function (api) {
    var controller = this._controller;

    if (!controller) {
      controller = this._controller = new RoamController(api.getZr());
      controller.enable(this.seriesModel.get('roam'));
      controller.on('pan', bind(this._onPan, this));
      controller.on('zoom', bind(this._onZoom, this));
    }

    var rect = new BoundingRect(0, 0, api.getWidth(), api.getHeight());
    controller.setPointerChecker(function (e, x, y) {
      return rect.contain(x, y);
    });
  };

  TreemapView.prototype._clearController = function () {
    var controller = this._controller;

    if (controller) {
      controller.dispose();
      controller = null;
    }
  };

  TreemapView.prototype._onPan = function (e) {
    if (this._state !== 'animating' && (Math.abs(e.dx) > DRAG_THRESHOLD || Math.abs(e.dy) > DRAG_THRESHOLD)) {
      var root = this.seriesModel.getData().tree.root;

      if (!root) {
        return;
      }

      var rootLayout = root.getLayout();

      if (!rootLayout) {
        return;
      }

      this.api.dispatchAction({
        type: 'treemapMove',
        from: this.uid,
        seriesId: this.seriesModel.id,
        rootRect: {
          x: rootLayout.x + e.dx,
          y: rootLayout.y + e.dy,
          width: rootLayout.width,
          height: rootLayout.height
        }
      });
    }
  };

  TreemapView.prototype._onZoom = function (e) {
    var mouseX = e.originX;
    var mouseY = e.originY;

    if (this._state !== 'animating') {
      var root = this.seriesModel.getData().tree.root;

      if (!root) {
        return;
      }

      var rootLayout = root.getLayout();

      if (!rootLayout) {
        return;
      }

      var rect = new BoundingRect(rootLayout.x, rootLayout.y, rootLayout.width, rootLayout.height);
      var layoutInfo = this.seriesModel.layoutInfo;
      mouseX -= layoutInfo.x;
      mouseY -= layoutInfo.y;
      var m = matrix.create();
      matrix.translate(m, m, [-mouseX, -mouseY]);
      matrix.scale(m, m, [e.scale, e.scale]);
      matrix.translate(m, m, [mouseX, mouseY]);
      rect.applyTransform(m);
      this.api.dispatchAction({
        type: 'treemapRender',
        from: this.uid,
        seriesId: this.seriesModel.id,
        rootRect: {
          x: rect.x,
          y: rect.y,
          width: rect.width,
          height: rect.height
        }
      });
    }
  };

  TreemapView.prototype._initEvents = function (containerGroup) {
    var _this = this;

    containerGroup.on('click', function (e) {
      if (_this._state !== 'ready') {
        return;
      }

      var nodeClick = _this.seriesModel.get('nodeClick', true);

      if (!nodeClick) {
        return;
      }

      var targetInfo = _this.findTarget(e.offsetX, e.offsetY);

      if (!targetInfo) {
        return;
      }

      var node = targetInfo.node;

      if (node.getLayout().isLeafRoot) {
        _this._rootToNode(targetInfo);
      } else {
        if (nodeClick === 'zoomToNode') {
          _this._zoomToNode(targetInfo);
        } else if (nodeClick === 'link') {
          var itemModel = node.hostTree.data.getItemModel(node.dataIndex);
          var link = itemModel.get('link', true);
          var linkTarget = itemModel.get('target', true) || 'blank';
          link && windowOpen(link, linkTarget);
        }
      }
    }, this);
  };

  TreemapView.prototype._renderBreadcrumb = function (seriesModel, api, targetInfo) {
    var _this = this;

    if (!targetInfo) {
      targetInfo = seriesModel.get('leafDepth', true) != null ? {
        node: seriesModel.getViewRoot()
      } : this.findTarget(api.getWidth() / 2, api.getHeight() / 2);

      if (!targetInfo) {
        targetInfo = {
          node: seriesModel.getData().tree.root
        };
      }
    }

    (this._breadcrumb || (this._breadcrumb = new Breadcrumb(this.group))).render(seriesModel, api, targetInfo.node, function (node) {
      if (_this._state !== 'animating') {
        helper.aboveViewRoot(seriesModel.getViewRoot(), node) ? _this._rootToNode({
          node: node
        }) : _this._zoomToNode({
          node: node
        });
      }
    });
  };

  TreemapView.prototype.remove = function () {
    this._clearController();

    this._containerGroup && this._containerGroup.removeAll();
    this._storage = createStorage();
    this._state = 'ready';
    this._breadcrumb && this._breadcrumb.remove();
  };

  TreemapView.prototype.dispose = function () {
    this._clearController();
  };

  TreemapView.prototype._zoomToNode = function (targetInfo) {
    this.api.dispatchAction({
      type: 'treemapZoomToNode',
      from: this.uid,
      seriesId: this.seriesModel.id,
      targetNode: targetInfo.node
    });
  };

  TreemapView.prototype._rootToNode = function (targetInfo) {
    this.api.dispatchAction({
      type: 'treemapRootToNode',
      from: this.uid,
      seriesId: this.seriesModel.id,
      targetNode: targetInfo.node
    });
  };

  TreemapView.prototype.findTarget = function (x, y) {
    var targetInfo;
    var viewRoot = this.seriesModel.getViewRoot();
    viewRoot.eachNode({
      attr: 'viewChildren',
      order: 'preorder'
    }, function (node) {
      var bgEl = this._storage.background[node.getRawIndex()];

      if (bgEl) {
        var point = bgEl.transformCoordToLocal(x, y);
        var shape = bgEl.shape;

        if (shape.x <= point[0] && point[0] <= shape.x + shape.width && shape.y <= point[1] && point[1] <= shape.y + shape.height) {
          targetInfo = {
            node: node,
            offsetX: point[0],
            offsetY: point[1]
          };
        } else {
          return false;
        }
      }
    }, this);
    return targetInfo;
  };

  TreemapView.type = 'treemap';
  return TreemapView;
}(ChartView);

function createStorage() {
  return {
    nodeGroup: [],
    background: [],
    content: []
  };
}

function renderNode(seriesModel, thisStorage, oldStorage, reRoot, lastsForAnimation, willInvisibleEls, thisNode, oldNode, parentGroup, depth) {
  if (!thisNode) {
    return;
  }

  var thisLayout = thisNode.getLayout();
  var data = seriesModel.getData();
  var nodeModel = thisNode.getModel();
  data.setItemGraphicEl(thisNode.dataIndex, null);

  if (!thisLayout || !thisLayout.isInView) {
    return;
  }

  var thisWidth = thisLayout.width;
  var thisHeight = thisLayout.height;
  var borderWidth = thisLayout.borderWidth;
  var thisInvisible = thisLayout.invisible;
  var thisRawIndex = thisNode.getRawIndex();
  var oldRawIndex = oldNode && oldNode.getRawIndex();
  var thisViewChildren = thisNode.viewChildren;
  var upperHeight = thisLayout.upperHeight;
  var isParent = thisViewChildren && thisViewChildren.length;
  var itemStyleNormalModel = nodeModel.getModel('itemStyle');
  var itemStyleEmphasisModel = nodeModel.getModel(['emphasis', 'itemStyle']);
  var itemStyleBlurModel = nodeModel.getModel(['blur', 'itemStyle']);
  var itemStyleSelectModel = nodeModel.getModel(['select', 'itemStyle']);
  var borderRadius = itemStyleNormalModel.get('borderRadius') || 0;
  var group = giveGraphic('nodeGroup', Group);

  if (!group) {
    return;
  }

  parentGroup.add(group);
  group.x = thisLayout.x || 0;
  group.y = thisLayout.y || 0;
  group.markRedraw();
  inner(group).nodeWidth = thisWidth;
  inner(group).nodeHeight = thisHeight;

  if (thisLayout.isAboveViewRoot) {
    return group;
  }

  var bg = giveGraphic('background', Rect, depth, Z_BG);
  bg && renderBackground(group, bg, isParent && thisLayout.upperLabelHeight);
  var focus = nodeModel.get(['emphasis', 'focus']);
  var blurScope = nodeModel.get(['emphasis', 'blurScope']);
  var focusDataIndices = focus === 'ancestor' ? thisNode.getAncestorsIndices() : focus === 'descendant' ? thisNode.getDescendantIndices() : null;

  if (isParent) {
    if (isHighDownDispatcher(group)) {
      setAsHighDownDispatcher(group, false);
    }

    if (bg) {
      setAsHighDownDispatcher(bg, true);
      data.setItemGraphicEl(thisNode.dataIndex, bg);
      enableHoverFocus(bg, focusDataIndices || focus, blurScope);
    }
  } else {
    var content = giveGraphic('content', Rect, depth, Z_CONTENT);
    content && renderContent(group, content);

    if (bg && isHighDownDispatcher(bg)) {
      setAsHighDownDispatcher(bg, false);
    }

    setAsHighDownDispatcher(group, true);
    data.setItemGraphicEl(thisNode.dataIndex, group);
    enableHoverFocus(group, focusDataIndices || focus, blurScope);
  }

  return group;

  function renderBackground(group, bg, useUpperLabel) {
    var ecData = getECData(bg);
    ecData.dataIndex = thisNode.dataIndex;
    ecData.seriesIndex = seriesModel.seriesIndex;
    bg.setShape({
      x: 0,
      y: 0,
      width: thisWidth,
      height: thisHeight,
      r: borderRadius
    });

    if (thisInvisible) {
      processInvisible(bg);
    } else {
      bg.invisible = false;
      var visualBorderColor = thisNode.getVisual('style').stroke;
      var normalStyle = getItemStyleNormal(itemStyleNormalModel);
      normalStyle.fill = visualBorderColor;
      var emphasisStyle = getStateItemStyle(itemStyleEmphasisModel);
      emphasisStyle.fill = itemStyleEmphasisModel.get('borderColor');
      var blurStyle = getStateItemStyle(itemStyleBlurModel);
      blurStyle.fill = itemStyleBlurModel.get('borderColor');
      var selectStyle = getStateItemStyle(itemStyleSelectModel);
      selectStyle.fill = itemStyleSelectModel.get('borderColor');

      if (useUpperLabel) {
        var upperLabelWidth = thisWidth - 2 * borderWidth;
        prepareText(bg, visualBorderColor, upperLabelWidth, upperHeight, {
          x: borderWidth,
          y: 0,
          width: upperLabelWidth,
          height: upperHeight
        });
      } else {
        bg.removeTextContent();
      }

      bg.setStyle(normalStyle);
      bg.ensureState('emphasis').style = emphasisStyle;
      bg.ensureState('blur').style = blurStyle;
      bg.ensureState('select').style = selectStyle;
      setDefaultStateProxy(bg);
    }

    group.add(bg);
  }

  function renderContent(group, content) {
    var ecData = getECData(content);
    ecData.dataIndex = thisNode.dataIndex;
    ecData.seriesIndex = seriesModel.seriesIndex;
    var contentWidth = Math.max(thisWidth - 2 * borderWidth, 0);
    var contentHeight = Math.max(thisHeight - 2 * borderWidth, 0);
    content.culling = true;
    content.setShape({
      x: borderWidth,
      y: borderWidth,
      width: contentWidth,
      height: contentHeight,
      r: borderRadius
    });

    if (thisInvisible) {
      processInvisible(content);
    } else {
      content.invisible = false;
      var visualColor = thisNode.getVisual('style').fill;
      var normalStyle = getItemStyleNormal(itemStyleNormalModel);
      normalStyle.fill = visualColor;
      var emphasisStyle = getStateItemStyle(itemStyleEmphasisModel);
      var blurStyle = getStateItemStyle(itemStyleBlurModel);
      var selectStyle = getStateItemStyle(itemStyleSelectModel);
      prepareText(content, visualColor, contentWidth, contentHeight);
      content.setStyle(normalStyle);
      content.ensureState('emphasis').style = emphasisStyle;
      content.ensureState('blur').style = blurStyle;
      content.ensureState('select').style = selectStyle;
      setDefaultStateProxy(content);
    }

    group.add(content);
  }

  function processInvisible(element) {
    !element.invisible && willInvisibleEls.push(element);
  }

  function prepareText(rectEl, visualColor, width, height, upperLabelRect) {
    var normalLabelModel = nodeModel.getModel(upperLabelRect ? PATH_UPPERLABEL_NORMAL : PATH_LABEL_NOAMAL);
    var text = retrieve(seriesModel.getFormattedLabel(thisNode.dataIndex, 'normal', null, null, normalLabelModel.get('formatter')), nodeModel.get('name'));

    if (!upperLabelRect && thisLayout.isLeafRoot) {
      var iconChar = seriesModel.get('drillDownIcon', true);
      text = iconChar ? iconChar + ' ' + text : text;
    }

    var isShow = normalLabelModel.getShallow('show');
    setLabelStyle(rectEl, getLabelStatesModels(nodeModel, upperLabelRect ? PATH_UPPERLABEL_NORMAL : PATH_LABEL_NOAMAL), {
      defaultText: isShow ? text : null,
      inheritColor: visualColor,
      labelFetcher: seriesModel,
      labelDataIndex: thisNode.dataIndex
    });
    var textEl = rectEl.getTextContent();
    var textStyle = textEl.style;
    var textPadding = normalizeCssArray(textStyle.padding || 0);

    if (upperLabelRect) {
      rectEl.setTextConfig({
        layoutRect: upperLabelRect
      });
      textEl.disableLabelLayout = true;
    }

    textEl.beforeUpdate = function () {
      var width = Math.max((upperLabelRect ? upperLabelRect.width : rectEl.shape.width) - textPadding[1] - textPadding[3], 0);
      var height = Math.max((upperLabelRect ? upperLabelRect.height : rectEl.shape.height) - textPadding[0] - textPadding[2], 0);

      if (textStyle.width !== width || textStyle.height !== height) {
        textEl.setStyle({
          width: width,
          height: height
        });
      }
    };

    textStyle.truncateMinChar = 2;
    textStyle.lineOverflow = 'truncate';
    addDrillDownIcon(textStyle, upperLabelRect, thisLayout);
    var textEmphasisState = textEl.getState('emphasis');
    addDrillDownIcon(textEmphasisState ? textEmphasisState.style : null, upperLabelRect, thisLayout);
  }

  function addDrillDownIcon(style, upperLabelRect, thisLayout) {
    var text = style ? style.text : null;

    if (!upperLabelRect && thisLayout.isLeafRoot && text != null) {
      var iconChar = seriesModel.get('drillDownIcon', true);
      style.text = iconChar ? iconChar + ' ' + text : text;
    }
  }

  function giveGraphic(storageName, Ctor, depth, z) {
    var element = oldRawIndex != null && oldStorage[storageName][oldRawIndex];
    var lasts = lastsForAnimation[storageName];

    if (element) {
      oldStorage[storageName][oldRawIndex] = null;
      prepareAnimationWhenHasOld(lasts, element);
    } else if (!thisInvisible) {
      element = new Ctor();

      if (element instanceof Displayable) {
        element.z = calculateZ(depth, z);
      }

      prepareAnimationWhenNoOld(lasts, element);
    }

    return thisStorage[storageName][thisRawIndex] = element;
  }

  function prepareAnimationWhenHasOld(lasts, element) {
    var lastCfg = lasts[thisRawIndex] = {};

    if (element instanceof Group) {
      lastCfg.oldX = element.x;
      lastCfg.oldY = element.y;
    } else {
      lastCfg.oldShape = extend({}, element.shape);
    }
  }

  function prepareAnimationWhenNoOld(lasts, element) {
    var lastCfg = lasts[thisRawIndex] = {};
    var parentNode = thisNode.parentNode;
    var isGroup = element instanceof graphic.Group;

    if (parentNode && (!reRoot || reRoot.direction === 'drillDown')) {
      var parentOldX = 0;
      var parentOldY = 0;
      var parentOldBg = lastsForAnimation.background[parentNode.getRawIndex()];

      if (!reRoot && parentOldBg && parentOldBg.oldShape) {
        parentOldX = parentOldBg.oldShape.width;
        parentOldY = parentOldBg.oldShape.height;
      }

      if (isGroup) {
        lastCfg.oldX = 0;
        lastCfg.oldY = parentOldY;
      } else {
        lastCfg.oldShape = {
          x: parentOldX,
          y: parentOldY,
          width: 0,
          height: 0
        };
      }
    }

    lastCfg.fadein = !isGroup;
  }
}

function calculateZ(depth, zInLevel) {
  var zb = depth * Z_BASE + zInLevel;
  return (zb - 1) / zb;
}

ChartView.registerClass(TreemapView);