UNPKG

ag-grid-enterprise

Version:

AG Grid Enterprise Features

471 lines 24.6 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __values = (this && this.__values) || function(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); }; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.CartesianChart = void 0; var chart_1 = require("./chart"); var categoryAxis_1 = require("./axis/categoryAxis"); var groupedCategoryAxis_1 = require("./axis/groupedCategoryAxis"); var chartAxisDirection_1 = require("./chartAxisDirection"); var logger_1 = require("../util/logger"); var angle_1 = require("../util/angle"); var directions = ['top', 'right', 'bottom', 'left']; var CartesianChart = /** @class */ (function (_super) { __extends(CartesianChart, _super); function CartesianChart(document, overrideDevicePixelRatio, resources) { if (document === void 0) { document = window.document; } var _this = _super.call(this, document, overrideDevicePixelRatio, resources) || this; /** Integrated Charts feature state - not used in Standalone Charts. */ _this.paired = true; _this._lastAxisWidths = { top: 0, bottom: 0, left: 0, right: 0, }; _this._lastVisibility = { crossLines: true, series: true, }; return _this; } CartesianChart.prototype.performLayout = function () { return __awaiter(this, void 0, void 0, function () { var shrinkRect, _a, seriesRect, visibility, clipSeries, _b, seriesRoot, seriesAreaPadding, seriesPaddedRect, hoverRectPadding, hoverRect; return __generator(this, function (_c) { switch (_c.label) { case 0: return [4 /*yield*/, _super.prototype.performLayout.call(this)]; case 1: shrinkRect = _c.sent(); _a = this.updateAxes(shrinkRect), seriesRect = _a.seriesRect, visibility = _a.visibility, clipSeries = _a.clipSeries; this.seriesRoot.visible = visibility.series; this.seriesRect = seriesRect; this.seriesRoot.translationX = Math.floor(seriesRect.x); this.seriesRoot.translationY = Math.floor(seriesRect.y); _b = this, seriesRoot = _b.seriesRoot, seriesAreaPadding = _b.seriesAreaPadding; seriesPaddedRect = seriesRect.clone().grow({ top: seriesAreaPadding.top, right: seriesAreaPadding.right, bottom: seriesAreaPadding.bottom, left: seriesAreaPadding.left, }); hoverRectPadding = 20; hoverRect = seriesPaddedRect.clone().grow(hoverRectPadding); this.hoverRect = hoverRect; this.layoutService.dispatchLayoutComplete({ type: 'layout-complete', chart: { width: this.scene.width, height: this.scene.height }, series: { rect: seriesRect, paddedRect: seriesPaddedRect, hoverRect: hoverRect, visible: visibility.series }, axes: this.axes.map(function (axis) { return (__assign({ id: axis.id }, axis.getLayoutState())); }), }); if (clipSeries) { seriesRoot.setClipRectInGroupCoordinateSpace(seriesRect); } else { seriesRoot.setClipRectInGroupCoordinateSpace(); } return [2 /*return*/, shrinkRect]; } }); }); }; CartesianChart.prototype.updateAxes = function (inputShrinkRect) { var e_1, _a; var _b; // Start with a good approximation from the last update - this should mean that in many resize // cases that only a single pass is needed \o/. var axisWidths = __assign({}, this._lastAxisWidths); var visibility = __assign({}, this._lastVisibility); // Clean any positions which aren't valid with the current axis status (otherwise we end up // never being able to find a stable result). var liveAxisWidths = new Set(this._axes.map(function (a) { return a.position; })); try { for (var _c = __values(Object.keys(axisWidths)), _d = _c.next(); !_d.done; _d = _c.next()) { var position = _d.value; if (!liveAxisWidths.has(position)) { delete axisWidths[position]; } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_d && !_d.done && (_a = _c.return)) _a.call(_c); } finally { if (e_1) throw e_1.error; } } var stableOutputs = function (otherAxisWidths, otherVisibility) { // Check for new axis positions. if (Object.keys(otherAxisWidths).some(function (k) { return axisWidths[k] == null; })) { return false; } return (visibility.crossLines === otherVisibility.crossLines && visibility.series === otherVisibility.series && // Check for existing axis positions and equality. Object.entries(axisWidths).every(function (_a) { var _b = __read(_a, 2), p = _b[0], w = _b[1]; var otherW = otherAxisWidths[p]; if (w != null || otherW != null) { return w === otherW; } return true; })); }; var ceilValues = function (records) { return Object.entries(records).reduce(function (out, _a) { var _b = __read(_a, 2), key = _b[0], value = _b[1]; if (value && Math.abs(value) === Infinity) { value = 0; } out[key] = value != null ? Math.ceil(value) : value; return out; }, {}); }; // Iteratively try to resolve axis widths - since X axis width affects Y axis range, // and vice-versa, we need to iteratively try and find a fit for the axes and their // ticks/labels. var lastPassAxisWidths = {}; var lastPassVisibility = {}; var clipSeries = false; var seriesRect = (_b = this.seriesRect) === null || _b === void 0 ? void 0 : _b.clone(); var count = 0; do { Object.assign(axisWidths, lastPassAxisWidths); Object.assign(visibility, lastPassVisibility); var result = this.updateAxesPass(axisWidths, inputShrinkRect.clone(), seriesRect); lastPassAxisWidths = ceilValues(result.axisWidths); lastPassVisibility = result.visibility; clipSeries = result.clipSeries; seriesRect = result.seriesRect; if (count++ > 10) { logger_1.Logger.warn('unable to find stable axis layout.'); break; } } while (!stableOutputs(lastPassAxisWidths, lastPassVisibility)); var clipRectPadding = 5; this.axes.forEach(function (axis) { // update visibility of crosslines axis.setCrossLinesVisible(visibility.crossLines); if (!seriesRect) { return; } axis.clipGrid(seriesRect.x, seriesRect.y, seriesRect.width + clipRectPadding, seriesRect.height + clipRectPadding); switch (axis.position) { case 'left': case 'right': axis.clipTickLines(inputShrinkRect.x, seriesRect.y, inputShrinkRect.width + clipRectPadding, seriesRect.height + clipRectPadding); break; case 'top': case 'bottom': axis.clipTickLines(seriesRect.x, inputShrinkRect.y, seriesRect.width + clipRectPadding, inputShrinkRect.height + clipRectPadding); break; } }); this._lastAxisWidths = axisWidths; this._lastVisibility = visibility; return { seriesRect: seriesRect, visibility: visibility, clipSeries: clipSeries }; }; CartesianChart.prototype.updateAxesPass = function (axisWidths, bounds, lastPassSeriesRect) { var _this = this; var axes = this.axes; var visited = {}; var newAxisWidths = {}; var visibility = { series: true, crossLines: true, }; var clipSeries = false; var primaryTickCounts = {}; var paddedBounds = this.applySeriesPadding(bounds); var crossLinePadding = lastPassSeriesRect ? this.buildCrossLinePadding(axisWidths) : {}; var axisBound = this.buildAxisBound(paddedBounds, axisWidths, crossLinePadding, visibility); var seriesRect = this.buildSeriesRect(axisBound, axisWidths); // Set the number of ticks for continuous axes based on the available range // before updating the axis domain via `this.updateAxes()` as the tick count has an effect on the calculated `nice` domain extent axes.forEach(function (axis) { var _a, _b; var _c = axis.position, position = _c === void 0 ? 'left' : _c; var _d = _this.calculateAxisDimensions({ axis: axis, seriesRect: seriesRect, paddedBounds: paddedBounds, axisWidths: axisWidths, newAxisWidths: newAxisWidths, primaryTickCounts: primaryTickCounts, clipSeries: clipSeries, addInterAxisPadding: ((_a = visited[position]) !== null && _a !== void 0 ? _a : 0) > 0, }), newClipSeries = _d.clipSeries, axisThickness = _d.axisThickness, axisOffset = _d.axisOffset; visited[position] = ((_b = visited[position]) !== null && _b !== void 0 ? _b : 0) + 1; clipSeries = clipSeries || newClipSeries; _this.positionAxis({ axis: axis, axisBound: axisBound, axisOffset: axisOffset, axisThickness: axisThickness, axisWidths: axisWidths, primaryTickCounts: primaryTickCounts, seriesRect: seriesRect, }); }); return { clipSeries: clipSeries, seriesRect: seriesRect, axisWidths: newAxisWidths, visibility: visibility }; }; CartesianChart.prototype.buildCrossLinePadding = function (axisWidths) { var e_2, _a; var _b; var crossLinePadding = {}; this.axes.forEach(function (axis) { if (axis.crossLines) { axis.crossLines.forEach(function (crossLine) { crossLine.calculatePadding(crossLinePadding); }); } }); try { // Reduce cross-line padding to account for overlap with axes. for (var _c = __values(Object.entries(crossLinePadding)), _d = _c.next(); !_d.done; _d = _c.next()) { var _e = __read(_d.value, 2), side = _e[0], _f = _e[1], padding = _f === void 0 ? 0 : _f; crossLinePadding[side] = Math.max(padding - ((_b = axisWidths[side]) !== null && _b !== void 0 ? _b : 0), 0); } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (_d && !_d.done && (_a = _c.return)) _a.call(_c); } finally { if (e_2) throw e_2.error; } } return crossLinePadding; }; CartesianChart.prototype.applySeriesPadding = function (bounds) { var _this = this; var paddedRect = bounds.clone(); var reversedAxes = this.axes.slice().reverse(); directions.forEach(function (dir) { var padding = _this.seriesAreaPadding[dir]; var axis = reversedAxes.find(function (axis) { return axis.position === dir; }); if (axis) { axis.seriesAreaPadding = padding; } else { paddedRect.shrink(padding, dir); } }); return paddedRect; }; CartesianChart.prototype.buildAxisBound = function (bounds, axisWidths, crossLinePadding, visibility) { var _a, _b, _c, _d; var result = bounds.clone(); var _e = crossLinePadding.top, top = _e === void 0 ? 0 : _e, _f = crossLinePadding.right, right = _f === void 0 ? 0 : _f, _g = crossLinePadding.bottom, bottom = _g === void 0 ? 0 : _g, _h = crossLinePadding.left, left = _h === void 0 ? 0 : _h; var horizontalPadding = left + right; var verticalPadding = top + bottom; var totalWidth = ((_a = axisWidths.left) !== null && _a !== void 0 ? _a : 0) + ((_b = axisWidths.right) !== null && _b !== void 0 ? _b : 0) + horizontalPadding; var totalHeight = ((_c = axisWidths.top) !== null && _c !== void 0 ? _c : 0) + ((_d = axisWidths.bottom) !== null && _d !== void 0 ? _d : 0) + verticalPadding; if (result.width <= totalWidth || result.height <= totalHeight) { // Not enough space for crossLines and series visibility.crossLines = false; visibility.series = false; return result; } result.x += left; result.y += top; result.width -= horizontalPadding; result.height -= verticalPadding; return result; }; CartesianChart.prototype.buildSeriesRect = function (axisBound, axisWidths) { var result = axisBound.clone(); var top = axisWidths.top, bottom = axisWidths.bottom, left = axisWidths.left, right = axisWidths.right; result.x += left !== null && left !== void 0 ? left : 0; result.y += top !== null && top !== void 0 ? top : 0; result.width -= (left !== null && left !== void 0 ? left : 0) + (right !== null && right !== void 0 ? right : 0); result.height -= (top !== null && top !== void 0 ? top : 0) + (bottom !== null && bottom !== void 0 ? bottom : 0); // Width and height should not be negative. result.width = Math.max(0, result.width); result.height = Math.max(0, result.height); return result; }; CartesianChart.prototype.clampToOutsideSeriesRect = function (seriesRect, value, dimension, direction) { var x = seriesRect.x, y = seriesRect.y, width = seriesRect.width, height = seriesRect.height; var clampBounds = [x, y, x + width, y + height]; var fn = direction === 1 ? Math.min : Math.max; var compareTo = clampBounds[(dimension === 'x' ? 0 : 1) + (direction === 1 ? 0 : 2)]; return fn(value, compareTo); }; CartesianChart.prototype.calculateAxisDimensions = function (opts) { var _a, _b, _c, _d, _e; var axis = opts.axis, seriesRect = opts.seriesRect, paddedBounds = opts.paddedBounds, axisWidths = opts.axisWidths, newAxisWidths = opts.newAxisWidths, primaryTickCounts = opts.primaryTickCounts, addInterAxisPadding = opts.addInterAxisPadding; var clipSeries = opts.clipSeries; var _f = axis.position, position = _f === void 0 ? 'left' : _f, direction = axis.direction; var axisLeftRightRange = function (axis) { if (axis instanceof categoryAxis_1.CategoryAxis || axis instanceof groupedCategoryAxis_1.GroupedCategoryAxis) { return [0, seriesRect.height]; } return [seriesRect.height, 0]; }; var axisOffset = (_a = newAxisWidths[position]) !== null && _a !== void 0 ? _a : 0; switch (position) { case 'top': case 'bottom': axis.range = [0, seriesRect.width]; axis.gridLength = seriesRect.height; break; case 'right': case 'left': axis.range = axisLeftRightRange(axis); axis.gridLength = seriesRect.width; break; } var zoom = this.zoomManager.getAxisZoom(axis.id); var _g = zoom !== null && zoom !== void 0 ? zoom : {}, _h = _g.min, min = _h === void 0 ? 0 : _h, _j = _g.max, max = _j === void 0 ? 1 : _j; axis.visibleRange = [min, max]; if (!clipSeries && (axis.visibleRange[0] > 0 || axis.visibleRange[1] < 1)) { clipSeries = true; } var primaryTickCount = axis.nice ? primaryTickCounts[direction] : undefined; var paddedBoundsCoefficient = 0.3; if (axis.thickness != null && axis.thickness > 0) { axis.maxThickness = axis.thickness; } else if (direction === chartAxisDirection_1.ChartAxisDirection.Y) { axis.maxThickness = paddedBounds.width * paddedBoundsCoefficient; } else { axis.maxThickness = paddedBounds.height * paddedBoundsCoefficient; } primaryTickCount = axis.update(primaryTickCount); primaryTickCounts[direction] = (_b = primaryTickCounts[direction]) !== null && _b !== void 0 ? _b : primaryTickCount; var axisThickness = 0; if (axis.thickness != null && axis.thickness > 0) { axisThickness = axis.thickness; } else { var bbox = axis.computeBBox(); axisThickness = direction === chartAxisDirection_1.ChartAxisDirection.X ? bbox.height : bbox.width; } // for multiple axes in the same direction and position, apply padding at the top of each inner axis (i.e. between axes). var axisPadding = 15; if (addInterAxisPadding) { axisThickness += axisPadding; } axisThickness = Math.ceil(axisThickness); newAxisWidths[position] = ((_c = newAxisWidths[position]) !== null && _c !== void 0 ? _c : 0) + axisThickness; axis.gridPadding = ((_d = axisWidths[position]) !== null && _d !== void 0 ? _d : 0) - ((_e = newAxisWidths[position]) !== null && _e !== void 0 ? _e : 0); return { clipSeries: clipSeries, axisThickness: axisThickness, axisOffset: axisOffset }; }; CartesianChart.prototype.positionAxis = function (opts) { var _a, _b, _c, _d; var axis = opts.axis, axisBound = opts.axisBound, axisWidths = opts.axisWidths, seriesRect = opts.seriesRect, axisOffset = opts.axisOffset, axisThickness = opts.axisThickness; var position = axis.position; switch (position) { case 'top': axis.translation.x = axisBound.x + ((_a = axisWidths.left) !== null && _a !== void 0 ? _a : 0); axis.translation.y = this.clampToOutsideSeriesRect(seriesRect, axisBound.y + 1 + axisOffset + axisThickness, 'y', 1); break; case 'bottom': axis.translation.x = axisBound.x + ((_b = axisWidths.left) !== null && _b !== void 0 ? _b : 0); axis.translation.y = this.clampToOutsideSeriesRect(seriesRect, axisBound.y + axisBound.height + 1 - axisThickness - axisOffset, 'y', -1); break; case 'left': axis.translation.y = axisBound.y + ((_c = axisWidths.top) !== null && _c !== void 0 ? _c : 0); axis.translation.x = this.clampToOutsideSeriesRect(seriesRect, axisBound.x + axisOffset + axisThickness, 'x', 1); break; case 'right': axis.translation.y = axisBound.y + ((_d = axisWidths.top) !== null && _d !== void 0 ? _d : 0); axis.translation.x = this.clampToOutsideSeriesRect(seriesRect, axisBound.x + axisBound.width - axisThickness - axisOffset, 'x', -1); break; } axis.updatePosition({ rotation: angle_1.toRadians(axis.rotation), sideFlag: axis.label.getSideFlag() }); }; CartesianChart.className = 'CartesianChart'; CartesianChart.type = 'cartesian'; return CartesianChart; }(chart_1.Chart)); exports.CartesianChart = CartesianChart; //# sourceMappingURL=cartesianChart.js.map