@babylonjs/gui
Version:
Babylon.js GUI module =====================
1,035 lines • 41.2 kB
JavaScript
import { __decorate } from "@babylonjs/core/tslib.es6.js";
import { Observable } from "@babylonjs/core/Misc/observable.js";
import { ClipboardEventTypes } from "@babylonjs/core/Events/clipboardEvents.js";
import { PointerEventTypes } from "@babylonjs/core/Events/pointerEvents.js";
import { Control } from "./control.js";
import { ValueAndUnit } from "../valueAndUnit.js";
import { RegisterClass } from "@babylonjs/core/Misc/typeStore.js";
import { TextWrapper } from "./textWrapper.js";
import { serialize } from "@babylonjs/core/Misc/decorators.js";
/**
* Class used to create input text control
*/
export class InputText extends Control {
/**
* Gets or sets outlineWidth of the text to display
*/
get outlineWidth() {
return this._outlineWidth;
}
set outlineWidth(value) {
if (this._outlineWidth === value) {
return;
}
this._outlineWidth = value;
this._markAsDirty();
}
/**
* Gets or sets outlineColor of the text to display
*/
get outlineColor() {
return this._outlineColor;
}
set outlineColor(value) {
if (this._outlineColor === value) {
return;
}
this._outlineColor = value;
this._markAsDirty();
}
/** Gets or sets the maximum width allowed by the control */
get maxWidth() {
return this._maxWidth.toString(this._host);
}
/** Gets the maximum width allowed by the control in pixels */
get maxWidthInPixels() {
return this._maxWidth.getValueInPixel(this._host, this._cachedParentMeasure.width);
}
set maxWidth(value) {
if (this._maxWidth.toString(this._host) === value) {
return;
}
if (this._maxWidth.fromString(value)) {
this._markAsDirty();
}
}
/** Gets or sets the text highlighter transparency; default: 0.4 */
get highligherOpacity() {
return this._highligherOpacity;
}
set highligherOpacity(value) {
if (this._highligherOpacity === value) {
return;
}
this._highligherOpacity = value;
this._markAsDirty();
}
/** Gets or sets a boolean indicating whether to select complete text by default on input focus */
get onFocusSelectAll() {
return this._onFocusSelectAll;
}
set onFocusSelectAll(value) {
if (this._onFocusSelectAll === value) {
return;
}
this._onFocusSelectAll = value;
this._markAsDirty();
}
/** Gets or sets the text hightlight color */
get textHighlightColor() {
return this._textHighlightColor;
}
set textHighlightColor(value) {
if (this._textHighlightColor === value) {
return;
}
this._textHighlightColor = value;
this._markAsDirty();
}
/** Gets or sets control margin */
get margin() {
return this._margin.toString(this._host);
}
/** Gets control margin in pixels */
get marginInPixels() {
return this._margin.getValueInPixel(this._host, this._cachedParentMeasure.width);
}
set margin(value) {
if (this._margin.toString(this._host) === value) {
return;
}
if (this._margin.fromString(value)) {
this._markAsDirty();
}
}
/** Gets or sets a boolean indicating if the control can auto stretch its width to adapt to the text */
get autoStretchWidth() {
return this._autoStretchWidth;
}
set autoStretchWidth(value) {
if (this._autoStretchWidth === value) {
return;
}
this._autoStretchWidth = value;
this._markAsDirty();
}
/** Gets or sets border thickness */
get thickness() {
return this._thickness;
}
set thickness(value) {
if (this._thickness === value) {
return;
}
this._thickness = value;
this._markAsDirty();
}
/** Gets or sets the background color when focused */
get focusedBackground() {
return this._focusedBackground;
}
set focusedBackground(value) {
if (this._focusedBackground === value) {
return;
}
this._focusedBackground = value;
this._markAsDirty();
}
/** Gets or sets the background color when focused */
set focusedColor(value) {
if (this._focusedColor === value) {
return;
}
this._focusedColor = value;
this._markAsDirty();
}
/** Gets or sets the background color */
get background() {
return this._background;
}
set background(value) {
if (this._background === value) {
return;
}
this._background = value;
this._markAsDirty();
}
/** Gets or sets the placeholder color */
get placeholderColor() {
return this._placeholderColor;
}
set placeholderColor(value) {
if (this._placeholderColor === value) {
return;
}
this._placeholderColor = value;
this._markAsDirty();
}
/** Gets or sets the text displayed when the control is empty */
get placeholderText() {
return this._placeholderText;
}
set placeholderText(value) {
if (this._placeholderText === value) {
return;
}
this._placeholderText = value;
this._markAsDirty();
}
/** Gets or sets the dead key. 0 to disable. */
get deadKey() {
return this._deadKey;
}
set deadKey(flag) {
this._deadKey = flag;
}
/** Gets or sets the highlight text */
get highlightedText() {
return this._highlightedText;
}
set highlightedText(text) {
if (this._highlightedText === text) {
return;
}
this._highlightedText = text;
this._markAsDirty();
}
/** Gets or sets if the current key should be added */
get addKey() {
return this._addKey;
}
set addKey(flag) {
this._addKey = flag;
}
/** Gets or sets the value of the current key being entered */
get currentKey() {
return this._currentKey;
}
set currentKey(key) {
this._currentKey = key;
}
/** Gets or sets the text displayed in the control */
get text() {
return this._textWrapper.text;
}
set text(value) {
const valueAsString = value.toString(); // Forcing convertion
if (!this._textWrapper) {
this._textWrapper = new TextWrapper();
}
if (this._textWrapper.text === valueAsString) {
return;
}
this._textWrapper.text = valueAsString;
this._textHasChanged();
}
_textHasChanged() {
this._markAsDirty();
this.onTextChangedObservable.notifyObservers(this);
}
_applyStates(context) {
super._applyStates(context);
if (this.outlineWidth) {
context.lineWidth = this.outlineWidth;
context.strokeStyle = this.outlineColor;
}
}
/** Gets or sets control width */
get width() {
return this._width.toString(this._host);
}
set width(value) {
if (this._width.toString(this._host) === value && !this._autoStretchWidth) {
return;
}
if (this._width.fromString(value)) {
this._markAsDirty();
}
this.autoStretchWidth = false;
}
/**
* Creates a new InputText
* @param name defines the control name
* @param text defines the text of the control
*/
constructor(name, text = "") {
super(name);
this.name = name;
this._placeholderText = "";
this._background = "#222222";
this._focusedBackground = "#000000";
this._placeholderColor = "gray";
this._thickness = 1;
this._margin = new ValueAndUnit(10, ValueAndUnit.UNITMODE_PIXEL);
this._autoStretchWidth = true;
this._maxWidth = new ValueAndUnit(1, ValueAndUnit.UNITMODE_PERCENTAGE, false);
this._blinkIsEven = false;
this._cursorOffset = 0;
this._deadKey = false;
this._addKey = true;
this._currentKey = "";
this._isTextHighlightOn = false;
this._textHighlightColor = "#d5e0ff";
this._highligherOpacity = 0.4;
this._highlightedText = "";
this._startHighlightIndex = 0;
this._endHighlightIndex = 0;
this._cursorIndex = -1;
this._outlineWidth = 0;
this._outlineColor = "white";
this._onFocusSelectAll = false;
this._isPointerDown = false;
/** Gets or sets a string representing the message displayed on mobile when the control gets the focus */
this.promptMessage = "Please enter text:";
/** Force disable prompt on mobile device */
this.disableMobilePrompt = false;
/** Observable raised when the text changes */
this.onTextChangedObservable = new Observable();
/** Observable raised just before an entered character is to be added */
this.onBeforeKeyAddObservable = new Observable();
/** Observable raised when the text is highlighted */
this.onTextHighlightObservable = new Observable();
/** Observable raised when copy event is triggered */
this.onTextCopyObservable = new Observable();
/** Observable raised when cut event is triggered */
this.onTextCutObservable = new Observable();
/** Observable raised when paste event is triggered */
this.onTextPasteObservable = new Observable();
this.text = text;
this.isPointerBlocker = true;
this._focusedColor = "white";
}
/** @internal */
onBlur() {
this._isFocused = false;
this._scrollLeft = null;
this._cursorOffset = 0;
clearTimeout(this._blinkTimeout);
this._markAsDirty();
this.onBlurObservable.notifyObservers(this);
this._host.unRegisterClipboardEvents();
if (this._onClipboardObserver) {
this._host.onClipboardObservable.remove(this._onClipboardObserver);
}
const scene = this._host.getScene();
if (this._onPointerDblTapObserver && scene) {
scene.onPointerObservable.remove(this._onPointerDblTapObserver);
}
}
/** @internal */
onFocus() {
if (!this._isEnabled) {
return;
}
this._scrollLeft = null;
this._isFocused = true;
this._blinkIsEven = false;
this._cursorOffset = 0;
this._markAsDirty();
this.onFocusObservable.notifyObservers(this);
if (this._focusedBy === "touch" && !this.disableMobilePrompt) {
const value = prompt(this.promptMessage);
if (value !== null) {
this.text = value;
}
this._host.focusedControl = null;
return;
}
this._host.registerClipboardEvents();
this._onClipboardObserver = this._host.onClipboardObservable.add((clipboardInfo) => {
// process clipboard event, can be configured.
switch (clipboardInfo.type) {
case ClipboardEventTypes.COPY:
this._onCopyText(clipboardInfo.event);
this.onTextCopyObservable.notifyObservers(this);
break;
case ClipboardEventTypes.CUT:
this._onCutText(clipboardInfo.event);
this.onTextCutObservable.notifyObservers(this);
break;
case ClipboardEventTypes.PASTE:
this._onPasteText(clipboardInfo.event);
this.onTextPasteObservable.notifyObservers(this);
break;
default:
return;
}
});
const scene = this._host.getScene();
if (scene) {
//register the pointer double tap event
this._onPointerDblTapObserver = scene.onPointerObservable.add((pointerInfo) => {
if (!this._isFocused) {
return;
}
if (pointerInfo.type === PointerEventTypes.POINTERDOUBLETAP) {
this._processDblClick(pointerInfo);
}
});
}
if (this._onFocusSelectAll) {
this.selectAllText();
}
}
_getTypeName() {
return "InputText";
}
/**
* Function called to get the list of controls that should not steal the focus from this control
* @returns an array of controls
*/
keepsFocusWith() {
if (!this._connectedVirtualKeyboard) {
return null;
}
return [this._connectedVirtualKeyboard];
}
/**
* @internal
*/
processKey(keyCode, key, evt) {
if (this.isReadOnly) {
return;
}
//return if clipboard event keys (i.e -ctr/cmd + c,v,x)
if (evt && (evt.ctrlKey || evt.metaKey) && (keyCode === 67 || keyCode === 86 || keyCode === 88)) {
return;
}
//select all
if (evt && (evt.ctrlKey || evt.metaKey) && keyCode === 65) {
this.selectAllText();
evt.preventDefault();
return;
}
// Specific cases
switch (keyCode) {
case 32: //SPACE
key = " "; //ie11 key for space is "Spacebar"
break;
case 191: //SLASH
if (evt) {
evt.preventDefault();
}
break;
case 8: // BACKSPACE
if (this._textWrapper.text && this._textWrapper.length > 0) {
//delete the highlighted text
if (this.isTextHighlightOn) {
this._textWrapper.removePart(this._startHighlightIndex, this._endHighlightIndex);
this._textHasChanged();
this.isTextHighlightOn = false;
this._cursorOffset = this._textWrapper.length - this._startHighlightIndex;
this._blinkIsEven = false;
if (evt) {
evt.preventDefault();
}
return;
}
//delete single character
if (this._cursorOffset === 0) {
this.text = this._textWrapper.substring(0, this._textWrapper.length - 1);
}
else {
const deletePosition = this._textWrapper.length - this._cursorOffset;
if (deletePosition > 0) {
this._textWrapper.removePart(deletePosition - 1, deletePosition);
this._textHasChanged();
}
}
}
if (evt) {
evt.preventDefault();
}
return;
case 46: // DELETE
if (this.isTextHighlightOn) {
this._textWrapper.removePart(this._startHighlightIndex, this._endHighlightIndex);
this._textHasChanged();
this.isTextHighlightOn = false;
this._cursorOffset = this._textWrapper.length - this._startHighlightIndex;
if (evt) {
evt.preventDefault();
}
return;
}
if (this._textWrapper.text && this._textWrapper.length > 0 && this._cursorOffset > 0) {
const deletePosition = this._textWrapper.length - this._cursorOffset;
this._textWrapper.removePart(deletePosition, deletePosition + 1);
this._textHasChanged();
this._cursorOffset--;
}
if (evt) {
evt.preventDefault();
}
return;
case 13: // RETURN
this._host.focusedControl = null;
this.isTextHighlightOn = false;
return;
case 35: // END
this._cursorOffset = 0;
this._blinkIsEven = false;
this.isTextHighlightOn = false;
this._markAsDirty();
return;
case 36: // HOME
this._cursorOffset = this._textWrapper.length;
this._blinkIsEven = false;
this.isTextHighlightOn = false;
this._markAsDirty();
return;
case 37: // LEFT
this._cursorOffset++;
if (this._cursorOffset > this._textWrapper.length) {
this._cursorOffset = this._textWrapper.length;
}
if (evt && evt.shiftKey) {
// update the cursor
this._blinkIsEven = false;
// shift + ctrl/cmd + <-
if (evt.ctrlKey || evt.metaKey) {
if (!this.isTextHighlightOn) {
if (this._textWrapper.length === this._cursorOffset) {
return;
}
else {
this._endHighlightIndex = this._textWrapper.length - this._cursorOffset + 1;
}
}
this._startHighlightIndex = 0;
this._cursorIndex = this._textWrapper.length - this._endHighlightIndex;
this._cursorOffset = this._textWrapper.length;
this.isTextHighlightOn = true;
this._markAsDirty();
return;
}
//store the starting point
if (!this.isTextHighlightOn) {
this.isTextHighlightOn = true;
this._cursorIndex = this._cursorOffset >= this._textWrapper.length ? this._textWrapper.length : this._cursorOffset - 1;
}
//if text is already highlighted
else if (this._cursorIndex === -1) {
this._cursorIndex = this._textWrapper.length - this._endHighlightIndex;
this._cursorOffset = this._startHighlightIndex === 0 ? this._textWrapper.length : this._textWrapper.length - this._startHighlightIndex + 1;
}
//set the highlight indexes
if (this._cursorIndex < this._cursorOffset) {
this._endHighlightIndex = this._textWrapper.length - this._cursorIndex;
this._startHighlightIndex = this._textWrapper.length - this._cursorOffset;
}
else if (this._cursorIndex > this._cursorOffset) {
this._endHighlightIndex = this._textWrapper.length - this._cursorOffset;
this._startHighlightIndex = this._textWrapper.length - this._cursorIndex;
}
else {
this.isTextHighlightOn = false;
}
this._markAsDirty();
return;
}
if (this.isTextHighlightOn) {
this._cursorOffset = this._textWrapper.length - this._startHighlightIndex;
this.isTextHighlightOn = false;
}
if (evt && (evt.ctrlKey || evt.metaKey)) {
this._cursorOffset = this._textWrapper.length;
evt.preventDefault();
}
this._blinkIsEven = false;
this.isTextHighlightOn = false;
this._cursorIndex = -1;
this._markAsDirty();
return;
case 39: // RIGHT
this._cursorOffset--;
if (this._cursorOffset < 0) {
this._cursorOffset = 0;
}
if (evt && evt.shiftKey) {
//update the cursor
this._blinkIsEven = false;
//shift + ctrl/cmd + ->
if (evt.ctrlKey || evt.metaKey) {
if (!this.isTextHighlightOn) {
if (this._cursorOffset === 0) {
return;
}
else {
this._startHighlightIndex = this._textWrapper.length - this._cursorOffset - 1;
}
}
this._endHighlightIndex = this._textWrapper.length;
this.isTextHighlightOn = true;
this._cursorIndex = this._textWrapper.length - this._startHighlightIndex;
this._cursorOffset = 0;
this._markAsDirty();
return;
}
if (!this.isTextHighlightOn) {
this.isTextHighlightOn = true;
this._cursorIndex = this._cursorOffset <= 0 ? 0 : this._cursorOffset + 1;
}
//if text is already highlighted
else if (this._cursorIndex === -1) {
this._cursorIndex = this._textWrapper.length - this._startHighlightIndex;
this._cursorOffset = this._textWrapper.length === this._endHighlightIndex ? 0 : this._textWrapper.length - this._endHighlightIndex - 1;
}
//set the highlight indexes
if (this._cursorIndex < this._cursorOffset) {
this._endHighlightIndex = this._textWrapper.length - this._cursorIndex;
this._startHighlightIndex = this._textWrapper.length - this._cursorOffset;
}
else if (this._cursorIndex > this._cursorOffset) {
this._endHighlightIndex = this._textWrapper.length - this._cursorOffset;
this._startHighlightIndex = this._textWrapper.length - this._cursorIndex;
}
else {
this.isTextHighlightOn = false;
}
this._markAsDirty();
return;
}
if (this.isTextHighlightOn) {
this._cursorOffset = this._textWrapper.length - this._endHighlightIndex;
this.isTextHighlightOn = false;
}
//ctr + ->
if (evt && (evt.ctrlKey || evt.metaKey)) {
this._cursorOffset = 0;
evt.preventDefault();
}
this._blinkIsEven = false;
this.isTextHighlightOn = false;
this._cursorIndex = -1;
this._markAsDirty();
return;
}
if (keyCode === 32) {
key = evt?.key ?? " ";
}
this._deadKey = key === "Dead";
// Printable characters
if (key &&
(keyCode === -1 || // Direct access
keyCode === 32 || // Space
keyCode === 34 || // " add support for single and double quotes
keyCode === 39 || // '
(keyCode > 47 && keyCode < 64) || // Numbers
(keyCode > 64 && keyCode < 91) || // Letters
(keyCode > 159 && keyCode < 193) || // Special characters
(keyCode > 218 && keyCode < 223) || // Special characters
(keyCode > 95 && keyCode < 112))) {
// Numpad
this._currentKey = key;
this.onBeforeKeyAddObservable.notifyObservers(this);
key = this._currentKey;
if (this._addKey && !this._deadKey) {
if (this.isTextHighlightOn) {
this._textWrapper.removePart(this._startHighlightIndex, this._endHighlightIndex, key);
this._textHasChanged();
this._cursorOffset = this._textWrapper.length - (this._startHighlightIndex + 1);
this.isTextHighlightOn = false;
this._blinkIsEven = false;
this._markAsDirty();
}
else if (this._cursorOffset === 0) {
this.text += this._deadKey && evt?.key ? evt.key : key;
}
else {
const insertPosition = this._textWrapper.length - this._cursorOffset;
this._textWrapper.removePart(insertPosition, insertPosition, key);
this._textHasChanged();
}
}
}
}
/**
* @internal
*/
_updateValueFromCursorIndex(offset) {
//update the cursor
this._blinkIsEven = false;
if (this._cursorIndex === -1) {
this._cursorIndex = offset;
}
else {
if (this._cursorIndex < this._cursorOffset) {
this._endHighlightIndex = this._textWrapper.length - this._cursorIndex;
this._startHighlightIndex = this._textWrapper.length - this._cursorOffset;
}
else if (this._cursorIndex > this._cursorOffset) {
this._endHighlightIndex = this._textWrapper.length - this._cursorOffset;
this._startHighlightIndex = this._textWrapper.length - this._cursorIndex;
}
else {
this.isTextHighlightOn = false;
this._markAsDirty();
return;
}
}
this.isTextHighlightOn = true;
this._markAsDirty();
}
/**
* @internal
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_processDblClick(evt) {
//pre-find the start and end index of the word under cursor, speeds up the rendering
this._startHighlightIndex = this._textWrapper.length - this._cursorOffset;
this._endHighlightIndex = this._startHighlightIndex;
let moveLeft, moveRight;
do {
moveRight = this._endHighlightIndex < this._textWrapper.length && this._textWrapper.isWord(this._endHighlightIndex) ? ++this._endHighlightIndex : 0;
moveLeft = this._startHighlightIndex > 0 && this._textWrapper.isWord(this._startHighlightIndex - 1) ? --this._startHighlightIndex : 0;
} while (moveLeft || moveRight);
this._cursorOffset = this._textWrapper.length - this._startHighlightIndex;
this.isTextHighlightOn = true;
this._clickedCoordinate = null;
this._blinkIsEven = true;
this._cursorIndex = -1;
this._markAsDirty();
}
/**
* Allow the user to select all text
*/
selectAllText() {
this._blinkIsEven = true;
this.isTextHighlightOn = true;
this._startHighlightIndex = 0;
this._endHighlightIndex = this._textWrapper.length;
this._cursorOffset = this._textWrapper.length;
this._cursorIndex = -1;
this._markAsDirty();
}
/**
* Handles the keyboard event
* @param evt Defines the KeyboardEvent
*/
processKeyboard(evt) {
// process pressed key
this.processKey(evt.keyCode, evt.key, evt);
super.processKeyboard(evt);
}
/**
* @internal
*/
_onCopyText(ev) {
this.isTextHighlightOn = false;
//when write permission to clipbaord data is denied
try {
ev.clipboardData && ev.clipboardData.setData("text/plain", this._highlightedText);
}
catch { } //pass
this._host.clipboardData = this._highlightedText;
}
/**
* @internal
*/
_onCutText(ev) {
if (!this._highlightedText) {
return;
}
this._textWrapper.removePart(this._startHighlightIndex, this._endHighlightIndex);
this._textHasChanged();
this.isTextHighlightOn = false;
this._cursorOffset = this._textWrapper.length - this._startHighlightIndex;
//when write permission to clipbaord data is denied
try {
ev.clipboardData && ev.clipboardData.setData("text/plain", this._highlightedText);
}
catch { } //pass
this._host.clipboardData = this._highlightedText;
this._highlightedText = "";
}
/**
* @internal
*/
_onPasteText(ev) {
let data = "";
if (ev.clipboardData && ev.clipboardData.types.indexOf("text/plain") !== -1) {
data = ev.clipboardData.getData("text/plain");
}
else {
//get the cached data; returns blank string by default
data = this._host.clipboardData;
}
const insertPosition = this._textWrapper.length - this._cursorOffset;
this._textWrapper.removePart(insertPosition, insertPosition, data);
this._textHasChanged();
}
_draw(context) {
context.save();
this._applyStates(context);
if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
context.shadowColor = this.shadowColor;
context.shadowBlur = this.shadowBlur;
context.shadowOffsetX = this.shadowOffsetX;
context.shadowOffsetY = this.shadowOffsetY;
}
// Background
if (this._isFocused) {
if (this._focusedBackground) {
context.fillStyle = this._isEnabled ? this._focusedBackground : this._disabledColor;
context.fillRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
}
}
else if (this._background) {
context.fillStyle = this._isEnabled ? this._background : this._disabledColor;
context.fillRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
}
if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
context.shadowBlur = 0;
context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
}
if (!this._fontOffset || this._wasDirty) {
this._fontOffset = Control._GetFontOffset(context.font, this._host.getScene()?.getEngine());
}
// Text
const clipTextLeft = this._currentMeasure.left + this._margin.getValueInPixel(this._host, this._tempParentMeasure.width);
if (this.color) {
context.fillStyle = this.color;
}
let text = this._beforeRenderText(this._textWrapper);
if (!this._isFocused && !this._textWrapper.text && this._placeholderText) {
text = new TextWrapper();
text.text = this._placeholderText;
if (this._placeholderColor) {
context.fillStyle = this._placeholderColor;
}
}
this._textWidth = context.measureText(text.text).width;
const marginWidth = this._margin.getValueInPixel(this._host, this._tempParentMeasure.width) * 2;
if (this._autoStretchWidth) {
this.width = Math.min(this._maxWidth.getValueInPixel(this._host, this._tempParentMeasure.width), this._textWidth + marginWidth) + "px";
this._autoStretchWidth = true; // setting the width will have reset _autoStretchWidth to false!
}
const rootY = this._fontOffset.ascent + (this._currentMeasure.height - this._fontOffset.height) / 2;
const availableWidth = this._width.getValueInPixel(this._host, this._tempParentMeasure.width) - marginWidth;
context.save();
context.beginPath();
context.rect(clipTextLeft, this._currentMeasure.top + (this._currentMeasure.height - this._fontOffset.height) / 2, availableWidth + 2, this._currentMeasure.height);
context.clip();
if (this._isFocused && this._textWidth > availableWidth) {
const textLeft = clipTextLeft - this._textWidth + availableWidth;
if (!this._scrollLeft) {
this._scrollLeft = textLeft;
}
}
else {
this._scrollLeft = clipTextLeft;
}
if (this.outlineWidth) {
context.strokeText(text.text, this._scrollLeft, this._currentMeasure.top + rootY);
}
context.fillText(text.text, this._scrollLeft, this._currentMeasure.top + rootY);
// Cursor
if (this._isFocused) {
// Need to move cursor
if (this._clickedCoordinate) {
const rightPosition = this._scrollLeft + this._textWidth;
const absoluteCursorPosition = rightPosition - this._clickedCoordinate;
let currentSize = 0;
this._cursorOffset = 0;
let previousDist = 0;
do {
if (this._cursorOffset) {
previousDist = Math.abs(absoluteCursorPosition - currentSize);
}
this._cursorOffset++;
currentSize = context.measureText(text.substr(text.length - this._cursorOffset, this._cursorOffset)).width;
} while (currentSize < absoluteCursorPosition && text.length >= this._cursorOffset);
// Find closest move
if (Math.abs(absoluteCursorPosition - currentSize) > previousDist) {
this._cursorOffset--;
}
this._blinkIsEven = false;
this._clickedCoordinate = null;
}
// Render cursor
if (!this._blinkIsEven) {
const cursorOffsetText = text.substr(text.length - this._cursorOffset);
const cursorOffsetWidth = context.measureText(cursorOffsetText).width;
let cursorLeft = this._scrollLeft + this._textWidth - cursorOffsetWidth;
if (cursorLeft < clipTextLeft) {
this._scrollLeft += clipTextLeft - cursorLeft;
cursorLeft = clipTextLeft;
this._markAsDirty();
}
else if (cursorLeft > clipTextLeft + availableWidth) {
this._scrollLeft += clipTextLeft + availableWidth - cursorLeft;
cursorLeft = clipTextLeft + availableWidth;
this._markAsDirty();
}
if (!this.isTextHighlightOn) {
context.fillRect(cursorLeft, this._currentMeasure.top + (this._currentMeasure.height - this._fontOffset.height) / 2, 2, this._fontOffset.height);
}
}
clearTimeout(this._blinkTimeout);
this._blinkTimeout = setTimeout(() => {
this._blinkIsEven = !this._blinkIsEven;
this._markAsDirty();
}, 500);
//show the highlighted text
if (this.isTextHighlightOn) {
clearTimeout(this._blinkTimeout);
const highlightCursorOffsetWidth = context.measureText(text.substring(this._startHighlightIndex)).width;
let highlightCursorLeft = this._scrollLeft + this._textWidth - highlightCursorOffsetWidth;
this._highlightedText = text.substring(this._startHighlightIndex, this._endHighlightIndex);
let width = context.measureText(text.substring(this._startHighlightIndex, this._endHighlightIndex)).width;
if (highlightCursorLeft < clipTextLeft) {
width = width - (clipTextLeft - highlightCursorLeft);
if (!width) {
// when using left arrow on text.length > availableWidth;
// assigns the width of the first letter after clipTextLeft
width = context.measureText(text.charAt(text.length - this._cursorOffset)).width;
}
highlightCursorLeft = clipTextLeft;
}
//for transparancy
context.globalAlpha = this._highligherOpacity;
context.fillStyle = this._textHighlightColor;
context.fillRect(highlightCursorLeft, this._currentMeasure.top + (this._currentMeasure.height - this._fontOffset.height) / 2, width, this._fontOffset.height);
context.globalAlpha = 1.0;
}
}
context.restore();
// Border
if (this._thickness) {
if (this._isFocused) {
if (this.focusedColor) {
context.strokeStyle = this.focusedColor;
}
}
else {
if (this.color) {
context.strokeStyle = this.color;
}
}
context.lineWidth = this._thickness;
context.strokeRect(this._currentMeasure.left + this._thickness / 2, this._currentMeasure.top + this._thickness / 2, this._currentMeasure.width - this._thickness, this._currentMeasure.height - this._thickness);
}
context.restore();
}
_onPointerDown(target, coordinates, pointerId, buttonIndex, pi) {
if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex, pi)) {
return false;
}
if (this.isReadOnly) {
return true;
}
this._clickedCoordinate = coordinates.x;
this.isTextHighlightOn = false;
this._highlightedText = "";
this._cursorIndex = -1;
this._isPointerDown = true;
this._host._capturingControl[pointerId] = this;
this._focusedBy = pi.event.pointerType;
if (this._host.focusedControl === this) {
// Move cursor
clearTimeout(this._blinkTimeout);
this._markAsDirty();
return true;
}
if (!this._isEnabled) {
return false;
}
this._host.focusedControl = this;
return true;
}
_onPointerMove(target, coordinates, pointerId, pi) {
if (this._host.focusedControl === this && this._isPointerDown && !this.isReadOnly) {
this._clickedCoordinate = coordinates.x;
this._markAsDirty();
this._updateValueFromCursorIndex(this._cursorOffset);
}
super._onPointerMove(target, coordinates, pointerId, pi);
}
_onPointerUp(target, coordinates, pointerId, buttonIndex, notifyClick) {
this._isPointerDown = false;
delete this._host._capturingControl[pointerId];
super._onPointerUp(target, coordinates, pointerId, buttonIndex, notifyClick);
}
_beforeRenderText(textWrapper) {
return textWrapper;
}
/** @internal */
// eslint-disable-next-line @typescript-eslint/naming-convention
set isTextHighlightOn(value) {
if (this._isTextHighlightOn === value) {
return;
}
if (value) {
this.onTextHighlightObservable.notifyObservers(this);
}
this._isTextHighlightOn = value;
}
/** @internal */
// eslint-disable-next-line @typescript-eslint/naming-convention
get isTextHighlightOn() {
return this._isTextHighlightOn;
}
dispose() {
super.dispose();
this.onBlurObservable.clear();
this.onFocusObservable.clear();
this.onTextChangedObservable.clear();
this.onTextCopyObservable.clear();
this.onTextCutObservable.clear();
this.onTextPasteObservable.clear();
this.onTextHighlightObservable.clear();
this.onKeyboardEventProcessedObservable.clear();
}
}
__decorate([
serialize()
], InputText.prototype, "promptMessage", void 0);
__decorate([
serialize()
], InputText.prototype, "disableMobilePrompt", void 0);
__decorate([
serialize()
], InputText.prototype, "maxWidth", null);
__decorate([
serialize()
], InputText.prototype, "highligherOpacity", null);
__decorate([
serialize()
], InputText.prototype, "onFocusSelectAll", null);
__decorate([
serialize()
], InputText.prototype, "textHighlightColor", null);
__decorate([
serialize()
], InputText.prototype, "margin", null);
__decorate([
serialize()
], InputText.prototype, "autoStretchWidth", null);
__decorate([
serialize()
], InputText.prototype, "thickness", null);
__decorate([
serialize()
], InputText.prototype, "focusedBackground", null);
__decorate([
serialize()
], InputText.prototype, "background", null);
__decorate([
serialize()
], InputText.prototype, "placeholderColor", null);
__decorate([
serialize()
], InputText.prototype, "placeholderText", null);
__decorate([
serialize()
], InputText.prototype, "deadKey", null);
__decorate([
serialize()
], InputText.prototype, "text", null);
__decorate([
serialize()
], InputText.prototype, "width", null);
RegisterClass("BABYLON.GUI.InputText", InputText);
//# sourceMappingURL=inputText.js.map