first commit
This commit is contained in:
+466
@@ -0,0 +1,466 @@
|
||||
|
||||
/*
|
||||
* 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 { getLayoutRect } from '../../util/layout.js';
|
||||
import { ListIterator } from '../../util/model.js';
|
||||
import { eqNaN, isArray, retrieve2 } from 'zrender/lib/core/util.js';
|
||||
import { WH, XY } from '../../util/graphic.js';
|
||||
import Model from '../../model/Model.js';
|
||||
import { mathMax, mathMin, parsePositionSizeOption } from '../../util/number.js';
|
||||
import { createNaNRectLike, MatrixClampOption, MatrixCellLayoutInfoType, parseCoordRangeOption, resetXYLocatorRange, xyLocatorRangeToRectOneDim } from './matrixCoordHelper.js';
|
||||
import { error } from '../../util/log.js';
|
||||
import { injectCoordSysByOption, simpleCoordSysInjectionProvider } from '../../core/CoordinateSystem.js';
|
||||
var Matrix = /** @class */function () {
|
||||
function Matrix(matrixModel, ecModel, api) {
|
||||
this.dimensions = Matrix.dimensions;
|
||||
this.type = 'matrix';
|
||||
this._model = matrixModel;
|
||||
var models = this._dimModels = {
|
||||
x: matrixModel.getDimensionModel('x'),
|
||||
y: matrixModel.getDimensionModel('y')
|
||||
};
|
||||
this._dims = {
|
||||
x: models.x.dim,
|
||||
y: models.y.dim
|
||||
};
|
||||
this._resize(matrixModel, api);
|
||||
}
|
||||
/**
|
||||
* @see fetchers in `model/referHelper.ts`,
|
||||
* which is used to parse data in ordinal way.
|
||||
* In most series only 'x' and 'y' is required,
|
||||
* but some series, such as heatmap, can specify value.
|
||||
*/
|
||||
Matrix.getDimensionsInfo = function () {
|
||||
return [{
|
||||
name: 'x',
|
||||
type: 'ordinal'
|
||||
}, {
|
||||
name: 'y',
|
||||
type: 'ordinal'
|
||||
}, {
|
||||
name: 'value'
|
||||
}];
|
||||
};
|
||||
Matrix.create = function (ecModel, api) {
|
||||
var matrixList = [];
|
||||
ecModel.eachComponent('matrix', function (matrixModel) {
|
||||
var matrix = new Matrix(matrixModel, ecModel, api);
|
||||
matrixList.push(matrix);
|
||||
matrixModel.coordinateSystem = matrix;
|
||||
});
|
||||
// Inject coordinate system
|
||||
// PENDING: optimize to not to travel all components?
|
||||
// (collect relevant components in ecModel only when model update?)
|
||||
ecModel.eachComponent(function (mainType, componentModel) {
|
||||
injectCoordSysByOption({
|
||||
targetModel: componentModel,
|
||||
coordSysType: 'matrix',
|
||||
coordSysProvider: simpleCoordSysInjectionProvider
|
||||
});
|
||||
});
|
||||
return matrixList;
|
||||
};
|
||||
Matrix.prototype.getRect = function () {
|
||||
return this._rect;
|
||||
};
|
||||
Matrix.prototype._resize = function (matrixModel, api) {
|
||||
var dims = this._dims;
|
||||
var dimModels = this._dimModels;
|
||||
var rect = this._rect = getLayoutRect(matrixModel.getBoxLayoutParams(), {
|
||||
width: api.getWidth(),
|
||||
height: api.getHeight()
|
||||
});
|
||||
layOutUnitsOnDimension(dimModels, dims, rect, 0);
|
||||
layOutUnitsOnDimension(dimModels, dims, rect, 1);
|
||||
layOutDimCellsRestInfoByUnit(0, dims);
|
||||
layOutDimCellsRestInfoByUnit(1, dims);
|
||||
layOutBodyCornerCellMerge(this._model.getBody(), dims);
|
||||
layOutBodyCornerCellMerge(this._model.getCorner(), dims);
|
||||
};
|
||||
/**
|
||||
* @implement
|
||||
* - The input is allowed to be `[NaN/null/undefined, xxx]`/`[xxx, NaN/null/undefined]`;
|
||||
* the return is `[NaN, xxxresult]`/`[xxxresult, NaN]` or clamped boundary value if
|
||||
* `clamp` passed. This is for the usage that only get coord on single x or y.
|
||||
* - Alwasy return an numeric array, but never be null/undefined.
|
||||
* If it can not be located or invalid, return `[NaN, NaN]`.
|
||||
*/
|
||||
Matrix.prototype.dataToPoint = function (data, opt, out) {
|
||||
out = out || [];
|
||||
this.dataToLayout(data, opt, _dtpOutDataToLayout);
|
||||
out[0] = _dtpOutDataToLayout.rect.x + _dtpOutDataToLayout.rect.width / 2;
|
||||
out[1] = _dtpOutDataToLayout.rect.y + _dtpOutDataToLayout.rect.height / 2;
|
||||
return out;
|
||||
};
|
||||
/**
|
||||
* @implement
|
||||
* - The input is allowed to be `[NaN/null/undefined, xxx]`/`[xxx, NaN/null/undefined]`;
|
||||
* the return is `{x: NaN, width: NaN, y: xxxresulty, height: xxxresulth}`/
|
||||
* `{y: NaN, height: NaN, x: xxxresultx, width: xxxresultw}` or clamped boundary value
|
||||
* if `clamp` passed. This is for the usage that only get coord on single x or y.
|
||||
* - The returned `out.rect` and `out.matrixXYLocatorRange` is always an object or an 2d-array,
|
||||
* but never be null/undefined. If it cannot be located or invalid, `NaN` is in their
|
||||
* corresponding number props.
|
||||
* - Do not provide `out.contentRect`, because it's allowed to input non-leaf dimension x/y or
|
||||
* a range of x/y, which determines a rect covering multiple cells (even not merged), in which
|
||||
* case the padding and borderWidth can not be determined to make a contentRect. Therefore only
|
||||
* return `out.rect` in any case for consistency. The caller is responsible for adding space to
|
||||
* avoid covering cell borders, if necessary.
|
||||
*/
|
||||
Matrix.prototype.dataToLayout = function (data, opt, out) {
|
||||
var dims = this._dims;
|
||||
out = out || {};
|
||||
var outRect = out.rect = out.rect || {};
|
||||
outRect.x = outRect.y = outRect.width = outRect.height = NaN;
|
||||
var outLocRange = out.matrixXYLocatorRange = resetXYLocatorRange(out.matrixXYLocatorRange);
|
||||
if (!isArray(data)) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
error('Input data must be an array in `convertToLayout`, `convertToPixel`');
|
||||
}
|
||||
return out;
|
||||
}
|
||||
parseCoordRangeOption(outLocRange, null, data, dims, retrieve2(opt && opt.clamp, MatrixClampOption.none));
|
||||
if (!opt || !opt.ignoreMergeCells) {
|
||||
if (!opt || opt.clamp !== MatrixClampOption.corner) {
|
||||
this._model.getBody().expandRangeByCellMerge(outLocRange);
|
||||
}
|
||||
if (!opt || opt.clamp !== MatrixClampOption.body) {
|
||||
this._model.getCorner().expandRangeByCellMerge(outLocRange);
|
||||
}
|
||||
}
|
||||
xyLocatorRangeToRectOneDim(outRect, outLocRange, dims, 0);
|
||||
xyLocatorRangeToRectOneDim(outRect, outLocRange, dims, 1);
|
||||
return out;
|
||||
};
|
||||
/**
|
||||
* The returned locator pair can be the input of `dataToPoint` or `dataToLayout`.
|
||||
*
|
||||
* If point[0] is out of the matrix rect,
|
||||
* the out[0] is NaN;
|
||||
* else if it is on the right of top-left corner of body,
|
||||
* the out[0] is the oridinal number (>= 0).
|
||||
* else
|
||||
* out[0] is the locator for corner or header (<= 0).
|
||||
*
|
||||
* The same rule goes for point[1] and out[1].
|
||||
*
|
||||
* But point[0] and point[1] are calculated separately, i.e.,
|
||||
* the reuslt can be `[1, NaN]` or `[NaN, 1]` if only one dimension is out of boundary.
|
||||
*
|
||||
* @implement
|
||||
*/
|
||||
Matrix.prototype.pointToData = function (point, opt, out) {
|
||||
var dims = this._dims;
|
||||
pointToDataOneDimPrepareCtx(_tmpCtxPointToData, 0, dims, point, opt && opt.clamp);
|
||||
pointToDataOneDimPrepareCtx(_tmpCtxPointToData, 1, dims, point, opt && opt.clamp);
|
||||
out = out || [];
|
||||
out[0] = out[1] = NaN;
|
||||
if (_tmpCtxPointToData.y === CtxPointToDataAreaType.inCorner && _tmpCtxPointToData.x === CtxPointToDataAreaType.inBody) {
|
||||
pointToDataOnlyHeaderFillOut(_tmpCtxPointToData, out, 0, dims);
|
||||
} else if (_tmpCtxPointToData.x === CtxPointToDataAreaType.inCorner && _tmpCtxPointToData.y === CtxPointToDataAreaType.inBody) {
|
||||
pointToDataOnlyHeaderFillOut(_tmpCtxPointToData, out, 1, dims);
|
||||
} else {
|
||||
pointToDataBodyCornerFillOut(_tmpCtxPointToData, out, 0, dims);
|
||||
pointToDataBodyCornerFillOut(_tmpCtxPointToData, out, 1, dims);
|
||||
}
|
||||
return out;
|
||||
};
|
||||
Matrix.prototype.convertToPixel = function (ecModel, finder, value, opt) {
|
||||
var coordSys = getCoordSys(finder);
|
||||
return coordSys === this ? coordSys.dataToPoint(value, opt) : undefined;
|
||||
};
|
||||
Matrix.prototype.convertToLayout = function (ecModel, finder, value, opt) {
|
||||
var coordSys = getCoordSys(finder);
|
||||
return coordSys === this ? coordSys.dataToLayout(value, opt) : undefined;
|
||||
};
|
||||
Matrix.prototype.convertFromPixel = function (ecModel, finder, pixel, opt) {
|
||||
var coordSys = getCoordSys(finder);
|
||||
return coordSys === this ? coordSys.pointToData(pixel, opt) : undefined;
|
||||
};
|
||||
Matrix.prototype.containPoint = function (point) {
|
||||
return this._rect.contain(point[0], point[1]);
|
||||
};
|
||||
Matrix.dimensions = ['x', 'y', 'value'];
|
||||
return Matrix;
|
||||
}();
|
||||
var _dtpOutDataToLayout = {
|
||||
rect: createNaNRectLike()
|
||||
};
|
||||
var _ptdLevelIt = new ListIterator();
|
||||
var _ptdDimCellIt = new ListIterator();
|
||||
function layOutUnitsOnDimension(dimModels, dims, matrixRect, dimIdx) {
|
||||
var otherDimIdx = 1 - dimIdx;
|
||||
var thisDim = dims[XY[dimIdx]];
|
||||
var otherDim = dims[XY[otherDimIdx]];
|
||||
// Notice: If matrix.x/y.show is false, still lay out, to ensure the
|
||||
// consistent return of `dataToLayout`.
|
||||
var otherDimShow = otherDim.shouldShow();
|
||||
// Reset
|
||||
for (var it_1 = thisDim.resetCellIterator(); it_1.next();) {
|
||||
it_1.item.wh = it_1.item.xy = NaN;
|
||||
}
|
||||
for (var it_2 = otherDim.resetLayoutIterator(null, dimIdx); it_2.next();) {
|
||||
it_2.item.wh = it_2.item.xy = NaN;
|
||||
}
|
||||
// Set specified size from option.
|
||||
var restSize = matrixRect[WH[dimIdx]];
|
||||
var restCellsCount = thisDim.getLocatorCount(dimIdx) + otherDim.getLocatorCount(dimIdx);
|
||||
var tmpLevelModel = new Model();
|
||||
for (var it_3 = otherDim.resetLevelIterator(); it_3.next();) {
|
||||
// Consider `matrix.x.levelSize` and `matrix.x.levels[i].levelSize`.
|
||||
tmpLevelModel.option = it_3.item.option;
|
||||
tmpLevelModel.parentModel = dimModels[XY[otherDimIdx]];
|
||||
layOutSpecified(it_3.item, otherDimShow ? tmpLevelModel.get('levelSize') : 0);
|
||||
}
|
||||
var tmpCellModel = new Model();
|
||||
for (var it_4 = thisDim.resetCellIterator(); it_4.next();) {
|
||||
// Only leaf support size specification, to avoid unnecessary complexity.
|
||||
if (it_4.item.type === MatrixCellLayoutInfoType.leaf) {
|
||||
tmpCellModel.option = it_4.item.option;
|
||||
tmpCellModel.parentModel = undefined;
|
||||
layOutSpecified(it_4.item, tmpCellModel.get('size'));
|
||||
}
|
||||
}
|
||||
function layOutSpecified(item, sizeOption) {
|
||||
var size = parseSizeOption(sizeOption, dimIdx, matrixRect);
|
||||
if (!eqNaN(size)) {
|
||||
item.wh = confineSize(size, restSize);
|
||||
restSize = confineSize(restSize - item.wh);
|
||||
restCellsCount--;
|
||||
}
|
||||
}
|
||||
// Set all sizes and positions to levels and leaf cells of which size is unspecified.
|
||||
// Contents lay out based on matrix, rather than inverse; therefore do not support
|
||||
// calculating size based on content, but allocate equally.
|
||||
var computedCellWH = restCellsCount ? restSize / restCellsCount : 0;
|
||||
// If all size specified, but some space remain (may also caused by matrix.x/y.show: false)
|
||||
// do not align to the big most edge.
|
||||
var notAlignToBigmost = !restCellsCount && restSize >= 1; // `1` for cumulative precision error.
|
||||
var currXY = matrixRect[XY[dimIdx]];
|
||||
var maxLocator = thisDim.getLocatorCount(dimIdx) - 1;
|
||||
var it = new ListIterator();
|
||||
// Lay out levels of the perpendicular dim.
|
||||
for (otherDim.resetLayoutIterator(it, dimIdx); it.next();) {
|
||||
layOutUnspecified(it.item);
|
||||
}
|
||||
for (thisDim.resetLayoutIterator(it, dimIdx); it.next();) {
|
||||
layOutUnspecified(it.item);
|
||||
}
|
||||
function layOutUnspecified(item) {
|
||||
if (eqNaN(item.wh)) {
|
||||
item.wh = computedCellWH;
|
||||
}
|
||||
item.xy = currXY;
|
||||
if (item.id[XY[dimIdx]] === maxLocator && !notAlignToBigmost) {
|
||||
// Align to the rightmost border, consider cumulative precision error.
|
||||
item.wh = matrixRect[XY[dimIdx]] + matrixRect[WH[dimIdx]] - item.xy;
|
||||
}
|
||||
currXY += item.wh;
|
||||
}
|
||||
}
|
||||
function layOutDimCellsRestInfoByUnit(dimIdx, dims) {
|
||||
// Finally save layout info based on the unit leaves and levels.
|
||||
for (var it_5 = dims[XY[dimIdx]].resetCellIterator(); it_5.next();) {
|
||||
var dimCell = it_5.item;
|
||||
layOutRectOneDimBasedOnUnit(dimCell.rect, dimIdx, dimCell.id, dimCell.span, dims);
|
||||
// Consider level varitation on tree leaves, should extend the size to touch matrix body
|
||||
// to avoid weird appearance.
|
||||
layOutRectOneDimBasedOnUnit(dimCell.rect, 1 - dimIdx, dimCell.id, dimCell.span, dims);
|
||||
if (dimCell.type === MatrixCellLayoutInfoType.nonLeaf) {
|
||||
// `xy` and `wh` need to be saved in non-leaf since it supports locating by non-leaf
|
||||
// in `dataToPoint` or `dataToLayout`.
|
||||
dimCell.xy = dimCell.rect[XY[dimIdx]];
|
||||
dimCell.wh = dimCell.rect[WH[dimIdx]];
|
||||
}
|
||||
}
|
||||
}
|
||||
function layOutBodyCornerCellMerge(bodyOrCorner, dims) {
|
||||
bodyOrCorner.travelExistingCells(function (cell) {
|
||||
var computedSpan = cell.span;
|
||||
if (computedSpan) {
|
||||
var layoutRect = cell.spanRect;
|
||||
var id = cell.id;
|
||||
layOutRectOneDimBasedOnUnit(layoutRect, 0, id, computedSpan, dims);
|
||||
layOutRectOneDimBasedOnUnit(layoutRect, 1, id, computedSpan, dims);
|
||||
}
|
||||
});
|
||||
}
|
||||
// Save to rect for rendering.
|
||||
function layOutRectOneDimBasedOnUnit(outRect, dimIdx, id, span, dims) {
|
||||
outRect[WH[dimIdx]] = 0;
|
||||
var locator = id[XY[dimIdx]];
|
||||
var dim = locator < 0 ? dims[XY[1 - dimIdx]] : dims[XY[dimIdx]];
|
||||
var layoutUnit = dim.getUnitLayoutInfo(dimIdx, id[XY[dimIdx]]);
|
||||
outRect[XY[dimIdx]] = layoutUnit.xy;
|
||||
outRect[WH[dimIdx]] = layoutUnit.wh;
|
||||
if (span[XY[dimIdx]] > 1) {
|
||||
var layoutUnit2 = dim.getUnitLayoutInfo(dimIdx, id[XY[dimIdx]] + span[XY[dimIdx]] - 1);
|
||||
// Be careful the cumulative error - cell must be aligned.
|
||||
outRect[WH[dimIdx]] = layoutUnit2.xy + layoutUnit2.wh - layoutUnit.xy;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Return NaN if not defined or invalid.
|
||||
*/
|
||||
function parseSizeOption(sizeOption, dimIdx, matrixRect) {
|
||||
var sizeNum = parsePositionSizeOption(sizeOption, matrixRect[WH[dimIdx]]);
|
||||
return confineSize(sizeNum, matrixRect[WH[dimIdx]]);
|
||||
}
|
||||
function confineSize(sizeNum, sizeLimit) {
|
||||
return Math.max(Math.min(sizeNum, retrieve2(sizeLimit, Infinity)), 0);
|
||||
}
|
||||
function getCoordSys(finder) {
|
||||
var matrixModel = finder.matrixModel;
|
||||
var seriesModel = finder.seriesModel;
|
||||
var coordSys = matrixModel ? matrixModel.coordinateSystem : seriesModel ? seriesModel.coordinateSystem : null;
|
||||
return coordSys;
|
||||
}
|
||||
var CtxPointToDataAreaType = {
|
||||
inBody: 1,
|
||||
inCorner: 2,
|
||||
outside: 3
|
||||
};
|
||||
// For handy performance optimization in pointToData.
|
||||
var _tmpCtxPointToData = {
|
||||
x: null,
|
||||
y: null,
|
||||
point: []
|
||||
};
|
||||
function pointToDataOneDimPrepareCtx(ctx, dimIdx, dims, point, clamp) {
|
||||
var thisDim = dims[XY[dimIdx]];
|
||||
var otherDim = dims[XY[1 - dimIdx]];
|
||||
// Notice: considered cases: `matrix.x/y.show: false`, `matrix.x/y.data` is empty.
|
||||
// In this cases the `layout.xy` is on the edge and `layout.wh` is `0`; they still can be
|
||||
// use to calculate clampping.
|
||||
var bodyMaxUnit = thisDim.getUnitLayoutInfo(dimIdx, thisDim.getLocatorCount(dimIdx) - 1);
|
||||
var body0Unit = thisDim.getUnitLayoutInfo(dimIdx, 0);
|
||||
var cornerMinUnit = otherDim.getUnitLayoutInfo(dimIdx, -otherDim.getLocatorCount(dimIdx));
|
||||
var cornerMinus1Unit = otherDim.shouldShow() ? otherDim.getUnitLayoutInfo(dimIdx, -1) : null;
|
||||
var coord = ctx.point[dimIdx] = point[dimIdx]; // Transfer the oridinal coord.
|
||||
if (!body0Unit && !cornerMinus1Unit) {
|
||||
ctx[XY[dimIdx]] = CtxPointToDataAreaType.outside;
|
||||
return;
|
||||
}
|
||||
if (clamp === MatrixClampOption.body) {
|
||||
if (body0Unit) {
|
||||
ctx[XY[dimIdx]] = CtxPointToDataAreaType.inBody;
|
||||
coord = mathMin(bodyMaxUnit.xy + bodyMaxUnit.wh, mathMax(body0Unit.xy, coord));
|
||||
ctx.point[dimIdx] = coord;
|
||||
} else {
|
||||
// If clamp to body, the result must not be in header.
|
||||
ctx[XY[dimIdx]] = CtxPointToDataAreaType.outside;
|
||||
}
|
||||
return;
|
||||
} else if (clamp === MatrixClampOption.corner) {
|
||||
if (cornerMinus1Unit) {
|
||||
ctx[XY[dimIdx]] = CtxPointToDataAreaType.inCorner;
|
||||
coord = mathMin(cornerMinus1Unit.xy + cornerMinus1Unit.wh, mathMax(cornerMinUnit.xy, coord));
|
||||
ctx.point[dimIdx] = coord;
|
||||
} else {
|
||||
// If clamp to corner, the result must not be in body.
|
||||
ctx[XY[dimIdx]] = CtxPointToDataAreaType.outside;
|
||||
}
|
||||
return;
|
||||
}
|
||||
var pxLoc0 = body0Unit ? body0Unit.xy : cornerMinus1Unit ? cornerMinus1Unit.xy + cornerMinus1Unit.wh : NaN;
|
||||
var pxMin = cornerMinUnit ? cornerMinUnit.xy : pxLoc0;
|
||||
var pxMax = bodyMaxUnit ? bodyMaxUnit.xy + bodyMaxUnit.wh : pxLoc0;
|
||||
if (coord < pxMin) {
|
||||
if (!clamp) {
|
||||
// Quick pass for later calc, since mouse event on any place will enter this method if use `pointToData`.
|
||||
ctx[XY[dimIdx]] = CtxPointToDataAreaType.outside;
|
||||
return;
|
||||
}
|
||||
coord = pxMin;
|
||||
} else if (coord > pxMax) {
|
||||
if (!clamp) {
|
||||
ctx[XY[dimIdx]] = CtxPointToDataAreaType.outside;
|
||||
return;
|
||||
}
|
||||
coord = pxMax;
|
||||
}
|
||||
ctx.point[dimIdx] = coord; // Save the updated coord.
|
||||
ctx[XY[dimIdx]] = pxLoc0 <= coord && coord <= pxMax ? CtxPointToDataAreaType.inBody : pxMin <= coord && coord <= pxLoc0 ? CtxPointToDataAreaType.inCorner : CtxPointToDataAreaType.outside;
|
||||
// Every props in ctx must be set in every branch of this method.
|
||||
}
|
||||
// Assume partialOut has been set to NaN outside.
|
||||
// This method may fill out[0] and out[1] in one call.
|
||||
function pointToDataOnlyHeaderFillOut(ctx, partialOut, dimIdx, dims) {
|
||||
var otherDimIdx = 1 - dimIdx;
|
||||
if (ctx[XY[dimIdx]] === CtxPointToDataAreaType.outside) {
|
||||
return;
|
||||
}
|
||||
for (dims[XY[dimIdx]].resetCellIterator(_ptdDimCellIt); _ptdDimCellIt.next();) {
|
||||
var cell = _ptdDimCellIt.item;
|
||||
if (isCoordInRect(ctx.point[dimIdx], cell.rect, dimIdx) && isCoordInRect(ctx.point[otherDimIdx], cell.rect, otherDimIdx)) {
|
||||
// non-leaves are also allowed to be located.
|
||||
// If the point is in x or y dimension cell area, should check both x and y coord to
|
||||
// determine a cell; in this way a non-leaf cell can be determined.
|
||||
partialOut[dimIdx] = cell.ordinal;
|
||||
partialOut[otherDimIdx] = cell.id[XY[otherDimIdx]];
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Assume partialOut has been set to NaN outside.
|
||||
// This method may fill out[0] and out[1] in one call.
|
||||
function pointToDataBodyCornerFillOut(ctx, partialOut, dimIdx, dims) {
|
||||
if (ctx[XY[dimIdx]] === CtxPointToDataAreaType.outside) {
|
||||
return;
|
||||
}
|
||||
var dim = ctx[XY[dimIdx]] === CtxPointToDataAreaType.inCorner ? dims[XY[1 - dimIdx]] : dims[XY[dimIdx]];
|
||||
for (dim.resetLayoutIterator(_ptdLevelIt, dimIdx); _ptdLevelIt.next();) {
|
||||
if (isCoordInLayoutInfo(ctx.point[dimIdx], _ptdLevelIt.item)) {
|
||||
partialOut[dimIdx] = _ptdLevelIt.item.id[XY[dimIdx]];
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
function isCoordInLayoutInfo(coord, cell) {
|
||||
return cell.xy <= coord && coord <= cell.xy + cell.wh;
|
||||
}
|
||||
function isCoordInRect(coord, rect, dimIdx) {
|
||||
return rect[XY[dimIdx]] <= coord && coord <= rect[XY[dimIdx]] + rect[WH[dimIdx]];
|
||||
}
|
||||
export default Matrix;
|
||||
+227
@@ -0,0 +1,227 @@
|
||||
|
||||
/*
|
||||
* 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 { createHashMap, each, extend, isArray, isObject } from 'zrender/lib/core/util.js';
|
||||
import { error } from '../../util/log.js';
|
||||
import Point from 'zrender/lib/core/Point.js';
|
||||
import { resolveXYLocatorRangeByCellMerge, MatrixClampOption, parseCoordRangeOption, fillIdSpanFromLocatorRange, createNaNRectLike, isXYLocatorRangeInvalidOnDim, resetXYLocatorRange, cloneXYLocatorRange } from './matrixCoordHelper.js';
|
||||
/**
|
||||
* Lifetime: the same with `MatrixModel`, but different from `coord/Matrix`.
|
||||
*/
|
||||
var MatrixBodyCorner = /** @class */function () {
|
||||
function MatrixBodyCorner(kind, bodyOrCornerModel, dims) {
|
||||
this._model = bodyOrCornerModel;
|
||||
this._dims = dims;
|
||||
this._kind = kind;
|
||||
this._cellMergeOwnerList = [];
|
||||
}
|
||||
/**
|
||||
* Can not be called before series models initialization finished, since the ordinalMeta may
|
||||
* use collect the values from `series.data` in series initialization.
|
||||
*/
|
||||
MatrixBodyCorner.prototype._ensureCellMap = function () {
|
||||
var self = this;
|
||||
var _cellMap = self._cellMap;
|
||||
if (!_cellMap) {
|
||||
_cellMap = self._cellMap = createHashMap();
|
||||
fillCellMap();
|
||||
}
|
||||
return _cellMap;
|
||||
function fillCellMap() {
|
||||
var parsedList = [];
|
||||
var cellOptionList = self._model.getShallow('data');
|
||||
if (cellOptionList && !isArray(cellOptionList)) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
error("matrix." + cellOptionList + ".data must be an array if specified.");
|
||||
}
|
||||
cellOptionList = null;
|
||||
}
|
||||
each(cellOptionList, function (option, idx) {
|
||||
if (!isObject(option) || !isArray(option.coord)) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
error("Illegal matrix." + self._kind + ".data[" + idx + "], must be a {coord: [...], ...}");
|
||||
}
|
||||
return;
|
||||
}
|
||||
var locatorRange = resetXYLocatorRange([]);
|
||||
var reasonArr = null;
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
reasonArr = [];
|
||||
}
|
||||
parseCoordRangeOption(locatorRange, reasonArr, option.coord, self._dims, option.coordClamp ? MatrixClampOption[self._kind] : MatrixClampOption.none);
|
||||
if (isXYLocatorRangeInvalidOnDim(locatorRange, 0) || isXYLocatorRangeInvalidOnDim(locatorRange, 1)) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
error("Can not determine cells by option matrix." + self._kind + ".data[" + idx + "]: " + ("" + reasonArr.join(' ')));
|
||||
}
|
||||
return;
|
||||
}
|
||||
var cellMergeOwner = option && option.mergeCells;
|
||||
var parsed = {
|
||||
id: new Point(),
|
||||
span: new Point(),
|
||||
locatorRange: locatorRange,
|
||||
option: option,
|
||||
cellMergeOwner: cellMergeOwner
|
||||
};
|
||||
fillIdSpanFromLocatorRange(parsed, locatorRange);
|
||||
// The order of the `parsedList` determines the precedence of the styles, if there
|
||||
// are overlaps between ranges specified in different items. Preserve the original
|
||||
// order of `matrix.body/corner/data` to make it predictable for users.
|
||||
parsedList.push(parsed);
|
||||
});
|
||||
// Resolve cell merging intersection - union to a larger rect.
|
||||
var mergedMarkList = [];
|
||||
for (var parsedIdx = 0; parsedIdx < parsedList.length; parsedIdx++) {
|
||||
var parsed = parsedList[parsedIdx];
|
||||
if (!parsed.cellMergeOwner) {
|
||||
continue;
|
||||
}
|
||||
var locatorRange = parsed.locatorRange;
|
||||
resolveXYLocatorRangeByCellMerge(locatorRange, mergedMarkList, parsedList, parsedIdx);
|
||||
for (var idx = 0; idx < parsedIdx; idx++) {
|
||||
if (mergedMarkList[idx]) {
|
||||
parsedList[idx].cellMergeOwner = false;
|
||||
}
|
||||
}
|
||||
if (locatorRange[0][0] !== parsed.id.x || locatorRange[1][0] !== parsed.id.y) {
|
||||
// The top-left cell of the unioned locatorRange is not this cell any more.
|
||||
parsed.cellMergeOwner = false;
|
||||
// Reconcile: simply use the last style and value option if multiple styles involved
|
||||
// in a merged area, since there might be no commonly used merge strategy.
|
||||
var newOption = extend({}, parsed.option);
|
||||
newOption.coord = null;
|
||||
var newParsed = {
|
||||
id: new Point(),
|
||||
span: new Point(),
|
||||
locatorRange: locatorRange,
|
||||
option: newOption,
|
||||
cellMergeOwner: true
|
||||
};
|
||||
fillIdSpanFromLocatorRange(newParsed, locatorRange);
|
||||
parsedList.push(newParsed);
|
||||
}
|
||||
}
|
||||
// Assign options to cells.
|
||||
each(parsedList, function (parsed) {
|
||||
var topLeftCell = ensureBodyOrCornerCell(parsed.id.x, parsed.id.y);
|
||||
if (parsed.cellMergeOwner) {
|
||||
topLeftCell.cellMergeOwner = true;
|
||||
topLeftCell.span = parsed.span;
|
||||
topLeftCell.locatorRange = parsed.locatorRange;
|
||||
topLeftCell.spanRect = createNaNRectLike();
|
||||
self._cellMergeOwnerList.push(topLeftCell);
|
||||
}
|
||||
if (!parsed.cellMergeOwner && !parsed.option) {
|
||||
return;
|
||||
}
|
||||
for (var yidx = 0; yidx < parsed.span.y; yidx++) {
|
||||
for (var xidx = 0; xidx < parsed.span.x; xidx++) {
|
||||
var cell = ensureBodyOrCornerCell(parsed.id.x + xidx, parsed.id.y + yidx);
|
||||
// If multiple style options are defined on a cell, the later ones takes precedence.
|
||||
cell.option = parsed.option;
|
||||
if (parsed.cellMergeOwner) {
|
||||
cell.inSpanOf = topLeftCell;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} // End of fillCellMap
|
||||
function ensureBodyOrCornerCell(x, y) {
|
||||
var key = makeCellMapKey(x, y);
|
||||
var cell = _cellMap.get(key);
|
||||
if (!cell) {
|
||||
cell = _cellMap.set(key, {
|
||||
id: new Point(x, y),
|
||||
option: null,
|
||||
inSpanOf: null,
|
||||
span: null,
|
||||
spanRect: null,
|
||||
locatorRange: null,
|
||||
cellMergeOwner: false
|
||||
});
|
||||
}
|
||||
return cell;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Body cells or corner cell are not commonly defined specifically, especially in a large
|
||||
* table, thus his is a sparse data structure - bodys or corner cells exist only if there
|
||||
* are options specified to it (in `matrix.body.data` or `matrix.corner.data`);
|
||||
* otherwise, return `NullUndefined`.
|
||||
*/
|
||||
MatrixBodyCorner.prototype.getCell = function (xy) {
|
||||
// Assert xy do not contain NaN
|
||||
return this._ensureCellMap().get(makeCellMapKey(xy[0], xy[1]));
|
||||
};
|
||||
/**
|
||||
* Only cell existing (has specific definition or props) will be travelled.
|
||||
*/
|
||||
MatrixBodyCorner.prototype.travelExistingCells = function (cb) {
|
||||
this._ensureCellMap().each(cb);
|
||||
};
|
||||
/**
|
||||
* @param locatorRange Must be the return of `parseCoordRangeOption`.
|
||||
*/
|
||||
MatrixBodyCorner.prototype.expandRangeByCellMerge = function (locatorRange) {
|
||||
if (!isXYLocatorRangeInvalidOnDim(locatorRange, 0) && !isXYLocatorRangeInvalidOnDim(locatorRange, 1) && locatorRange[0][0] === locatorRange[0][1] && locatorRange[1][0] === locatorRange[1][1]) {
|
||||
// If it locates to a single cell, use this quick path to avoid travelling.
|
||||
// It is based on the fact that any cell is not contained by more than one cell merging rect.
|
||||
_tmpERBCMLocator[0] = locatorRange[0][0];
|
||||
_tmpERBCMLocator[1] = locatorRange[1][0];
|
||||
var cell = this.getCell(_tmpERBCMLocator);
|
||||
var inSpanOf = cell && cell.inSpanOf;
|
||||
if (inSpanOf) {
|
||||
cloneXYLocatorRange(locatorRange, inSpanOf.locatorRange);
|
||||
return;
|
||||
}
|
||||
}
|
||||
var list = this._cellMergeOwnerList;
|
||||
resolveXYLocatorRangeByCellMerge(locatorRange, null, list, list.length);
|
||||
};
|
||||
return MatrixBodyCorner;
|
||||
}();
|
||||
export { MatrixBodyCorner };
|
||||
var _tmpERBCMLocator = [];
|
||||
function makeCellMapKey(x, y) {
|
||||
return x + "|" + y;
|
||||
}
|
||||
+359
@@ -0,0 +1,359 @@
|
||||
|
||||
/*
|
||||
* 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 { createHashMap, defaults, each, eqNaN, isArray, isObject, isString } from 'zrender/lib/core/util.js';
|
||||
import Point from 'zrender/lib/core/Point.js';
|
||||
import OrdinalMeta from '../../data/OrdinalMeta.js';
|
||||
import Ordinal from '../../scale/Ordinal.js';
|
||||
import { WH, XY } from '../../util/graphic.js';
|
||||
import { ListIterator } from '../../util/model.js';
|
||||
import { createNaNRectLike, setDimXYValue, MatrixCellLayoutInfoType } from './matrixCoordHelper.js';
|
||||
import { error } from '../../util/log.js';
|
||||
import { mathMax } from '../../util/number.js';
|
||||
/**
|
||||
* Lifetime: the same with `MatrixModel`, but different from `coord/Matrix`.
|
||||
*/
|
||||
var MatrixDim = /** @class */function () {
|
||||
function MatrixDim(dim, dimModel) {
|
||||
// Under the current definition, every leave corresponds a unit cell,
|
||||
// and leaves can serve as the locator of cells.
|
||||
// Therefore make sure:
|
||||
// - The first `_leavesCount` elements in `_cells` are leaves.
|
||||
// - `_cells[leaf.id[XY[this.dimIdx]]]` is the leaf itself.
|
||||
// - Leaves of each subtree are placed together, that is, the leaves of a dimCell are:
|
||||
// `this._cells.slice(dimCell.firstLeafLocator, dimCell.span[XY[this.dimIdx]])`
|
||||
this._cells = [];
|
||||
// Can be visited by `_levels[cell.level]` or `_levels[cell.id[1 - dimIdx] + _levels.length]`.
|
||||
// Items are never be null/undefined after initialized.
|
||||
this._levels = [];
|
||||
this.dim = dim;
|
||||
this.dimIdx = dim === 'x' ? 0 : 1;
|
||||
this._model = dimModel;
|
||||
this._uniqueValueGen = createUniqueValueGenerator(dim);
|
||||
var dimModelData = dimModel.get('data', true);
|
||||
if (dimModelData != null && !isArray(dimModelData)) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
error("Illegal echarts option - matrix." + this.dim + ".data must be an array if specified.");
|
||||
}
|
||||
dimModelData = [];
|
||||
}
|
||||
if (dimModelData) {
|
||||
this._initByDimModelData(dimModelData);
|
||||
} else {
|
||||
this._initBySeriesData();
|
||||
}
|
||||
}
|
||||
MatrixDim.prototype._initByDimModelData = function (dimModelData) {
|
||||
var self = this;
|
||||
var _cells = self._cells;
|
||||
var _levels = self._levels;
|
||||
var sameLocatorCellsLists = []; // Save for sorting.
|
||||
var _cellCount = 0;
|
||||
self._leavesCount = traverseInitCells(dimModelData, 0, 0);
|
||||
postInitCells();
|
||||
return;
|
||||
function traverseInitCells(dimModelData, firstLeafLocator, level) {
|
||||
var totalSpan = 0;
|
||||
if (!dimModelData) {
|
||||
return totalSpan;
|
||||
}
|
||||
each(dimModelData, function (option, optionIdx) {
|
||||
var invalidOption = false;
|
||||
var cellOption;
|
||||
if (isString(option)) {
|
||||
cellOption = {
|
||||
value: option
|
||||
};
|
||||
} else if (isObject(option)) {
|
||||
cellOption = option;
|
||||
if (option.value != null && !isString(option.value)) {
|
||||
invalidOption = true;
|
||||
cellOption = {
|
||||
value: null
|
||||
};
|
||||
}
|
||||
} else {
|
||||
cellOption = {
|
||||
value: null
|
||||
};
|
||||
if (option != null) {
|
||||
invalidOption = true;
|
||||
}
|
||||
}
|
||||
if (invalidOption) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
error("Illegal echarts option - matrix." + self.dim + ".data[" + optionIdx + "]" + ' must be `string | {value: string}`.');
|
||||
}
|
||||
}
|
||||
var cell = {
|
||||
type: MatrixCellLayoutInfoType.nonLeaf,
|
||||
ordinal: NaN,
|
||||
level: level,
|
||||
firstLeafLocator: firstLeafLocator,
|
||||
id: new Point(),
|
||||
span: setDimXYValue(new Point(), self.dimIdx, 1, 1),
|
||||
option: cellOption,
|
||||
xy: NaN,
|
||||
wh: NaN,
|
||||
dim: self,
|
||||
rect: createNaNRectLike()
|
||||
};
|
||||
_cellCount++;
|
||||
(sameLocatorCellsLists[firstLeafLocator] || (sameLocatorCellsLists[firstLeafLocator] = [])).push(cell);
|
||||
if (!_levels[level]) {
|
||||
// Create a level only if at least one cell exists.
|
||||
_levels[level] = {
|
||||
type: MatrixCellLayoutInfoType.level,
|
||||
xy: NaN,
|
||||
wh: NaN,
|
||||
option: null,
|
||||
id: new Point(),
|
||||
dim: self
|
||||
};
|
||||
}
|
||||
var childrenSpan = traverseInitCells(cellOption.children, firstLeafLocator, level + 1);
|
||||
var subSpan = Math.max(1, childrenSpan);
|
||||
cell.span[XY[self.dimIdx]] = subSpan;
|
||||
totalSpan += subSpan;
|
||||
firstLeafLocator += subSpan;
|
||||
});
|
||||
return totalSpan;
|
||||
}
|
||||
function postInitCells() {
|
||||
// Sort to make sure the leaves are at the beginning, so that
|
||||
// they can be used as the locator of body cells.
|
||||
var categories = [];
|
||||
while (_cells.length < _cellCount) {
|
||||
for (var locator = 0; locator < sameLocatorCellsLists.length; locator++) {
|
||||
var cell = sameLocatorCellsLists[locator].pop();
|
||||
if (cell) {
|
||||
cell.ordinal = categories.length;
|
||||
var val = cell.option.value;
|
||||
categories.push(val);
|
||||
_cells.push(cell);
|
||||
self._uniqueValueGen.calcDupBase(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
self._uniqueValueGen.ensureValueUnique(categories, _cells);
|
||||
var ordinalMeta = self._ordinalMeta = new OrdinalMeta({
|
||||
categories: categories,
|
||||
needCollect: false,
|
||||
deduplication: false
|
||||
});
|
||||
self._scale = new Ordinal({
|
||||
ordinalMeta: ordinalMeta
|
||||
});
|
||||
for (var idx = 0; idx < self._leavesCount; idx++) {
|
||||
var leaf = self._cells[idx];
|
||||
leaf.type = MatrixCellLayoutInfoType.leaf;
|
||||
// Handle the tree level variation: enlarge the span of the leaves to reach the body cells.
|
||||
leaf.span[XY[1 - self.dimIdx]] = self._levels.length - leaf.level;
|
||||
}
|
||||
self._initCellsId();
|
||||
self._initLevelIdOptions();
|
||||
}
|
||||
};
|
||||
MatrixDim.prototype._initBySeriesData = function () {
|
||||
var self = this;
|
||||
self._leavesCount = 0;
|
||||
self._levels = [{
|
||||
type: MatrixCellLayoutInfoType.level,
|
||||
xy: NaN,
|
||||
wh: NaN,
|
||||
option: null,
|
||||
id: new Point(),
|
||||
dim: self
|
||||
}];
|
||||
self._initLevelIdOptions();
|
||||
var ordinalMeta = self._ordinalMeta = new OrdinalMeta({
|
||||
needCollect: true,
|
||||
deduplication: true,
|
||||
onCollect: function (value, ordinalNumber) {
|
||||
var cell = self._cells[ordinalNumber] = {
|
||||
type: MatrixCellLayoutInfoType.leaf,
|
||||
ordinal: ordinalNumber,
|
||||
level: 0,
|
||||
firstLeafLocator: ordinalNumber,
|
||||
id: new Point(),
|
||||
span: setDimXYValue(new Point(), self.dimIdx, 1, 1),
|
||||
// Theoretically `value` is from `dataset` or `series.data`, so it may be any type.
|
||||
// Do not restrict this case for user's convenience, and here simply convert it to
|
||||
// string for display.
|
||||
option: {
|
||||
value: value + ''
|
||||
},
|
||||
xy: NaN,
|
||||
wh: NaN,
|
||||
dim: self,
|
||||
rect: createNaNRectLike()
|
||||
};
|
||||
self._leavesCount++;
|
||||
self._setCellId(cell);
|
||||
}
|
||||
});
|
||||
self._scale = new Ordinal({
|
||||
ordinalMeta: ordinalMeta
|
||||
});
|
||||
};
|
||||
MatrixDim.prototype._setCellId = function (cell) {
|
||||
var levelsLen = this._levels.length;
|
||||
var dimIdx = this.dimIdx;
|
||||
setDimXYValue(cell.id, dimIdx, cell.firstLeafLocator, cell.level - levelsLen);
|
||||
};
|
||||
MatrixDim.prototype._initCellsId = function () {
|
||||
var levelsLen = this._levels.length;
|
||||
var dimIdx = this.dimIdx;
|
||||
each(this._cells, function (cell) {
|
||||
setDimXYValue(cell.id, dimIdx, cell.firstLeafLocator, cell.level - levelsLen);
|
||||
});
|
||||
};
|
||||
MatrixDim.prototype._initLevelIdOptions = function () {
|
||||
var levelsLen = this._levels.length;
|
||||
var dimIdx = this.dimIdx;
|
||||
var levelOptionList = this._model.get('levels', true);
|
||||
levelOptionList = isArray(levelOptionList) ? levelOptionList : [];
|
||||
each(this._levels, function (levelCfg, level) {
|
||||
setDimXYValue(levelCfg.id, dimIdx, 0, level - levelsLen);
|
||||
levelCfg.option = levelOptionList[level];
|
||||
});
|
||||
};
|
||||
MatrixDim.prototype.shouldShow = function () {
|
||||
return !!this._model.getShallow('show', true);
|
||||
};
|
||||
/**
|
||||
* Iterate leaves (they are layout units) if dimIdx === this.dimIdx.
|
||||
* Iterate levels if dimIdx !== this.dimIdx.
|
||||
*/
|
||||
MatrixDim.prototype.resetLayoutIterator = function (it, dimIdx, startLocator, count) {
|
||||
it = it || new ListIterator();
|
||||
if (dimIdx === this.dimIdx) {
|
||||
var len = this._leavesCount;
|
||||
var startIdx = startLocator != null ? Math.max(0, startLocator) : 0;
|
||||
count = count != null ? Math.min(count, len) : len;
|
||||
it.reset(this._cells, startIdx, startIdx + count);
|
||||
} else {
|
||||
var len = this._levels.length;
|
||||
// Corner locator is from `-this._levels.length` to `-1`.
|
||||
var startIdx = startLocator != null ? Math.max(0, startLocator + len) : 0;
|
||||
count = count != null ? Math.min(count, len) : len;
|
||||
it.reset(this._levels, startIdx, startIdx + count);
|
||||
}
|
||||
return it;
|
||||
};
|
||||
MatrixDim.prototype.resetCellIterator = function (it) {
|
||||
return (it || new ListIterator()).reset(this._cells, 0);
|
||||
};
|
||||
MatrixDim.prototype.resetLevelIterator = function (it) {
|
||||
return (it || new ListIterator()).reset(this._levels, 0);
|
||||
};
|
||||
MatrixDim.prototype.getLayout = function (outRect, dimIdx, locator) {
|
||||
var layout = this.getUnitLayoutInfo(dimIdx, locator);
|
||||
outRect[XY[dimIdx]] = layout ? layout.xy : NaN;
|
||||
outRect[WH[dimIdx]] = layout ? layout.wh : NaN;
|
||||
};
|
||||
/**
|
||||
* Get leaf cell or get level info.
|
||||
* Should be able to return null/undefined if not found on x or y, thus input `dimIdx` is needed.
|
||||
*/
|
||||
MatrixDim.prototype.getUnitLayoutInfo = function (dimIdx, locator) {
|
||||
return dimIdx === this.dimIdx ? locator < this._leavesCount ? this._cells[locator] : undefined : this._levels[locator + this._levels.length];
|
||||
};
|
||||
/**
|
||||
* Get dimension cell by data, including leaves and non-leaves.
|
||||
*/
|
||||
MatrixDim.prototype.getCell = function (value) {
|
||||
var ordinal = this._scale.parse(value);
|
||||
return eqNaN(ordinal) ? undefined : this._cells[ordinal];
|
||||
};
|
||||
/**
|
||||
* Get leaf count or get level count.
|
||||
*/
|
||||
MatrixDim.prototype.getLocatorCount = function (dimIdx) {
|
||||
return dimIdx === this.dimIdx ? this._leavesCount : this._levels.length;
|
||||
};
|
||||
MatrixDim.prototype.getOrdinalMeta = function () {
|
||||
return this._ordinalMeta;
|
||||
};
|
||||
return MatrixDim;
|
||||
}();
|
||||
export { MatrixDim };
|
||||
function createUniqueValueGenerator(dim) {
|
||||
var dimUpper = dim.toUpperCase();
|
||||
var defaultValReg = new RegExp("^" + dimUpper + "([0-9]+)$");
|
||||
var dupBase = 0;
|
||||
function calcDupBase(val) {
|
||||
var matchResult;
|
||||
if (val != null && (matchResult = val.match(defaultValReg))) {
|
||||
dupBase = mathMax(dupBase, +matchResult[1] + 1);
|
||||
}
|
||||
}
|
||||
function makeUniqueValue() {
|
||||
return "" + dimUpper + dupBase++;
|
||||
}
|
||||
// Duplicated value is allowed, because the `matrix.x/y.data` can be a tree and it's reasonable
|
||||
// that leaves in different subtrees has the same text. But only the first one is allowed to be
|
||||
// queried by the text, and the other ones can only be queried by index.
|
||||
// Additionally, `matrix.x/y.data: [null, null, ...]` is allowed.
|
||||
function ensureValueUnique(categories, cells) {
|
||||
// A simple way to deduplicate or handle illegal or not specified values to avoid unexpected behaviors.
|
||||
// The tree structure should not be broken even if duplicated.
|
||||
var cateMap = createHashMap();
|
||||
for (var idx = 0; idx < categories.length; idx++) {
|
||||
var value = categories[idx];
|
||||
// value may be set to NullUndefined by users or if illegal.
|
||||
if (value == null || cateMap.get(value) != null) {
|
||||
// Still display the original option.value if duplicated, but loose the ability to query by text.
|
||||
categories[idx] = value = makeUniqueValue();
|
||||
cells[idx].option = defaults({
|
||||
value: value
|
||||
}, cells[idx].option);
|
||||
}
|
||||
cateMap.set(value, true);
|
||||
}
|
||||
}
|
||||
return {
|
||||
calcDupBase: calcDupBase,
|
||||
ensureValueUnique: ensureValueUnique
|
||||
};
|
||||
}
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
|
||||
/*
|
||||
* 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 { __extends } from "tslib";
|
||||
import ComponentModel from '../../model/Component.js';
|
||||
import Model from '../../model/Model.js';
|
||||
import { MatrixDim } from './MatrixDim.js';
|
||||
import { MatrixBodyCorner } from './MatrixBodyCorner.js';
|
||||
import tokens from '../../visual/tokens.js';
|
||||
var defaultLabelOption = {
|
||||
show: true,
|
||||
color: tokens.color.secondary,
|
||||
// overflow: 'truncate',
|
||||
overflow: 'break',
|
||||
lineOverflow: 'truncate',
|
||||
padding: [2, 3, 2, 3],
|
||||
// Prefer to use `padding`, rather than distance.
|
||||
distance: 0
|
||||
};
|
||||
function makeDefaultCellItemStyleOption(isCorner) {
|
||||
return {
|
||||
color: 'none',
|
||||
borderWidth: 1,
|
||||
borderColor: isCorner ? 'none' : tokens.color.borderTint
|
||||
};
|
||||
}
|
||||
;
|
||||
var defaultDimOption = {
|
||||
show: true,
|
||||
label: defaultLabelOption,
|
||||
itemStyle: makeDefaultCellItemStyleOption(false),
|
||||
silent: undefined,
|
||||
dividerLineStyle: {
|
||||
width: 1,
|
||||
color: tokens.color.border
|
||||
}
|
||||
};
|
||||
var defaultBodyOption = {
|
||||
label: defaultLabelOption,
|
||||
itemStyle: makeDefaultCellItemStyleOption(false),
|
||||
silent: undefined
|
||||
};
|
||||
var defaultCornerOption = {
|
||||
label: defaultLabelOption,
|
||||
itemStyle: makeDefaultCellItemStyleOption(true),
|
||||
silent: undefined
|
||||
};
|
||||
var defaultMatrixOption = {
|
||||
// As a most basic coord sys, `z` should be lower than
|
||||
// other series and coord sys, such as, grid.
|
||||
z: -50,
|
||||
left: '10%',
|
||||
top: '10%',
|
||||
right: '10%',
|
||||
bottom: '10%',
|
||||
x: defaultDimOption,
|
||||
y: defaultDimOption,
|
||||
body: defaultBodyOption,
|
||||
corner: defaultCornerOption,
|
||||
backgroundStyle: {
|
||||
color: 'none',
|
||||
borderColor: tokens.color.axisLine,
|
||||
borderWidth: 1
|
||||
}
|
||||
};
|
||||
var MatrixModel = /** @class */function (_super) {
|
||||
__extends(MatrixModel, _super);
|
||||
function MatrixModel() {
|
||||
var _this = _super !== null && _super.apply(this, arguments) || this;
|
||||
_this.type = MatrixModel.type;
|
||||
return _this;
|
||||
}
|
||||
MatrixModel.prototype.optionUpdated = function () {
|
||||
// Simply re-create all to follow model changes.
|
||||
var dimModels = this._dimModels = {
|
||||
// Do not use matrixModel as the parent model, for preventing from cascade-fetching options to it.
|
||||
x: new MatrixDimensionModel(this.get('x', true) || {}),
|
||||
y: new MatrixDimensionModel(this.get('y', true) || {})
|
||||
};
|
||||
dimModels.x.option.type = dimModels.y.option.type = 'category';
|
||||
var xDim = dimModels.x.dim = new MatrixDim('x', dimModels.x);
|
||||
var yDim = dimModels.y.dim = new MatrixDim('y', dimModels.y);
|
||||
var dims = {
|
||||
x: xDim,
|
||||
y: yDim
|
||||
};
|
||||
this._body = new MatrixBodyCorner('body', new Model(this.getShallow('body')), dims);
|
||||
this._corner = new MatrixBodyCorner('corner', new Model(this.getShallow('corner')), dims);
|
||||
};
|
||||
MatrixModel.prototype.getDimensionModel = function (dim) {
|
||||
return this._dimModels[dim];
|
||||
};
|
||||
MatrixModel.prototype.getBody = function () {
|
||||
return this._body;
|
||||
};
|
||||
MatrixModel.prototype.getCorner = function () {
|
||||
return this._corner;
|
||||
};
|
||||
MatrixModel.type = 'matrix';
|
||||
MatrixModel.layoutMode = 'box';
|
||||
MatrixModel.defaultOption = defaultMatrixOption;
|
||||
return MatrixModel;
|
||||
}(ComponentModel);
|
||||
var MatrixDimensionModel = /** @class */function (_super) {
|
||||
__extends(MatrixDimensionModel, _super);
|
||||
function MatrixDimensionModel() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
MatrixDimensionModel.prototype.getOrdinalMeta = function () {
|
||||
return this.dim.getOrdinalMeta();
|
||||
};
|
||||
return MatrixDimensionModel;
|
||||
}(Model);
|
||||
export { MatrixDimensionModel };
|
||||
export default MatrixModel;
|
||||
+295
@@ -0,0 +1,295 @@
|
||||
|
||||
/*
|
||||
* 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 { eqNaN, isArray, isNumber } from 'zrender/lib/core/util.js';
|
||||
import { WH, XY } from '../../util/graphic.js';
|
||||
import { mathMax, mathMin } from '../../util/number.js';
|
||||
export var MatrixCellLayoutInfoType = {
|
||||
level: 1,
|
||||
leaf: 2,
|
||||
nonLeaf: 3
|
||||
};
|
||||
/**
|
||||
* @public Public to users in `chart.convertFromPixel`.
|
||||
*/
|
||||
export var MatrixClampOption = {
|
||||
// No clamp, be falsy, equals to null/undefined. It means if the input part is
|
||||
// null/undefined/NaN/outOfBoundary, the result part is NaN, rather than clamp to
|
||||
// the boundary of the matrix.
|
||||
none: 0,
|
||||
// Clamp, where null/undefined/NaN/outOfBoundary can be used to cover the entire row/column.
|
||||
all: 1,
|
||||
body: 2,
|
||||
corner: 3
|
||||
};
|
||||
/**
|
||||
* For the x direction,
|
||||
* - find dimension cell from `xMatrixDim`,
|
||||
* - If `xDimCell` or `yDimCell` is not a leaf, return the non-leaf cell itself.
|
||||
* - otherwise find level from `yMatrixDim`.
|
||||
* - otherwise return `NullUndefined`.
|
||||
*
|
||||
* For the y direction, it's the opposite.
|
||||
*/
|
||||
export function coordDataToAllCellLevelLayout(coordValue, dims, thisDimIdx // 0 | 1
|
||||
) {
|
||||
// Find in body.
|
||||
var result = dims[XY[thisDimIdx]].getCell(coordValue);
|
||||
// Find in corner or dimension area.
|
||||
if (!result && isNumber(coordValue) && coordValue < 0) {
|
||||
result = dims[XY[1 - thisDimIdx]].getUnitLayoutInfo(thisDimIdx, Math.round(coordValue));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
export function resetXYLocatorRange(out) {
|
||||
var rg = out || [];
|
||||
rg[0] = rg[0] || [];
|
||||
rg[1] = rg[1] || [];
|
||||
rg[0][0] = rg[0][1] = rg[1][0] = rg[1][1] = NaN;
|
||||
return rg;
|
||||
}
|
||||
/**
|
||||
* If illegal or out of boundary, set NaN to `locOut`. See `isXYLocatorRangeInvalidOnDim`.
|
||||
* x dimension and y dimension are calculated separately.
|
||||
*/
|
||||
export function parseCoordRangeOption(locOut,
|
||||
// If illegal input or can not find any target, save reason to it.
|
||||
// Do nothing if `NullUndefined`.
|
||||
reasonOut, data, dims, clamp) {
|
||||
// x and y are supported to be handled separately - if one dimension is invalid
|
||||
// (may be users do not need that), the other one should also be calculated.
|
||||
parseCoordRangeOptionOnOneDim(locOut[0], reasonOut, clamp, data, dims, 0);
|
||||
parseCoordRangeOptionOnOneDim(locOut[1], reasonOut, clamp, data, dims, 1);
|
||||
}
|
||||
function parseCoordRangeOptionOnOneDim(locDimOut, reasonOut, clamp, data, dims, dimIdx) {
|
||||
locDimOut[0] = Infinity;
|
||||
locDimOut[1] = -Infinity;
|
||||
var dataOnDim = data[dimIdx];
|
||||
var coordValArr = isArray(dataOnDim) ? dataOnDim : [dataOnDim];
|
||||
var len = coordValArr.length;
|
||||
var hasClamp = !!clamp;
|
||||
if (len >= 1) {
|
||||
parseCoordRangeOptionOnOneDimOnePart(locDimOut, reasonOut, coordValArr, hasClamp, dims, dimIdx, 0);
|
||||
if (len > 1) {
|
||||
// Users may intuitively input the coords like `[[x1, x2, x3], ...]`;
|
||||
// consider the range as `[x1, x3]` in this case.
|
||||
parseCoordRangeOptionOnOneDimOnePart(locDimOut, reasonOut, coordValArr, hasClamp, dims, dimIdx, len - 1);
|
||||
}
|
||||
} else {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (reasonOut) {
|
||||
reasonOut.push('Should be like [["x1", "x2"], ["y1", "y2"]], or ["x1", "y1"], rather than empty.');
|
||||
}
|
||||
}
|
||||
locDimOut[0] = locDimOut[1] = NaN;
|
||||
}
|
||||
if (hasClamp) {
|
||||
// null/undefined/NaN or illegal data represents the entire row/column;
|
||||
// Cover the entire locator regardless of body or corner, and confine it later.
|
||||
var locLowerBound = -dims[XY[1 - dimIdx]].getLocatorCount(dimIdx);
|
||||
var locUpperBound = dims[XY[dimIdx]].getLocatorCount(dimIdx) - 1;
|
||||
if (clamp === MatrixClampOption.body) {
|
||||
locLowerBound = mathMax(0, locLowerBound);
|
||||
} else if (clamp === MatrixClampOption.corner) {
|
||||
locUpperBound = mathMin(-1, locUpperBound);
|
||||
}
|
||||
if (locUpperBound < locLowerBound) {
|
||||
// Also considered that both x and y has no cell.
|
||||
locLowerBound = locUpperBound = NaN;
|
||||
}
|
||||
if (eqNaN(locDimOut[0])) {
|
||||
locDimOut[0] = locLowerBound;
|
||||
}
|
||||
if (eqNaN(locDimOut[1])) {
|
||||
locDimOut[1] = locUpperBound;
|
||||
}
|
||||
locDimOut[0] = mathMax(mathMin(locDimOut[0], locUpperBound), locLowerBound);
|
||||
locDimOut[1] = mathMax(mathMin(locDimOut[1], locUpperBound), locLowerBound);
|
||||
}
|
||||
}
|
||||
// The return val must be finite or NaN.
|
||||
function parseCoordRangeOptionOnOneDimOnePart(locDimOut, reasonOut, coordValArr, hasClamp, dims, dimIdx, partIdx) {
|
||||
var layout = coordDataToAllCellLevelLayout(coordValArr[partIdx], dims, dimIdx);
|
||||
if (!layout) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (!hasClamp && reasonOut) {
|
||||
reasonOut.push("Can not find cell by coord[" + dimIdx + "][" + partIdx + "].");
|
||||
}
|
||||
}
|
||||
locDimOut[0] = locDimOut[1] = NaN;
|
||||
return;
|
||||
}
|
||||
var locatorA = layout.id[XY[dimIdx]];
|
||||
var locatorB = locatorA;
|
||||
var dimCell = cellLayoutInfoToDimCell(layout);
|
||||
if (dimCell) {
|
||||
// Handle non-leaf
|
||||
locatorB += dimCell.span[XY[dimIdx]] - 1;
|
||||
}
|
||||
locDimOut[0] = mathMin(locDimOut[0], locatorA, locatorB);
|
||||
locDimOut[1] = mathMax(locDimOut[1], locatorA, locatorB);
|
||||
}
|
||||
/**
|
||||
* @param locatorRange Must be the return of `parseCoordRangeOption`,
|
||||
* where if not NaN, it must be a valid locator.
|
||||
*/
|
||||
export function isXYLocatorRangeInvalidOnDim(locatorRange, dimIdx) {
|
||||
return eqNaN(locatorRange[dimIdx][0]) || eqNaN(locatorRange[dimIdx][1]);
|
||||
}
|
||||
// `locatorRange` will be expanded (modified) if an intersection is encountered.
|
||||
export function resolveXYLocatorRangeByCellMerge(inOutLocatorRange,
|
||||
// Item indices coorespond to mergeDefList (len: mergeDefListTravelLen).
|
||||
// Indicating whether each item has be merged into the `locatorRange`
|
||||
outMergedMarkList, mergeDefList, mergeDefListTravelLen) {
|
||||
outMergedMarkList = outMergedMarkList || _tmpOutMergedMarkList;
|
||||
for (var idx = 0; idx < mergeDefListTravelLen; idx++) {
|
||||
outMergedMarkList[idx] = false;
|
||||
}
|
||||
// In most case, cell merging definition list length is smaller than the range extent,
|
||||
// therefore, to detection intersection, travelling cell merging definition list is probably
|
||||
// performant than traveling the four edges of the rect formed by the locator range.
|
||||
while (true) {
|
||||
var expanded = false;
|
||||
for (var idx = 0; idx < mergeDefListTravelLen; idx++) {
|
||||
var mergeDef = mergeDefList[idx];
|
||||
if (!outMergedMarkList[idx] && mergeDef.cellMergeOwner && expandXYLocatorRangeIfIntersect(inOutLocatorRange, mergeDef.locatorRange)) {
|
||||
outMergedMarkList[idx] = true;
|
||||
expanded = true;
|
||||
}
|
||||
}
|
||||
if (!expanded) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
var _tmpOutMergedMarkList = [];
|
||||
// Return whether intersect.
|
||||
// `thisLocRange` will be expanded (modified) if an intersection is encountered.
|
||||
function expandXYLocatorRangeIfIntersect(thisLocRange, otherLocRange) {
|
||||
if (!locatorRangeIntersectOneDim(thisLocRange[0], otherLocRange[0]) || !locatorRangeIntersectOneDim(thisLocRange[1], otherLocRange[1])) {
|
||||
return false;
|
||||
}
|
||||
thisLocRange[0][0] = mathMin(thisLocRange[0][0], otherLocRange[0][0]);
|
||||
thisLocRange[0][1] = mathMax(thisLocRange[0][1], otherLocRange[0][1]);
|
||||
thisLocRange[1][0] = mathMin(thisLocRange[1][0], otherLocRange[1][0]);
|
||||
thisLocRange[1][1] = mathMax(thisLocRange[1][1], otherLocRange[1][1]);
|
||||
return true;
|
||||
}
|
||||
// Notice: If containing NaN, not intersect.
|
||||
function locatorRangeIntersectOneDim(locRange1OneDim, locRange2OneDim) {
|
||||
return locRange1OneDim[1] >= locRange2OneDim[0] && locRange1OneDim[0] <= locRange2OneDim[1];
|
||||
}
|
||||
export function fillIdSpanFromLocatorRange(owner, locatorRange) {
|
||||
owner.id.set(locatorRange[0][0], locatorRange[1][0]);
|
||||
owner.span.set(locatorRange[0][1] - owner.id.x + 1, locatorRange[1][1] - owner.id.y + 1);
|
||||
}
|
||||
export function cloneXYLocatorRange(target, source) {
|
||||
target[0][0] = source[0][0];
|
||||
target[0][1] = source[0][1];
|
||||
target[1][0] = source[1][0];
|
||||
target[1][1] = source[1][1];
|
||||
}
|
||||
/**
|
||||
* If illegal, the corresponding x/y/width/height is set to `NaN`.
|
||||
* `x/width` or `y/height` is supported to be calculated separately,
|
||||
* i.e., one side are NaN, the other side are normal.
|
||||
* @param oneDimOut only write to `x/width` or `y/height`, depending on `dimIdx`.
|
||||
*/
|
||||
export function xyLocatorRangeToRectOneDim(oneDimOut, locRange, dims, dimIdx) {
|
||||
var layoutMin = coordDataToAllCellLevelLayout(locRange[dimIdx][0], dims, dimIdx);
|
||||
var layoutMax = coordDataToAllCellLevelLayout(locRange[dimIdx][1], dims, dimIdx);
|
||||
oneDimOut[XY[dimIdx]] = oneDimOut[WH[dimIdx]] = NaN;
|
||||
if (layoutMin && layoutMax) {
|
||||
oneDimOut[XY[dimIdx]] = layoutMin.xy;
|
||||
oneDimOut[WH[dimIdx]] = layoutMax.xy + layoutMax.wh - layoutMin.xy;
|
||||
}
|
||||
}
|
||||
// No need currently, since `span` is not allowed to be defined directly by users.
|
||||
// /**
|
||||
// * If either span x or y is valid and > 1, return parsed span, otherwise return `NullUndefined`.
|
||||
// */
|
||||
// export function parseSpanOption(
|
||||
// spanOptionHost: MatrixCellSpanOptionHost,
|
||||
// dimCellPair: MatrixCellLayoutInfo[]
|
||||
// ): Point | NullUndefined {
|
||||
// const spanX = parseSpanOnDim(spanOptionHost.spanX, dimCellPair[0], 0);
|
||||
// const spanY = parseSpanOnDim(spanOptionHost.spanY, dimCellPair[1], 1);
|
||||
// if (!eqNaN(spanX) || !eqNaN(spanY)) {
|
||||
// return new Point(spanX || 1, spanY || 1);
|
||||
// }
|
||||
// function parseSpanOnDim(spanOption: unknown, dimCell: MatrixCellLayoutInfo, dimIdx: number): number {
|
||||
// if (!isNumber(spanOption)) {
|
||||
// return NaN;
|
||||
// }
|
||||
// // Ensure positive integer (not NaN) to avoid dead loop.
|
||||
// const span = mathMax(1, Math.round(spanOption || 1)) || 1;
|
||||
// // Clamp, and consider may also be specified as `Infinity` to span the entire col/row.
|
||||
// return mathMin(span, mathMax(1, dimCell.dim.getLocatorCount(dimIdx) - dimCell.id[XY[dimIdx]]));
|
||||
// }
|
||||
// }
|
||||
/**
|
||||
* @usage To get/set on dimension, use:
|
||||
* `xyVal[XY[dim]] = val;` // set on this dimension.
|
||||
* `xyVal[XY[1 - dim]] = val;` // set on the perpendicular dimension.
|
||||
*/
|
||||
export function setDimXYValue(out, dimIdx,
|
||||
// 0 | 1
|
||||
valueOnThisDim, valueOnOtherDim) {
|
||||
out[XY[dimIdx]] = valueOnThisDim;
|
||||
out[XY[1 - dimIdx]] = valueOnOtherDim;
|
||||
return out;
|
||||
}
|
||||
/**
|
||||
* Return NullUndefined if not dimension cell.
|
||||
*/
|
||||
function cellLayoutInfoToDimCell(cellLayoutInfo) {
|
||||
return cellLayoutInfo && (cellLayoutInfo.type === MatrixCellLayoutInfoType.leaf || cellLayoutInfo.type === MatrixCellLayoutInfoType.nonLeaf) ? cellLayoutInfo : null;
|
||||
}
|
||||
export function createNaNRectLike() {
|
||||
return {
|
||||
x: NaN,
|
||||
y: NaN,
|
||||
width: NaN,
|
||||
height: NaN
|
||||
};
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
export default function matrixPrepareCustom(coordSys) {
|
||||
var rect = coordSys.getRect();
|
||||
return {
|
||||
coordSys: {
|
||||
type: 'matrix',
|
||||
x: rect.x,
|
||||
y: rect.y,
|
||||
width: rect.width,
|
||||
height: rect.height
|
||||
},
|
||||
api: {
|
||||
coord: function (data, opt) {
|
||||
return coordSys.dataToPoint(data, opt);
|
||||
},
|
||||
layout: function (data, opt) {
|
||||
return coordSys.dataToLayout(data, opt);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user