ag-grid-enterprise
Version:
AG Grid Enterprise Features
596 lines • 25.7 kB
JavaScript
"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 __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
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.");
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.splitText = exports.measureText = exports.getFont = exports.createTextMeasurer = exports.Text = void 0;
var shape_1 = require("./shape");
var bbox_1 = require("../bbox");
var hdpiCanvas_1 = require("../../canvas/hdpiCanvas");
var node_1 = require("../node");
var ellipsis = '\u2026';
function SceneFontChangeDetection(opts) {
var _a = opts !== null && opts !== void 0 ? opts : {}, _b = _a.redraw, redraw = _b === void 0 ? node_1.RedrawType.MAJOR : _b, changeCb = _a.changeCb;
return node_1.SceneChangeDetection({ redraw: redraw, type: 'font', changeCb: changeCb });
}
var Text = /** @class */ (function (_super) {
__extends(Text, _super);
function Text() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.x = 0;
_this.y = 0;
_this.lines = [];
_this.text = undefined;
_this._dirtyFont = true;
_this.fontSize = 10;
_this.fontFamily = 'sans-serif';
_this.textAlign = Text.defaultStyles.textAlign;
_this.textBaseline = Text.defaultStyles.textBaseline;
// TextMetrics are used if lineHeight is not defined.
_this.lineHeight = undefined;
return _this;
}
Text.prototype._setLines = function () {
this.lines = splitText(this.text);
};
Object.defineProperty(Text.prototype, "font", {
get: function () {
if (this._font == null || this._dirtyFont) {
this._dirtyFont = false;
this._font = getFont(this);
}
return this._font;
},
enumerable: false,
configurable: true
});
Text.prototype.computeBBox = function () {
return hdpiCanvas_1.HdpiCanvas.has.textMetrics
? getPreciseBBox(this.lines, this.x, this.y, this)
: getApproximateBBox(this.lines, this.x, this.y, this);
};
Text.prototype.getLineHeight = function (line) {
var _a, _b;
if (this.lineHeight)
return this.lineHeight;
if (hdpiCanvas_1.HdpiCanvas.has.textMetrics) {
var metrics = hdpiCanvas_1.HdpiCanvas.measureText(line, this.font, this.textBaseline, this.textAlign);
return (((_a = metrics.fontBoundingBoxAscent) !== null && _a !== void 0 ? _a : metrics.emHeightAscent) +
((_b = metrics.fontBoundingBoxDescent) !== null && _b !== void 0 ? _b : metrics.emHeightDescent));
}
return hdpiCanvas_1.HdpiCanvas.getTextSize(line, this.font).height;
};
Text.prototype.isPointInPath = function (x, y) {
var point = this.transformPoint(x, y);
var bbox = this.computeBBox();
return bbox ? bbox.containsPoint(point.x, point.y) : false;
};
Text.prototype.render = function (renderCtx) {
var ctx = renderCtx.ctx, forceRender = renderCtx.forceRender, stats = renderCtx.stats;
if (this.dirty === node_1.RedrawType.NONE && !forceRender) {
if (stats)
stats.nodesSkipped += this.nodeCount.count;
return;
}
if (!this.lines.length || !this.layerManager) {
if (stats)
stats.nodesSkipped += this.nodeCount.count;
return;
}
this.computeTransformMatrix();
this.matrix.toContext(ctx);
var _a = this, fill = _a.fill, stroke = _a.stroke, strokeWidth = _a.strokeWidth;
ctx.font = this.font;
ctx.textAlign = this.textAlign;
ctx.textBaseline = this.textBaseline;
var pixelRatio = this.layerManager.canvas.pixelRatio || 1;
var globalAlpha = ctx.globalAlpha;
if (fill) {
ctx.fillStyle = fill;
ctx.globalAlpha = globalAlpha * this.opacity * this.fillOpacity;
var fillShadow = this.fillShadow;
if (fillShadow === null || fillShadow === void 0 ? void 0 : fillShadow.enabled) {
ctx.shadowColor = fillShadow.color;
ctx.shadowOffsetX = fillShadow.xOffset * pixelRatio;
ctx.shadowOffsetY = fillShadow.yOffset * pixelRatio;
ctx.shadowBlur = fillShadow.blur * pixelRatio;
}
this.renderLines(function (line, x, y) { return ctx.fillText(line, x, y); });
}
if (stroke && strokeWidth) {
ctx.strokeStyle = stroke;
ctx.lineWidth = strokeWidth;
ctx.globalAlpha = globalAlpha * this.opacity * this.strokeOpacity;
var _b = this, lineDash = _b.lineDash, lineDashOffset = _b.lineDashOffset, lineCap = _b.lineCap, lineJoin = _b.lineJoin;
if (lineDash) {
ctx.setLineDash(lineDash);
}
if (lineDashOffset) {
ctx.lineDashOffset = lineDashOffset;
}
if (lineCap) {
ctx.lineCap = lineCap;
}
if (lineJoin) {
ctx.lineJoin = lineJoin;
}
this.renderLines(function (line, x, y) { return ctx.strokeText(line, x, y); });
}
_super.prototype.render.call(this, renderCtx);
};
Text.prototype.renderLines = function (renderCallback) {
var _this = this;
var _a = this, lines = _a.lines, x = _a.x, y = _a.y;
var lineHeights = this.lines.map(function (line) { return _this.getLineHeight(line); });
var totalHeight = lineHeights.reduce(function (a, b) { return a + b; }, 0);
var offsetY = -(totalHeight - lineHeights[0]) * getVerticalOffset(this.textBaseline);
for (var i = 0; i < lines.length; i++) {
renderCallback(lines[i], x, y + offsetY);
offsetY += lineHeights[i];
}
};
Text.wrap = function (text, maxWidth, maxHeight, textProps, wrapping) {
var e_1, _a;
var font = getFont(textProps);
var measurer = createTextMeasurer(font);
var lines = text.split(/\r?\n/g);
if (lines.length === 0) {
return '';
}
if (wrapping === 'never') {
return Text.truncateLine(lines[0], maxWidth, measurer, false);
}
var result = [];
var cumulativeHeight = 0;
try {
for (var lines_1 = __values(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
var line = lines_1_1.value;
var wrappedLine = Text.wrapLine(line, maxWidth, maxHeight, measurer, textProps, wrapping, cumulativeHeight);
result.push(wrappedLine.result);
cumulativeHeight = wrappedLine.cumulativeHeight;
if (wrappedLine.truncated) {
break;
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
}
finally { if (e_1) throw e_1.error; }
}
return result.join('\n').trim();
};
Text.wrapLine = function (text, maxWidth, maxHeight, measurer, textProps, wrapping, cumulativeHeight) {
text = text.trim();
if (!text) {
return { result: '', truncated: false, cumulativeHeight: cumulativeHeight };
}
var initialSize = measurer.size(text);
if (initialSize.width <= maxWidth) {
// Text fits into a single line
return { result: text, truncated: false, cumulativeHeight: cumulativeHeight + initialSize.height };
}
if (initialSize.height > maxHeight || measurer.width('W') > maxWidth) {
// Not enough space for a single line or character
return { result: '', truncated: true, cumulativeHeight: cumulativeHeight };
}
var words = text.split(/\s+/g);
var wrapResult = Text.wrapLineSequentially(words, maxWidth, maxHeight, measurer, textProps, wrapping, cumulativeHeight);
cumulativeHeight = wrapResult.cumulativeHeight;
var lines = wrapResult.lines;
if (!(wrapResult.wordsBrokenOrTruncated || wrapResult.linesTruncated)) {
// If no word breaks or truncations, try the balanced wrapping
var linesCount = wrapResult.lines.length;
var balanced = Text.wrapLineBalanced(words, maxWidth, measurer, linesCount);
if (balanced.length === lines.length) {
// Some lines can't be balanced properly because of unusually long words
lines = balanced;
}
}
var wrappedText = lines.map(function (ln) { return ln.join(' '); }).join('\n');
return { result: wrappedText, truncated: wrapResult.linesTruncated, cumulativeHeight: cumulativeHeight };
};
Text.breakWord = function (word, firstLineWidth, maxWidth, hyphens, measurer) {
var e_2, _a;
var isPunctuationAt = function (index) { return Text.punctuationMarks.includes(word[index]); };
var h = hyphens ? measurer.width('-') : 0;
var breaks = [];
var partWidth = 0;
var p = 0;
for (var i = 0; i < word.length; i++) {
var c = word[i];
var w = measurer.width(c);
var limit = p === 0 ? firstLineWidth : maxWidth;
if (partWidth + w + h > limit) {
breaks.push(i);
partWidth = 0;
p++;
}
partWidth += w;
}
var parts = [];
var start = 0;
try {
for (var breaks_1 = __values(breaks), breaks_1_1 = breaks_1.next(); !breaks_1_1.done; breaks_1_1 = breaks_1.next()) {
var index = breaks_1_1.value;
var part = word.substring(start, index);
if (hyphens && part.length > 0 && !isPunctuationAt(index - 1) && !isPunctuationAt(index)) {
part += '-';
}
parts.push(part);
start = index;
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (breaks_1_1 && !breaks_1_1.done && (_a = breaks_1.return)) _a.call(breaks_1);
}
finally { if (e_2) throw e_2.error; }
}
parts.push(word.substring(start));
return parts;
};
Text.truncateLine = function (text, maxWidth, measurer, forceEllipsis) {
var lineWidth = measurer.width(text);
if (lineWidth < maxWidth && !forceEllipsis) {
return text;
}
var ellipsisWidth = measurer.width(ellipsis);
if (lineWidth + ellipsisWidth <= maxWidth) {
return "" + text + ellipsis;
}
var index = Math.floor((text.length * maxWidth) / lineWidth) + 1;
var trunc;
var truncWidth;
do {
trunc = text.substring(0, index);
truncWidth = measurer.width(trunc);
} while (--index >= 0 && truncWidth + ellipsisWidth > maxWidth);
return "" + trunc + ellipsis;
};
Text.wrapLineSequentially = function (words, maxWidth, maxHeight, measurer, textProps, wrapping, cumulativeHeight) {
var fontSize = textProps.fontSize, _a = textProps.lineHeight, lineHeight = _a === void 0 ? fontSize * Text.defaultLineHeightRatio : _a;
var breakWord = wrapping === 'always' || wrapping === 'hyphenate';
var hyphenate = wrapping === 'hyphenate';
var spaceWidth = measurer.width(' ');
var wordsBrokenOrTruncated = false;
var linesTruncated = false;
var lines = [];
var currentLine = [];
var lineWidth = 0;
var addNewLine = function () {
var expectedHeight = cumulativeHeight + lineHeight;
if (expectedHeight >= maxHeight) {
// Truncate the last line
var lastLine = currentLine.join(' ');
var trunc = Text.truncateLine(lastLine, maxWidth, measurer, true);
currentLine.splice(0, currentLine.length, trunc);
linesTruncated = true;
return false;
}
// Add new line
currentLine = [];
lineWidth = 0;
cumulativeHeight = expectedHeight;
lines.push(currentLine);
return true;
};
if (!addNewLine()) {
return { lines: lines, linesTruncated: true, wordsBrokenOrTruncated: wordsBrokenOrTruncated, cumulativeHeight: cumulativeHeight };
}
for (var i = 0; i < words.length; i++) {
var word = words[i];
var wordWidth = measurer.width(word);
var expectedSpaceWidth = currentLine.length === 0 ? 0 : spaceWidth;
var expectedLineWidth = lineWidth + expectedSpaceWidth + wordWidth;
if (expectedLineWidth <= maxWidth) {
// If the word fits, add it to the current line
currentLine.push(word);
lineWidth = expectedLineWidth;
continue;
}
if (wordWidth <= maxWidth) {
// If the word is not too long, put it onto new line
if (!addNewLine()) {
break;
}
currentLine.push(word);
lineWidth = wordWidth;
continue;
}
// Handle a long word
wordsBrokenOrTruncated = true;
if (breakWord) {
// Break the word into parts
var availWidth = maxWidth - lineWidth - expectedSpaceWidth;
var parts = Text.breakWord(word, availWidth, maxWidth, hyphenate, measurer);
var breakLoop = false;
for (var p = 0; p < parts.length; p++) {
var part = parts[p];
part && currentLine.push(part);
if (p === parts.length - 1) {
lineWidth = measurer.width(part);
}
else if (!addNewLine()) {
breakLoop = true;
break;
}
}
if (breakLoop)
break;
}
else {
// Truncate the word
if (!addNewLine()) {
break;
}
var trunc = Text.truncateLine(word, maxWidth, measurer, true);
currentLine.push(trunc);
if (i < words.length - 1) {
linesTruncated = true;
}
break;
}
}
return { lines: lines, linesTruncated: linesTruncated, wordsBrokenOrTruncated: wordsBrokenOrTruncated, cumulativeHeight: cumulativeHeight };
};
Text.wrapLineBalanced = function (words, maxWidth, measurer, linesCount) {
var e_3, _a;
var totalWordsWidth = words.reduce(function (sum, w) { return sum + measurer.width(w); }, 0);
var spaceWidth = measurer.width(' ');
var totalSpaceWidth = spaceWidth * (words.length - linesCount - 2);
var averageLineWidth = (totalWordsWidth + totalSpaceWidth) / linesCount;
var lines = [];
var currentLine = [];
var lineWidth = measurer.width(words[0]);
var newLine = true;
try {
for (var words_1 = __values(words), words_1_1 = words_1.next(); !words_1_1.done; words_1_1 = words_1.next()) {
var word = words_1_1.value;
var width = measurer.width(word);
if (newLine) {
// New line
currentLine = [];
currentLine.push(word);
lineWidth = width;
newLine = false;
lines.push(currentLine);
continue;
}
var expectedLineWidth = lineWidth + spaceWidth + width;
if (expectedLineWidth <= averageLineWidth) {
// Keep adding words to the line
currentLine.push(word);
lineWidth = expectedLineWidth;
}
else if (expectedLineWidth <= maxWidth) {
// Add the last word to the line
currentLine.push(word);
newLine = true;
}
else {
// Put the word onto the next line
currentLine = [word];
lineWidth = width;
lines.push(currentLine);
}
}
}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally {
try {
if (words_1_1 && !words_1_1.done && (_a = words_1.return)) _a.call(words_1);
}
finally { if (e_3) throw e_3.error; }
}
return lines;
};
Text.prototype.setFont = function (props) {
this.fontFamily = props.fontFamily;
this.fontSize = props.fontSize;
this.fontStyle = props.fontStyle;
this.fontWeight = props.fontWeight;
};
Text.prototype.setAlign = function (props) {
this.textAlign = props.textAlign;
this.textBaseline = props.textBaseline;
};
Text.className = 'Text';
// The default line spacing for document editors is usually 1.15
Text.defaultLineHeightRatio = 1.15;
Text.defaultStyles = Object.assign({}, shape_1.Shape.defaultStyles, {
textAlign: 'start',
fontStyle: undefined,
fontWeight: undefined,
fontSize: 10,
fontFamily: 'sans-serif',
textBaseline: 'alphabetic',
});
Text.punctuationMarks = ['.', ',', '-', ':', ';', '!', '?', "'", '"', '(', ')'];
__decorate([
node_1.SceneChangeDetection({ redraw: node_1.RedrawType.MAJOR })
], Text.prototype, "x", void 0);
__decorate([
node_1.SceneChangeDetection({ redraw: node_1.RedrawType.MAJOR })
], Text.prototype, "y", void 0);
__decorate([
node_1.SceneChangeDetection({ redraw: node_1.RedrawType.MAJOR, changeCb: function (o) { return o._setLines(); } })
], Text.prototype, "text", void 0);
__decorate([
SceneFontChangeDetection()
], Text.prototype, "fontStyle", void 0);
__decorate([
SceneFontChangeDetection()
], Text.prototype, "fontWeight", void 0);
__decorate([
SceneFontChangeDetection()
], Text.prototype, "fontSize", void 0);
__decorate([
SceneFontChangeDetection()
], Text.prototype, "fontFamily", void 0);
__decorate([
node_1.SceneChangeDetection({ redraw: node_1.RedrawType.MAJOR })
], Text.prototype, "textAlign", void 0);
__decorate([
node_1.SceneChangeDetection({ redraw: node_1.RedrawType.MAJOR })
], Text.prototype, "textBaseline", void 0);
__decorate([
node_1.SceneChangeDetection({ redraw: node_1.RedrawType.MAJOR })
], Text.prototype, "lineHeight", void 0);
return Text;
}(shape_1.Shape));
exports.Text = Text;
function createTextMeasurer(font) {
var cache = new Map();
var getTextSize = function (text) { return hdpiCanvas_1.HdpiCanvas.getTextSize(text, font); };
var getLineWidth = function (text) {
if (cache.has(text)) {
return cache.get(text);
}
var width = getTextSize(text).width;
cache.set(text, width);
return width;
};
return { size: getTextSize, width: getLineWidth };
}
exports.createTextMeasurer = createTextMeasurer;
function getFont(fontProps) {
var fontFamily = fontProps.fontFamily, fontSize = fontProps.fontSize, fontStyle = fontProps.fontStyle, fontWeight = fontProps.fontWeight;
return [fontStyle !== null && fontStyle !== void 0 ? fontStyle : '', fontWeight !== null && fontWeight !== void 0 ? fontWeight : '', fontSize + 'px', fontFamily].join(' ').trim();
}
exports.getFont = getFont;
function measureText(lines, x, y, textProps) {
return hdpiCanvas_1.HdpiCanvas.has.textMetrics
? getPreciseBBox(lines, x, y, textProps)
: getApproximateBBox(lines, x, y, textProps);
}
exports.measureText = measureText;
function getPreciseBBox(lines, x, y, textProps) {
var _a, _b;
var left = 0;
var top = 0;
var width = 0;
var height = 0;
// Distance between first and last base lines.
var baselineDistance = 0;
var font = getFont(textProps);
var lineHeight = textProps.lineHeight, _c = textProps.textBaseline, textBaseline = _c === void 0 ? Text.defaultStyles.textBaseline : _c, _d = textProps.textAlign, textAlign = _d === void 0 ? Text.defaultStyles.textAlign : _d;
for (var i = 0; i < lines.length; i++) {
var metrics = hdpiCanvas_1.HdpiCanvas.measureText(lines[i], font, textBaseline, textAlign);
left = Math.max(left, metrics.actualBoundingBoxLeft);
width = Math.max(width, metrics.width);
if (i == 0) {
top += metrics.actualBoundingBoxAscent;
height += metrics.actualBoundingBoxAscent;
}
else {
baselineDistance += (_a = metrics.fontBoundingBoxAscent) !== null && _a !== void 0 ? _a : metrics.emHeightAscent;
}
if (i == lines.length - 1) {
height += metrics.actualBoundingBoxDescent;
}
else {
baselineDistance += (_b = metrics.fontBoundingBoxDescent) !== null && _b !== void 0 ? _b : metrics.emHeightDescent;
}
}
if (lineHeight !== undefined) {
baselineDistance = (lines.length - 1) * lineHeight;
}
height += baselineDistance;
top += baselineDistance * getVerticalOffset(textBaseline);
return new bbox_1.BBox(x - left, y - top, width, height);
}
function getApproximateBBox(lines, x, y, textProps) {
var width = 0;
var firstLineHeight = 0;
// Distance between first and last base lines.
var baselineDistance = 0;
var font = getFont(textProps);
var lineHeight = textProps.lineHeight, _a = textProps.textBaseline, textBaseline = _a === void 0 ? Text.defaultStyles.textBaseline : _a, _b = textProps.textAlign, textAlign = _b === void 0 ? Text.defaultStyles.textAlign : _b;
if (lines.length > 0) {
var lineSize = hdpiCanvas_1.HdpiCanvas.getTextSize(lines[0], font);
width = lineSize.width;
firstLineHeight = lineSize.height;
}
for (var i = 1; i < lines.length; i++) {
var lineSize = hdpiCanvas_1.HdpiCanvas.getTextSize(lines[i], font);
width = Math.max(width, lineSize.width);
baselineDistance += lineHeight !== null && lineHeight !== void 0 ? lineHeight : lineSize.height;
}
switch (textAlign) {
case 'end':
case 'right':
x -= width;
break;
case 'center':
x -= width / 2;
}
switch (textBaseline) {
case 'alphabetic':
y -= firstLineHeight * 0.7 + baselineDistance * 0.5;
break;
case 'middle':
y -= firstLineHeight * 0.45 + baselineDistance * 0.5;
break;
case 'ideographic':
y -= firstLineHeight + baselineDistance;
break;
case 'hanging':
y -= firstLineHeight * 0.2 + baselineDistance * 0.5;
break;
case 'bottom':
y -= firstLineHeight + baselineDistance;
break;
}
return new bbox_1.BBox(x, y, width, firstLineHeight + baselineDistance);
}
function getVerticalOffset(textBaseline) {
switch (textBaseline) {
case 'top':
case 'hanging':
return 0;
case 'bottom':
case 'alphabetic':
case 'ideographic':
return 1;
case 'middle':
return 0.5;
}
}
function splitText(text) {
return typeof text === 'string' ? text.split(/\r?\n/g) : [];
}
exports.splitText = splitText;
//# sourceMappingURL=text.js.map