/// module BABYLON.GUI { export class TextBlock extends Control { private _text = ""; private _textY: number; private _textWrapping = false; private _textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER; private _textVerticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER; private _lines: any[]; private _totalHeight: number; private _resizeToFit: boolean = false; /** * An event triggered after the text is changed * @type {BABYLON.Observable} */ public onTextChangedObservable = new Observable(); get resizeToFit(): boolean { return this._resizeToFit; } set resizeToFit(value: boolean) { this._resizeToFit = value; if (this._resizeToFit) { this._width.ignoreAdaptiveScaling = true; this._height.ignoreAdaptiveScaling = true; } } public get textWrapping(): boolean { return this._textWrapping; } public set textWrapping(value: boolean) { if (this._textWrapping === value) { return; } this._textWrapping = value; this._markAsDirty(); } public get text(): string { return this._text; } public set text(value: string) { if (this._text === value) { return; } this._text = value; this._markAsDirty(); this.onTextChangedObservable.notifyObservers(this); } public get textHorizontalAlignment(): number { return this._textHorizontalAlignment; } public set textHorizontalAlignment(value: number) { if (this._textHorizontalAlignment === value) { return; } this._textHorizontalAlignment = value; this._markAsDirty(); } public get textVerticalAlignment(): number { return this._textVerticalAlignment; } public set textVerticalAlignment(value: number) { if (this._textVerticalAlignment === value) { return; } this._textVerticalAlignment = value; this._markAsDirty(); } constructor(public name?: string, text: string = "") { super(name); this.text = text; } protected _getTypeName(): string { return "TextBlock"; } private _drawText(text: string, textWidth: number, y: number, context: CanvasRenderingContext2D): void { var width = this._currentMeasure.width; var x = 0; switch (this._textHorizontalAlignment) { case Control.HORIZONTAL_ALIGNMENT_LEFT: x = 0 break; case Control.HORIZONTAL_ALIGNMENT_RIGHT: x = width - textWidth; break; case Control.HORIZONTAL_ALIGNMENT_CENTER: x = (width - textWidth) / 2; break; } context.fillText(text, this._currentMeasure.left + x, y); } public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void { context.save(); this._applyStates(context); if (this._processMeasures(parentMeasure, context)) { // Render lines this._renderLines(context); } context.restore(); } protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void { this._lines = []; var _lines = this.text.split("\n"); if (this._textWrapping && !this._resizeToFit) { for(var _line of _lines) { this._lines.push(this._parseLineWithTextWrapping(_line, context)); } } else { for(var _line of _lines) { this._lines.push(this._parseLine(_line, context)); } } } protected _parseLine(line: string='', context: CanvasRenderingContext2D): object { return {text: line, width: context.measureText(line).width}; } protected _parseLineWithTextWrapping(line: string='', context: CanvasRenderingContext2D): object { var words = line.split(' '); var width = this._currentMeasure.width; var lineWidth = 0; for(var n = 0; n < words.length; n++) { var testLine = n > 0 ? line + " " + words[n] : words[0]; var metrics = context.measureText(testLine); var testWidth = metrics.width; if (testWidth > width && n > 0) { this._lines.push({text: line, width: lineWidth}); line = words[n]; lineWidth = context.measureText(line).width; } else { lineWidth = testWidth; line = testLine; } } return {text: line, width: lineWidth}; } protected _renderLines(context: CanvasRenderingContext2D): void { var width = this._currentMeasure.width; var height = this._currentMeasure.height; if (!this._fontOffset) { this._fontOffset = Control._GetFontOffset(context.font); } var rootY = 0; switch (this._textVerticalAlignment) { case Control.VERTICAL_ALIGNMENT_TOP: rootY = this._fontOffset.ascent; break; case Control.VERTICAL_ALIGNMENT_BOTTOM: rootY = height - this._fontOffset.height * (this._lines.length - 1) - this._fontOffset.descent; break; case Control.VERTICAL_ALIGNMENT_CENTER: rootY = this._fontOffset.ascent + (height - this._fontOffset.height * this._lines.length) / 2; break; } rootY += this._currentMeasure.top; var maxLineWidth: number = 0; for (var line of this._lines) { this._drawText(line.text, line.width, rootY, context); rootY += this._fontOffset.height; if (line.width > maxLineWidth) maxLineWidth = line.width; } if (this._resizeToFit) { this.width = this.paddingLeftInPixels + this.paddingRightInPixels + maxLineWidth + 'px'; this.height = this.paddingTopInPixels + this.paddingBottomInPixels + this._fontOffset.height * this._lines.length + 'px'; } } dispose(): void { super.dispose(); this.onTextChangedObservable.clear(); } } }