@babylonjs/gui 9.15.0 → 9.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/2D/controls/checkbox.pure.js +164 -153
- package/2D/controls/checkbox.pure.js.map +1 -1
- package/2D/controls/colorpicker.pure.js +1300 -1289
- package/2D/controls/colorpicker.pure.js.map +1 -1
- package/2D/controls/container.pure.js +597 -582
- package/2D/controls/container.pure.js.map +1 -1
- package/2D/controls/control.pure.js +2474 -2434
- package/2D/controls/control.pure.js.map +1 -1
- package/2D/controls/displayGrid.pure.js +201 -190
- package/2D/controls/displayGrid.pure.js.map +1 -1
- package/2D/controls/ellipse.pure.js +96 -85
- package/2D/controls/ellipse.pure.js.map +1 -1
- package/2D/controls/grid.pure.js +511 -500
- package/2D/controls/grid.pure.js.map +1 -1
- package/2D/controls/image.pure.js +888 -877
- package/2D/controls/image.pure.js.map +1 -1
- package/2D/controls/inputText.pure.js +988 -973
- package/2D/controls/inputText.pure.js.map +1 -1
- package/2D/controls/inputTextArea.pure.js +955 -944
- package/2D/controls/inputTextArea.pure.js.map +1 -1
- package/2D/controls/line.pure.js +237 -226
- package/2D/controls/line.pure.js.map +1 -1
- package/2D/controls/multiLine.pure.js +233 -222
- package/2D/controls/multiLine.pure.js.map +1 -1
- package/2D/controls/radioButton.pure.js +182 -169
- package/2D/controls/radioButton.pure.js.map +1 -1
- package/2D/controls/rectangle.pure.js +211 -200
- package/2D/controls/rectangle.pure.js.map +1 -1
- package/2D/controls/scrollViewers/scrollViewer.pure.js +579 -567
- package/2D/controls/scrollViewers/scrollViewer.pure.js.map +1 -1
- package/2D/controls/sliders/baseSlider.js +291 -280
- package/2D/controls/sliders/baseSlider.js.map +1 -1
- package/2D/controls/sliders/imageBasedSlider.pure.js +158 -147
- package/2D/controls/sliders/imageBasedSlider.pure.js.map +1 -1
- package/2D/controls/sliders/imageScrollBar.js +237 -223
- package/2D/controls/sliders/imageScrollBar.js.map +1 -1
- package/2D/controls/sliders/scrollBar.pure.js +169 -158
- package/2D/controls/sliders/scrollBar.pure.js.map +1 -1
- package/2D/controls/sliders/slider.pure.js +251 -240
- package/2D/controls/sliders/slider.pure.js.map +1 -1
- package/2D/controls/stackPanel.pure.js +236 -221
- package/2D/controls/stackPanel.pure.js.map +1 -1
- package/2D/controls/textBlock.pure.js +637 -626
- package/2D/controls/textBlock.pure.js.map +1 -1
- package/3D/materials/fluent/fluentMaterial.pure.d.ts +4 -4
- package/3D/materials/fluent/fluentMaterial.pure.js +322 -273
- package/3D/materials/fluent/fluentMaterial.pure.js.map +1 -1
- package/3D/materials/fluentBackplate/fluentBackplateMaterial.pure.js +510 -454
- package/3D/materials/fluentBackplate/fluentBackplateMaterial.pure.js.map +1 -1
- package/3D/materials/fluentButton/fluentButtonMaterial.pure.js +612 -529
- package/3D/materials/fluentButton/fluentButtonMaterial.pure.js.map +1 -1
- package/3D/materials/mrdl/mrdlBackglowMaterial.pure.js +313 -274
- package/3D/materials/mrdl/mrdlBackglowMaterial.pure.js.map +1 -1
- package/3D/materials/mrdl/mrdlBackplateMaterial.pure.js +462 -405
- package/3D/materials/mrdl/mrdlBackplateMaterial.pure.js.map +1 -1
- package/3D/materials/mrdl/mrdlFrontplateMaterial.pure.js +583 -501
- package/3D/materials/mrdl/mrdlFrontplateMaterial.pure.js.map +1 -1
- package/3D/materials/mrdl/mrdlInnerquadMaterial.pure.js +226 -203
- package/3D/materials/mrdl/mrdlInnerquadMaterial.pure.js.map +1 -1
- package/3D/materials/mrdl/mrdlSliderBarMaterial.pure.js +961 -825
- package/3D/materials/mrdl/mrdlSliderBarMaterial.pure.js.map +1 -1
- package/3D/materials/mrdl/mrdlSliderThumbMaterial.pure.js +961 -825
- package/3D/materials/mrdl/mrdlSliderThumbMaterial.pure.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { __esDecorate, __runInitializers } from "@babylonjs/core/tslib.es6.js";
|
|
2
2
|
import { Observable } from "@babylonjs/core/Misc/observable.js";
|
|
3
3
|
import { Control } from "./control.pure.js";
|
|
4
4
|
import { ValueAndUnit } from "../valueAndUnit.js";
|
|
@@ -8,1020 +8,1031 @@ import { serialize } from "@babylonjs/core/Misc/decorators.js";
|
|
|
8
8
|
/**
|
|
9
9
|
* Class used to create input text control
|
|
10
10
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (this._height.toString(this._host) === value) {
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
if (this._height.fromString(value)) {
|
|
29
|
-
this._markAsDirty();
|
|
30
|
-
}
|
|
31
|
-
this._autoStretchHeight = false;
|
|
32
|
-
}
|
|
33
|
-
get maxHeight() {
|
|
34
|
-
return this._maxHeight.toString(this._host);
|
|
35
|
-
}
|
|
36
|
-
/** Gets the maximum width allowed by the control in pixels */
|
|
37
|
-
get maxHeightInPixels() {
|
|
38
|
-
return this._maxHeight.getValueInPixel(this._host, this._cachedParentMeasure.height);
|
|
39
|
-
}
|
|
40
|
-
set maxHeight(value) {
|
|
41
|
-
if (this._maxHeight.toString(this._host) === value) {
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
if (this._maxHeight.fromString(value)) {
|
|
45
|
-
this._markAsDirty();
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Creates a new InputTextArea
|
|
50
|
-
* @param name defines the control name
|
|
51
|
-
* @param text defines the text of the control
|
|
52
|
-
*/
|
|
53
|
-
constructor(name, text = "") {
|
|
54
|
-
super(name);
|
|
55
|
-
this.name = name;
|
|
56
|
-
this._textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
|
|
57
|
-
this._textVerticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
|
|
58
|
-
this._prevText = this.text;
|
|
59
|
-
this._lineSpacing = new ValueAndUnit(0);
|
|
60
|
-
this._maxHeight = new ValueAndUnit(1, ValueAndUnit.UNITMODE_PERCENTAGE, false);
|
|
61
|
-
/**
|
|
62
|
-
* An event triggered after the text was broken up into lines
|
|
63
|
-
*/
|
|
64
|
-
this.onLinesReadyObservable = new Observable();
|
|
65
|
-
this.text = text;
|
|
66
|
-
this.isPointerBlocker = true;
|
|
67
|
-
this.onLinesReadyObservable.add(() => this._updateCursorPosition());
|
|
68
|
-
this._highlightCursorInfo = {
|
|
69
|
-
initialStartIndex: -1,
|
|
70
|
-
initialRelativeStartIndex: -1,
|
|
71
|
-
initialLineIndex: -1,
|
|
72
|
-
};
|
|
73
|
-
this._cursorInfo = {
|
|
74
|
-
globalStartIndex: 0,
|
|
75
|
-
globalEndIndex: 0,
|
|
76
|
-
relativeEndIndex: 0,
|
|
77
|
-
relativeStartIndex: 0,
|
|
78
|
-
currentLineIndex: 0,
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
_getTypeName() {
|
|
82
|
-
return "InputTextArea";
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Handles the keyboard event
|
|
86
|
-
* @param evt Defines the KeyboardEvent
|
|
87
|
-
*/
|
|
88
|
-
processKeyboard(evt) {
|
|
89
|
-
if (this.isReadOnly) {
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
// process pressed key
|
|
93
|
-
this.alternativeProcessKey(evt.code, evt.key, evt);
|
|
94
|
-
this.onKeyboardEventProcessedObservable.notifyObservers(evt);
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Process the last keyboard input
|
|
98
|
-
*
|
|
99
|
-
* @param code The ascii input number
|
|
100
|
-
* @param key The key string representation
|
|
101
|
-
* @param evt The keyboard event emits with input
|
|
102
|
-
* @internal
|
|
103
|
-
*/
|
|
104
|
-
alternativeProcessKey(code, key, evt) {
|
|
105
|
-
//return if clipboard event keys (i.e -ctr/cmd + c,v,x)
|
|
106
|
-
if (evt && (evt.ctrlKey || evt.metaKey) && (key === "c" || key === "v" || key === "x")) {
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
// Specific cases
|
|
110
|
-
switch (code) {
|
|
111
|
-
case "Period": //SLASH
|
|
112
|
-
if (evt && evt.shiftKey) {
|
|
113
|
-
evt.preventDefault();
|
|
114
|
-
}
|
|
115
|
-
break;
|
|
116
|
-
case "Backspace": // BACKSPACE
|
|
117
|
-
if (!this._isTextHighlightOn && this._cursorInfo.globalStartIndex > 0) {
|
|
118
|
-
this._cursorInfo.globalEndIndex = this._cursorInfo.globalStartIndex;
|
|
119
|
-
this._cursorInfo.globalStartIndex--;
|
|
120
|
-
}
|
|
121
|
-
this._prevText = this._textWrapper.text;
|
|
122
|
-
this._textWrapper.removePart(this._cursorInfo.globalStartIndex, this._cursorInfo.globalEndIndex);
|
|
123
|
-
this._cursorInfo.globalEndIndex = this._cursorInfo.globalStartIndex;
|
|
124
|
-
if (evt) {
|
|
125
|
-
evt.preventDefault();
|
|
11
|
+
let InputTextArea = (() => {
|
|
12
|
+
var _a;
|
|
13
|
+
let _classSuper = InputText;
|
|
14
|
+
let _instanceExtraInitializers = [];
|
|
15
|
+
let _get_autoStretchHeight_decorators;
|
|
16
|
+
let _get_maxHeight_decorators;
|
|
17
|
+
return _a = class InputTextArea extends _classSuper {
|
|
18
|
+
/** Gets or sets a boolean indicating if the control can auto stretch its height to adapt to the text */
|
|
19
|
+
get autoStretchHeight() {
|
|
20
|
+
return this._autoStretchHeight;
|
|
21
|
+
}
|
|
22
|
+
set autoStretchHeight(value) {
|
|
23
|
+
if (this._autoStretchHeight === value) {
|
|
24
|
+
return;
|
|
126
25
|
}
|
|
127
|
-
this.
|
|
128
|
-
this.
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
if (
|
|
133
|
-
|
|
26
|
+
this._autoStretchHeight = value;
|
|
27
|
+
this._markAsDirty();
|
|
28
|
+
}
|
|
29
|
+
set height(value) {
|
|
30
|
+
this.fixedRatioMasterIsWidth = false;
|
|
31
|
+
if (this._height.toString(this._host) === value) {
|
|
32
|
+
return;
|
|
134
33
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
this._cursorInfo.globalEndIndex = this._cursorInfo.globalStartIndex;
|
|
138
|
-
if (evt) {
|
|
139
|
-
evt.preventDefault();
|
|
34
|
+
if (this._height.fromString(value)) {
|
|
35
|
+
this._markAsDirty();
|
|
140
36
|
}
|
|
141
|
-
this.
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
this.
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
this.
|
|
152
|
-
this._isTextHighlightOn = false;
|
|
153
|
-
this._textHasChanged();
|
|
154
|
-
return;
|
|
155
|
-
case "End": // END
|
|
156
|
-
this._cursorInfo.globalStartIndex = this.text.length;
|
|
157
|
-
this._blinkIsEven = false;
|
|
158
|
-
this._isTextHighlightOn = false;
|
|
159
|
-
this._markAsDirty();
|
|
160
|
-
return;
|
|
161
|
-
case "Home": // HOME
|
|
162
|
-
this._cursorInfo.globalStartIndex = 0;
|
|
163
|
-
this._blinkIsEven = false;
|
|
164
|
-
this._isTextHighlightOn = false;
|
|
165
|
-
this._markAsDirty();
|
|
166
|
-
return;
|
|
167
|
-
case "ArrowLeft": // LEFT
|
|
168
|
-
this._markAsDirty();
|
|
169
|
-
if (evt && evt.shiftKey) {
|
|
170
|
-
// shift + ctrl/cmd + <-
|
|
171
|
-
if (evt.ctrlKey || evt.metaKey) {
|
|
172
|
-
// Go to line's start by substract the relativeStartIndex to the globalStartIndex
|
|
173
|
-
this._cursorInfo.globalStartIndex -= this._cursorInfo.relativeStartIndex;
|
|
174
|
-
this._cursorInfo.globalEndIndex = this._highlightCursorInfo.initialStartIndex;
|
|
175
|
-
}
|
|
176
|
-
// store the starting point
|
|
177
|
-
if (!this._isTextHighlightOn) {
|
|
178
|
-
this._highlightCursorInfo.initialLineIndex = this._cursorInfo.currentLineIndex;
|
|
179
|
-
this._highlightCursorInfo.initialStartIndex = this._cursorInfo.globalStartIndex;
|
|
180
|
-
this._highlightCursorInfo.initialRelativeStartIndex = this._cursorInfo.relativeStartIndex;
|
|
181
|
-
this._cursorInfo.globalEndIndex = this._cursorInfo.globalStartIndex;
|
|
182
|
-
this._cursorInfo.globalStartIndex--;
|
|
183
|
-
this._isTextHighlightOn = true;
|
|
184
|
-
}
|
|
185
|
-
else {
|
|
186
|
-
if (this._cursorInfo.globalEndIndex > this._highlightCursorInfo.initialStartIndex) {
|
|
187
|
-
this._cursorInfo.globalEndIndex--;
|
|
188
|
-
}
|
|
189
|
-
else {
|
|
190
|
-
this._cursorInfo.globalStartIndex--;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
this._blinkIsEven = true;
|
|
194
|
-
evt.preventDefault();
|
|
37
|
+
this._autoStretchHeight = false;
|
|
38
|
+
}
|
|
39
|
+
get maxHeight() {
|
|
40
|
+
return this._maxHeight.toString(this._host);
|
|
41
|
+
}
|
|
42
|
+
/** Gets the maximum width allowed by the control in pixels */
|
|
43
|
+
get maxHeightInPixels() {
|
|
44
|
+
return this._maxHeight.getValueInPixel(this._host, this._cachedParentMeasure.height);
|
|
45
|
+
}
|
|
46
|
+
set maxHeight(value) {
|
|
47
|
+
if (this._maxHeight.toString(this._host) === value) {
|
|
195
48
|
return;
|
|
196
49
|
}
|
|
197
|
-
if (this.
|
|
198
|
-
this.
|
|
50
|
+
if (this._maxHeight.fromString(value)) {
|
|
51
|
+
this._markAsDirty();
|
|
199
52
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Creates a new InputTextArea
|
|
56
|
+
* @param name defines the control name
|
|
57
|
+
* @param text defines the text of the control
|
|
58
|
+
*/
|
|
59
|
+
constructor(name, text = "") {
|
|
60
|
+
super(name);
|
|
61
|
+
this.name = (__runInitializers(this, _instanceExtraInitializers), name);
|
|
62
|
+
this._textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
|
|
63
|
+
this._textVerticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
|
|
64
|
+
this._prevText = this.text;
|
|
65
|
+
this._lineSpacing = new ValueAndUnit(0);
|
|
66
|
+
this._maxHeight = new ValueAndUnit(1, ValueAndUnit.UNITMODE_PERCENTAGE, false);
|
|
67
|
+
/**
|
|
68
|
+
* An event triggered after the text was broken up into lines
|
|
69
|
+
*/
|
|
70
|
+
this.onLinesReadyObservable = new Observable();
|
|
71
|
+
this.text = text;
|
|
72
|
+
this.isPointerBlocker = true;
|
|
73
|
+
this.onLinesReadyObservable.add(() => this._updateCursorPosition());
|
|
74
|
+
this._highlightCursorInfo = {
|
|
75
|
+
initialStartIndex: -1,
|
|
76
|
+
initialRelativeStartIndex: -1,
|
|
77
|
+
initialLineIndex: -1,
|
|
78
|
+
};
|
|
79
|
+
this._cursorInfo = {
|
|
80
|
+
globalStartIndex: 0,
|
|
81
|
+
globalEndIndex: 0,
|
|
82
|
+
relativeEndIndex: 0,
|
|
83
|
+
relativeStartIndex: 0,
|
|
84
|
+
currentLineIndex: 0,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
_getTypeName() {
|
|
88
|
+
return "InputTextArea";
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Handles the keyboard event
|
|
92
|
+
* @param evt Defines the KeyboardEvent
|
|
93
|
+
*/
|
|
94
|
+
processKeyboard(evt) {
|
|
95
|
+
if (this.isReadOnly) {
|
|
96
|
+
return;
|
|
204
97
|
}
|
|
205
|
-
|
|
206
|
-
|
|
98
|
+
// process pressed key
|
|
99
|
+
this.alternativeProcessKey(evt.code, evt.key, evt);
|
|
100
|
+
this.onKeyboardEventProcessedObservable.notifyObservers(evt);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Process the last keyboard input
|
|
104
|
+
*
|
|
105
|
+
* @param code The ascii input number
|
|
106
|
+
* @param key The key string representation
|
|
107
|
+
* @param evt The keyboard event emits with input
|
|
108
|
+
* @internal
|
|
109
|
+
*/
|
|
110
|
+
alternativeProcessKey(code, key, evt) {
|
|
111
|
+
//return if clipboard event keys (i.e -ctr/cmd + c,v,x)
|
|
112
|
+
if (evt && (evt.ctrlKey || evt.metaKey) && (key === "c" || key === "v" || key === "x")) {
|
|
113
|
+
return;
|
|
207
114
|
}
|
|
208
|
-
//
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
if (!this._isTextHighlightOn) {
|
|
223
|
-
this._highlightCursorInfo.initialLineIndex = this._cursorInfo.currentLineIndex;
|
|
224
|
-
this._highlightCursorInfo.initialStartIndex = this._cursorInfo.globalStartIndex;
|
|
225
|
-
this._highlightCursorInfo.initialRelativeStartIndex = this._cursorInfo.relativeStartIndex;
|
|
115
|
+
// Specific cases
|
|
116
|
+
switch (code) {
|
|
117
|
+
case "Period": //SLASH
|
|
118
|
+
if (evt && evt.shiftKey) {
|
|
119
|
+
evt.preventDefault();
|
|
120
|
+
}
|
|
121
|
+
break;
|
|
122
|
+
case "Backspace": // BACKSPACE
|
|
123
|
+
if (!this._isTextHighlightOn && this._cursorInfo.globalStartIndex > 0) {
|
|
124
|
+
this._cursorInfo.globalEndIndex = this._cursorInfo.globalStartIndex;
|
|
125
|
+
this._cursorInfo.globalStartIndex--;
|
|
126
|
+
}
|
|
127
|
+
this._prevText = this._textWrapper.text;
|
|
128
|
+
this._textWrapper.removePart(this._cursorInfo.globalStartIndex, this._cursorInfo.globalEndIndex);
|
|
226
129
|
this._cursorInfo.globalEndIndex = this._cursorInfo.globalStartIndex;
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
130
|
+
if (evt) {
|
|
131
|
+
evt.preventDefault();
|
|
132
|
+
}
|
|
133
|
+
this._blinkIsEven = false;
|
|
134
|
+
this._isTextHighlightOn = false;
|
|
135
|
+
this._textHasChanged();
|
|
136
|
+
break;
|
|
137
|
+
case "Delete": // DELETE
|
|
138
|
+
if (!this._isTextHighlightOn && this._cursorInfo.globalEndIndex < this.text.length) {
|
|
139
|
+
this._cursorInfo.globalEndIndex = this._cursorInfo.globalStartIndex + 1;
|
|
140
|
+
}
|
|
141
|
+
this._prevText = this._textWrapper.text;
|
|
142
|
+
this._textWrapper.removePart(this._cursorInfo.globalStartIndex, this._cursorInfo.globalEndIndex);
|
|
143
|
+
this._cursorInfo.globalEndIndex = this._cursorInfo.globalStartIndex;
|
|
144
|
+
if (evt) {
|
|
145
|
+
evt.preventDefault();
|
|
146
|
+
}
|
|
147
|
+
this._blinkIsEven = false;
|
|
148
|
+
this._isTextHighlightOn = false;
|
|
149
|
+
this._textHasChanged();
|
|
150
|
+
break;
|
|
151
|
+
case "NumpadEnter": // NUMPAD ENTER
|
|
152
|
+
case "Enter": // RETURN
|
|
153
|
+
this._prevText = this._textWrapper.text;
|
|
154
|
+
this._textWrapper.removePart(this._cursorInfo.globalStartIndex, this._cursorInfo.globalEndIndex, "\n");
|
|
155
|
+
this._cursorInfo.globalStartIndex++;
|
|
156
|
+
this._cursorInfo.globalEndIndex = this._cursorInfo.globalStartIndex;
|
|
157
|
+
this._blinkIsEven = false;
|
|
158
|
+
this._isTextHighlightOn = false;
|
|
159
|
+
this._textHasChanged();
|
|
160
|
+
return;
|
|
161
|
+
case "End": // END
|
|
162
|
+
this._cursorInfo.globalStartIndex = this.text.length;
|
|
163
|
+
this._blinkIsEven = false;
|
|
164
|
+
this._isTextHighlightOn = false;
|
|
165
|
+
this._markAsDirty();
|
|
166
|
+
return;
|
|
167
|
+
case "Home": // HOME
|
|
168
|
+
this._cursorInfo.globalStartIndex = 0;
|
|
169
|
+
this._blinkIsEven = false;
|
|
170
|
+
this._isTextHighlightOn = false;
|
|
171
|
+
this._markAsDirty();
|
|
172
|
+
return;
|
|
173
|
+
case "ArrowLeft": // LEFT
|
|
174
|
+
this._markAsDirty();
|
|
175
|
+
if (evt && evt.shiftKey) {
|
|
176
|
+
// shift + ctrl/cmd + <-
|
|
177
|
+
if (evt.ctrlKey || evt.metaKey) {
|
|
178
|
+
// Go to line's start by substract the relativeStartIndex to the globalStartIndex
|
|
179
|
+
this._cursorInfo.globalStartIndex -= this._cursorInfo.relativeStartIndex;
|
|
180
|
+
this._cursorInfo.globalEndIndex = this._highlightCursorInfo.initialStartIndex;
|
|
181
|
+
}
|
|
182
|
+
// store the starting point
|
|
183
|
+
if (!this._isTextHighlightOn) {
|
|
184
|
+
this._highlightCursorInfo.initialLineIndex = this._cursorInfo.currentLineIndex;
|
|
185
|
+
this._highlightCursorInfo.initialStartIndex = this._cursorInfo.globalStartIndex;
|
|
186
|
+
this._highlightCursorInfo.initialRelativeStartIndex = this._cursorInfo.relativeStartIndex;
|
|
187
|
+
this._cursorInfo.globalEndIndex = this._cursorInfo.globalStartIndex;
|
|
188
|
+
this._cursorInfo.globalStartIndex--;
|
|
189
|
+
this._isTextHighlightOn = true;
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
if (this._cursorInfo.globalEndIndex > this._highlightCursorInfo.initialStartIndex) {
|
|
193
|
+
this._cursorInfo.globalEndIndex--;
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
this._cursorInfo.globalStartIndex--;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
this._blinkIsEven = true;
|
|
200
|
+
evt.preventDefault();
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
if (this._isTextHighlightOn) {
|
|
204
|
+
this._cursorInfo.globalEndIndex = this._cursorInfo.globalStartIndex;
|
|
205
|
+
}
|
|
206
|
+
else if (evt && (evt.ctrlKey || evt.metaKey)) {
|
|
207
|
+
// ctr + <-
|
|
208
|
+
this._cursorInfo.globalStartIndex -= this._cursorInfo.relativeStartIndex;
|
|
209
|
+
evt.preventDefault();
|
|
210
|
+
}
|
|
211
|
+
else if (this._cursorInfo.globalStartIndex > 0) {
|
|
212
|
+
this._cursorInfo.globalStartIndex--;
|
|
213
|
+
}
|
|
214
|
+
// update the cursor
|
|
215
|
+
this._blinkIsEven = false;
|
|
216
|
+
this._isTextHighlightOn = false;
|
|
217
|
+
return;
|
|
218
|
+
case "ArrowRight": // RIGHT
|
|
219
|
+
this._markAsDirty();
|
|
220
|
+
if (evt && evt.shiftKey) {
|
|
221
|
+
// shift + ctrl/cmd + ->
|
|
222
|
+
if (evt.ctrlKey || evt.metaKey) {
|
|
223
|
+
const rightDelta = this._lines[this._cursorInfo.currentLineIndex].text.length - this._cursorInfo.relativeEndIndex - 1;
|
|
224
|
+
this._cursorInfo.globalEndIndex += rightDelta;
|
|
225
|
+
this._cursorInfo.globalStartIndex = this._highlightCursorInfo.initialStartIndex;
|
|
226
|
+
}
|
|
227
|
+
// store the starting point
|
|
228
|
+
if (!this._isTextHighlightOn) {
|
|
229
|
+
this._highlightCursorInfo.initialLineIndex = this._cursorInfo.currentLineIndex;
|
|
230
|
+
this._highlightCursorInfo.initialStartIndex = this._cursorInfo.globalStartIndex;
|
|
231
|
+
this._highlightCursorInfo.initialRelativeStartIndex = this._cursorInfo.relativeStartIndex;
|
|
232
|
+
this._cursorInfo.globalEndIndex = this._cursorInfo.globalStartIndex;
|
|
233
|
+
this._cursorInfo.globalEndIndex++;
|
|
234
|
+
this._isTextHighlightOn = true;
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
if (this._cursorInfo.globalStartIndex < this._highlightCursorInfo.initialStartIndex) {
|
|
238
|
+
this._cursorInfo.globalStartIndex++;
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
this._cursorInfo.globalEndIndex++;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
this._blinkIsEven = true;
|
|
245
|
+
evt.preventDefault();
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
if (this._isTextHighlightOn) {
|
|
249
|
+
this._cursorInfo.globalStartIndex = this._cursorInfo.globalEndIndex;
|
|
250
|
+
}
|
|
251
|
+
else if (evt && (evt.ctrlKey || evt.metaKey)) {
|
|
252
|
+
//ctr + ->
|
|
253
|
+
const rightDelta = this._lines[this._cursorInfo.currentLineIndex].text.length - this._cursorInfo.relativeEndIndex;
|
|
254
|
+
this._cursorInfo.globalStartIndex += rightDelta;
|
|
255
|
+
}
|
|
256
|
+
else if (this._cursorInfo.globalStartIndex < this.text.length) {
|
|
232
257
|
this._cursorInfo.globalStartIndex++;
|
|
233
258
|
}
|
|
259
|
+
// update the cursor
|
|
260
|
+
this._blinkIsEven = false;
|
|
261
|
+
this._isTextHighlightOn = false;
|
|
262
|
+
return;
|
|
263
|
+
case "ArrowUp": // UP
|
|
264
|
+
// update the cursor
|
|
265
|
+
this._blinkIsEven = false;
|
|
266
|
+
if (evt) {
|
|
267
|
+
if (evt.shiftKey) {
|
|
268
|
+
if (!this._isTextHighlightOn) {
|
|
269
|
+
this._highlightCursorInfo.initialLineIndex = this._cursorInfo.currentLineIndex;
|
|
270
|
+
this._highlightCursorInfo.initialStartIndex = this._cursorInfo.globalStartIndex;
|
|
271
|
+
this._highlightCursorInfo.initialRelativeStartIndex = this._cursorInfo.relativeStartIndex;
|
|
272
|
+
}
|
|
273
|
+
this._isTextHighlightOn = true;
|
|
274
|
+
this._blinkIsEven = true;
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
this._isTextHighlightOn = false;
|
|
278
|
+
}
|
|
279
|
+
evt.preventDefault();
|
|
280
|
+
}
|
|
281
|
+
if (this._cursorInfo.currentLineIndex === 0) {
|
|
282
|
+
// First line
|
|
283
|
+
this._cursorInfo.globalStartIndex = 0;
|
|
284
|
+
}
|
|
234
285
|
else {
|
|
235
|
-
this._cursorInfo.
|
|
286
|
+
const currentLine = this._lines[this._cursorInfo.currentLineIndex];
|
|
287
|
+
const upperLine = this._lines[this._cursorInfo.currentLineIndex - 1];
|
|
288
|
+
let tmpIndex;
|
|
289
|
+
let relativeIndex;
|
|
290
|
+
if (!this._isTextHighlightOn || this._cursorInfo.currentLineIndex < this._highlightCursorInfo.initialLineIndex) {
|
|
291
|
+
tmpIndex = this._cursorInfo.globalStartIndex;
|
|
292
|
+
relativeIndex = this._cursorInfo.relativeStartIndex;
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
tmpIndex = this._cursorInfo.globalEndIndex;
|
|
296
|
+
relativeIndex = this._cursorInfo.relativeEndIndex;
|
|
297
|
+
}
|
|
298
|
+
const currentText = currentLine.text.substring(0, relativeIndex);
|
|
299
|
+
const currentWidth = this._contextForBreakLines.measureText(currentText).width;
|
|
300
|
+
let upperWidth = 0;
|
|
301
|
+
let previousWidth = 0;
|
|
302
|
+
tmpIndex -= relativeIndex; // Start of current line
|
|
303
|
+
tmpIndex -= upperLine.text.length + upperLine.lineEnding.length; // Start of upper line
|
|
304
|
+
let upperLineRelativeIndex = 0;
|
|
305
|
+
while (upperWidth < currentWidth && upperLineRelativeIndex < upperLine.text.length) {
|
|
306
|
+
tmpIndex++;
|
|
307
|
+
upperLineRelativeIndex++;
|
|
308
|
+
previousWidth = Math.abs(currentWidth - upperWidth);
|
|
309
|
+
upperWidth = this._contextForBreakLines.measureText(upperLine.text.substring(0, upperLineRelativeIndex)).width;
|
|
310
|
+
}
|
|
311
|
+
// Find closest move
|
|
312
|
+
if (Math.abs(currentWidth - upperWidth) > previousWidth && upperLineRelativeIndex > 0) {
|
|
313
|
+
tmpIndex--;
|
|
314
|
+
}
|
|
315
|
+
if (!this._isTextHighlightOn) {
|
|
316
|
+
this._cursorInfo.globalStartIndex = tmpIndex;
|
|
317
|
+
}
|
|
318
|
+
else if (this._cursorInfo.currentLineIndex <= this._highlightCursorInfo.initialLineIndex) {
|
|
319
|
+
this._cursorInfo.globalStartIndex = tmpIndex;
|
|
320
|
+
this._cursorInfo.globalEndIndex = this._highlightCursorInfo.initialStartIndex;
|
|
321
|
+
this._cursorInfo.relativeEndIndex = this._highlightCursorInfo.initialRelativeStartIndex;
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
this._cursorInfo.globalEndIndex = tmpIndex;
|
|
325
|
+
}
|
|
236
326
|
}
|
|
237
|
-
|
|
238
|
-
|
|
327
|
+
this._markAsDirty();
|
|
328
|
+
return;
|
|
329
|
+
case "ArrowDown": // DOWN
|
|
330
|
+
// update the cursor
|
|
331
|
+
this._blinkIsEven = false;
|
|
332
|
+
if (evt) {
|
|
333
|
+
if (evt.shiftKey) {
|
|
334
|
+
if (!this._isTextHighlightOn) {
|
|
335
|
+
this._highlightCursorInfo.initialLineIndex = this._cursorInfo.currentLineIndex;
|
|
336
|
+
this._highlightCursorInfo.initialStartIndex = this._cursorInfo.globalStartIndex;
|
|
337
|
+
this._highlightCursorInfo.initialRelativeStartIndex = this._cursorInfo.relativeStartIndex;
|
|
338
|
+
}
|
|
339
|
+
this._isTextHighlightOn = true;
|
|
340
|
+
this._blinkIsEven = true;
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
this._isTextHighlightOn = false;
|
|
344
|
+
}
|
|
345
|
+
evt.preventDefault();
|
|
346
|
+
}
|
|
347
|
+
if (this._cursorInfo.currentLineIndex === this._lines.length - 1) {
|
|
348
|
+
// Last line
|
|
349
|
+
this._cursorInfo.globalStartIndex = this.text.length;
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
const currentLine = this._lines[this._cursorInfo.currentLineIndex];
|
|
353
|
+
const underLine = this._lines[this._cursorInfo.currentLineIndex + 1];
|
|
354
|
+
let tmpIndex;
|
|
355
|
+
let relativeIndex;
|
|
356
|
+
if (!this._isTextHighlightOn || this._cursorInfo.currentLineIndex < this._highlightCursorInfo.initialLineIndex) {
|
|
357
|
+
tmpIndex = this._cursorInfo.globalStartIndex;
|
|
358
|
+
relativeIndex = this._cursorInfo.relativeStartIndex;
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
tmpIndex = this._cursorInfo.globalEndIndex;
|
|
362
|
+
relativeIndex = this._cursorInfo.relativeEndIndex;
|
|
363
|
+
}
|
|
364
|
+
const currentText = currentLine.text.substring(0, relativeIndex);
|
|
365
|
+
const currentWidth = this._contextForBreakLines.measureText(currentText).width;
|
|
366
|
+
let underWidth = 0;
|
|
367
|
+
let previousWidth = 0;
|
|
368
|
+
tmpIndex += currentLine.text.length - relativeIndex + currentLine.lineEnding.length; // Start of current line
|
|
369
|
+
let underLineRelativeIndex = 0;
|
|
370
|
+
while (underWidth < currentWidth && underLineRelativeIndex < underLine.text.length) {
|
|
371
|
+
tmpIndex++;
|
|
372
|
+
underLineRelativeIndex++;
|
|
373
|
+
previousWidth = Math.abs(currentWidth - underWidth);
|
|
374
|
+
underWidth = this._contextForBreakLines.measureText(underLine.text.substring(0, underLineRelativeIndex)).width;
|
|
375
|
+
}
|
|
376
|
+
// Find closest move
|
|
377
|
+
if (Math.abs(currentWidth - underWidth) > previousWidth && underLineRelativeIndex > 0) {
|
|
378
|
+
tmpIndex--;
|
|
379
|
+
}
|
|
380
|
+
if (!this._isTextHighlightOn) {
|
|
381
|
+
this._cursorInfo.globalStartIndex = tmpIndex;
|
|
382
|
+
}
|
|
383
|
+
else if (this._cursorInfo.currentLineIndex < this._highlightCursorInfo.initialLineIndex) {
|
|
384
|
+
this._cursorInfo.globalStartIndex = tmpIndex;
|
|
385
|
+
if (this._cursorInfo.globalStartIndex > this._cursorInfo.globalEndIndex) {
|
|
386
|
+
this._cursorInfo.globalEndIndex += this._cursorInfo.globalStartIndex;
|
|
387
|
+
this._cursorInfo.globalStartIndex = this._cursorInfo.globalEndIndex - this._cursorInfo.globalStartIndex;
|
|
388
|
+
this._cursorInfo.globalEndIndex -= this._cursorInfo.globalStartIndex;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
this._cursorInfo.globalEndIndex = tmpIndex;
|
|
393
|
+
this._cursorInfo.globalStartIndex = this._highlightCursorInfo.initialStartIndex;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
this._markAsDirty();
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
// special case - select all. Use key instead of code to support all keyboard layouts
|
|
400
|
+
if (key === "a" && evt && (evt.ctrlKey || evt.metaKey)) {
|
|
401
|
+
this.selectAllText();
|
|
239
402
|
evt.preventDefault();
|
|
240
403
|
return;
|
|
241
404
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
this.
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
405
|
+
// Printable characters
|
|
406
|
+
if (key?.length === 1) {
|
|
407
|
+
evt?.preventDefault();
|
|
408
|
+
this._currentKey = key;
|
|
409
|
+
this.onBeforeKeyAddObservable.notifyObservers(this);
|
|
410
|
+
key = this._currentKey;
|
|
411
|
+
if (this._addKey) {
|
|
412
|
+
this._isTextHighlightOn = false;
|
|
413
|
+
this._blinkIsEven = false;
|
|
414
|
+
this._prevText = this._textWrapper.text;
|
|
415
|
+
this._textWrapper.removePart(this._cursorInfo.globalStartIndex, this._cursorInfo.globalEndIndex, key);
|
|
416
|
+
this._cursorInfo.globalStartIndex += key.length;
|
|
417
|
+
this._cursorInfo.globalEndIndex = this._cursorInfo.globalStartIndex;
|
|
418
|
+
this._textHasChanged();
|
|
419
|
+
}
|
|
252
420
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
421
|
+
}
|
|
422
|
+
_parseLineWordWrap(line = "", width, context) {
|
|
423
|
+
const lines = [];
|
|
424
|
+
const words = line.split(" ");
|
|
425
|
+
let lineWidth = 0;
|
|
426
|
+
for (let n = 0; n < words.length; n++) {
|
|
427
|
+
const testLine = n > 0 ? line + " " + words[n] : words[0];
|
|
428
|
+
const metrics = context.measureText(testLine);
|
|
429
|
+
const testWidth = metrics.width;
|
|
430
|
+
if (testWidth > width) {
|
|
431
|
+
if (n > 0) {
|
|
432
|
+
// Avoid first word duplication if of too long
|
|
433
|
+
lineWidth = context.measureText(line).width;
|
|
434
|
+
lines.push({ text: line, width: lineWidth, lineEnding: " " });
|
|
266
435
|
}
|
|
267
|
-
|
|
268
|
-
|
|
436
|
+
line = words[n];
|
|
437
|
+
let flushedLine = "";
|
|
438
|
+
line.split("").map((char) => {
|
|
439
|
+
if (context.measureText(flushedLine + char).width > width) {
|
|
440
|
+
lines.push({ text: flushedLine, width: context.measureText(flushedLine).width, lineEnding: "" });
|
|
441
|
+
flushedLine = "";
|
|
442
|
+
}
|
|
443
|
+
flushedLine += char;
|
|
444
|
+
});
|
|
445
|
+
line = flushedLine;
|
|
446
|
+
// Measure remaining characters
|
|
447
|
+
lineWidth = context.measureText(line).width;
|
|
269
448
|
}
|
|
270
449
|
else {
|
|
271
|
-
|
|
450
|
+
lineWidth = testWidth;
|
|
451
|
+
line = testLine;
|
|
272
452
|
}
|
|
273
|
-
evt.preventDefault();
|
|
274
453
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
454
|
+
lines.push({ text: line, width: lineWidth, lineEnding: " " });
|
|
455
|
+
return lines;
|
|
456
|
+
}
|
|
457
|
+
_breakLines(refWidth, context) {
|
|
458
|
+
const lines = [];
|
|
459
|
+
const _lines = (this.text || this.placeholderText).split("\n");
|
|
460
|
+
if (this.clipContent) {
|
|
461
|
+
for (const _line of _lines) {
|
|
462
|
+
lines.push(...this._parseLineWordWrap(_line, refWidth, context));
|
|
463
|
+
}
|
|
278
464
|
}
|
|
279
465
|
else {
|
|
280
|
-
const
|
|
281
|
-
|
|
282
|
-
let tmpIndex;
|
|
283
|
-
let relativeIndex;
|
|
284
|
-
if (!this._isTextHighlightOn || this._cursorInfo.currentLineIndex < this._highlightCursorInfo.initialLineIndex) {
|
|
285
|
-
tmpIndex = this._cursorInfo.globalStartIndex;
|
|
286
|
-
relativeIndex = this._cursorInfo.relativeStartIndex;
|
|
287
|
-
}
|
|
288
|
-
else {
|
|
289
|
-
tmpIndex = this._cursorInfo.globalEndIndex;
|
|
290
|
-
relativeIndex = this._cursorInfo.relativeEndIndex;
|
|
291
|
-
}
|
|
292
|
-
const currentText = currentLine.text.substring(0, relativeIndex);
|
|
293
|
-
const currentWidth = this._contextForBreakLines.measureText(currentText).width;
|
|
294
|
-
let upperWidth = 0;
|
|
295
|
-
let previousWidth = 0;
|
|
296
|
-
tmpIndex -= relativeIndex; // Start of current line
|
|
297
|
-
tmpIndex -= upperLine.text.length + upperLine.lineEnding.length; // Start of upper line
|
|
298
|
-
let upperLineRelativeIndex = 0;
|
|
299
|
-
while (upperWidth < currentWidth && upperLineRelativeIndex < upperLine.text.length) {
|
|
300
|
-
tmpIndex++;
|
|
301
|
-
upperLineRelativeIndex++;
|
|
302
|
-
previousWidth = Math.abs(currentWidth - upperWidth);
|
|
303
|
-
upperWidth = this._contextForBreakLines.measureText(upperLine.text.substring(0, upperLineRelativeIndex)).width;
|
|
304
|
-
}
|
|
305
|
-
// Find closest move
|
|
306
|
-
if (Math.abs(currentWidth - upperWidth) > previousWidth && upperLineRelativeIndex > 0) {
|
|
307
|
-
tmpIndex--;
|
|
308
|
-
}
|
|
309
|
-
if (!this._isTextHighlightOn) {
|
|
310
|
-
this._cursorInfo.globalStartIndex = tmpIndex;
|
|
311
|
-
}
|
|
312
|
-
else if (this._cursorInfo.currentLineIndex <= this._highlightCursorInfo.initialLineIndex) {
|
|
313
|
-
this._cursorInfo.globalStartIndex = tmpIndex;
|
|
314
|
-
this._cursorInfo.globalEndIndex = this._highlightCursorInfo.initialStartIndex;
|
|
315
|
-
this._cursorInfo.relativeEndIndex = this._highlightCursorInfo.initialRelativeStartIndex;
|
|
316
|
-
}
|
|
317
|
-
else {
|
|
318
|
-
this._cursorInfo.globalEndIndex = tmpIndex;
|
|
466
|
+
for (const _line of _lines) {
|
|
467
|
+
lines.push(this._parseLine(_line, context));
|
|
319
468
|
}
|
|
320
469
|
}
|
|
321
|
-
|
|
322
|
-
return;
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
this._isTextHighlightOn = false;
|
|
338
|
-
}
|
|
339
|
-
evt.preventDefault();
|
|
470
|
+
lines[lines.length - 1].lineEnding = "\n";
|
|
471
|
+
return lines;
|
|
472
|
+
}
|
|
473
|
+
_parseLine(line = "", context) {
|
|
474
|
+
return { text: line, width: context.measureText(line).width, lineEnding: " " };
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Processing of child right before the parent measurement update
|
|
478
|
+
*
|
|
479
|
+
* @param parentMeasure The parent measure
|
|
480
|
+
* @param context The rendering canvas
|
|
481
|
+
* @internal
|
|
482
|
+
*/
|
|
483
|
+
_preMeasure(parentMeasure, context) {
|
|
484
|
+
if (!this._fontOffset || this._wasDirty) {
|
|
485
|
+
this._fontOffset = Control._GetFontOffset(context.font, this._host.getScene()?.getEngine());
|
|
340
486
|
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
487
|
+
let text = this._beforeRenderText(this._textWrapper).text;
|
|
488
|
+
// placeholder conditions and color setting
|
|
489
|
+
if (!this.text && this._placeholderText) {
|
|
490
|
+
text = this._placeholderText;
|
|
344
491
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
if (this._cursorInfo.
|
|
380
|
-
this._cursorInfo.
|
|
381
|
-
|
|
382
|
-
this._cursorInfo.globalEndIndex -= this._cursorInfo.globalStartIndex;
|
|
492
|
+
// measures the textlength -> this.measure.width
|
|
493
|
+
this._textWidth = context.measureText(text).width;
|
|
494
|
+
// we double up the margin width
|
|
495
|
+
const marginWidth = this._margin.getValueInPixel(this._host, parentMeasure.width) * 2;
|
|
496
|
+
if (this._autoStretchWidth) {
|
|
497
|
+
const tmpLines = text.split("\n");
|
|
498
|
+
const longerString = tmpLines.reduce((acc, val) => {
|
|
499
|
+
const valueLength = context.measureText(val).width;
|
|
500
|
+
const accLength = context.measureText(acc).width;
|
|
501
|
+
return valueLength > accLength ? val : acc;
|
|
502
|
+
}, "");
|
|
503
|
+
const longerStringWidth = context.measureText(longerString).width;
|
|
504
|
+
this.width = Math.min(this._maxWidth.getValueInPixel(this._host, parentMeasure.width), longerStringWidth + marginWidth) + "px";
|
|
505
|
+
this.autoStretchWidth = true;
|
|
506
|
+
}
|
|
507
|
+
this._availableWidth = this._width.getValueInPixel(this._host, parentMeasure.width) - marginWidth;
|
|
508
|
+
// Prepare lines
|
|
509
|
+
this._lines = this._breakLines(this._availableWidth, context);
|
|
510
|
+
// can we find a cleaner implementation here?
|
|
511
|
+
this._contextForBreakLines = context;
|
|
512
|
+
if (this._autoStretchHeight) {
|
|
513
|
+
const textHeight = this._lines.length * this._fontOffset.height;
|
|
514
|
+
const totalHeight = textHeight + this._margin.getValueInPixel(this._host, parentMeasure.height) * 2;
|
|
515
|
+
this.height = Math.min(this._maxHeight.getValueInPixel(this._host, parentMeasure.height), totalHeight) + "px";
|
|
516
|
+
this._autoStretchHeight = true;
|
|
517
|
+
}
|
|
518
|
+
const marginHeight = this._margin.getValueInPixel(this._host, parentMeasure.height) * 2;
|
|
519
|
+
this._availableHeight = this._height.getValueInPixel(this._host, parentMeasure.height) - marginHeight;
|
|
520
|
+
if (this._isFocused) {
|
|
521
|
+
this._cursorInfo.currentLineIndex = 0;
|
|
522
|
+
let lineLength = this._lines[this._cursorInfo.currentLineIndex].text.length + this._lines[this._cursorInfo.currentLineIndex].lineEnding.length;
|
|
523
|
+
let tmpLength = 0;
|
|
524
|
+
while (tmpLength + lineLength <= this._cursorInfo.globalStartIndex) {
|
|
525
|
+
tmpLength += lineLength;
|
|
526
|
+
if (this._cursorInfo.currentLineIndex < this._lines.length - 1) {
|
|
527
|
+
this._cursorInfo.currentLineIndex++;
|
|
528
|
+
lineLength = this._lines[this._cursorInfo.currentLineIndex].text.length + this._lines[this._cursorInfo.currentLineIndex].lineEnding.length;
|
|
383
529
|
}
|
|
384
530
|
}
|
|
385
|
-
else {
|
|
386
|
-
this._cursorInfo.globalEndIndex = tmpIndex;
|
|
387
|
-
this._cursorInfo.globalStartIndex = this._highlightCursorInfo.initialStartIndex;
|
|
388
|
-
}
|
|
389
531
|
}
|
|
390
|
-
this._markAsDirty();
|
|
391
|
-
return;
|
|
392
|
-
}
|
|
393
|
-
// special case - select all. Use key instead of code to support all keyboard layouts
|
|
394
|
-
if (key === "a" && evt && (evt.ctrlKey || evt.metaKey)) {
|
|
395
|
-
this.selectAllText();
|
|
396
|
-
evt.preventDefault();
|
|
397
|
-
return;
|
|
398
|
-
}
|
|
399
|
-
// Printable characters
|
|
400
|
-
if (key?.length === 1) {
|
|
401
|
-
evt?.preventDefault();
|
|
402
|
-
this._currentKey = key;
|
|
403
|
-
this.onBeforeKeyAddObservable.notifyObservers(this);
|
|
404
|
-
key = this._currentKey;
|
|
405
|
-
if (this._addKey) {
|
|
406
|
-
this._isTextHighlightOn = false;
|
|
407
|
-
this._blinkIsEven = false;
|
|
408
|
-
this._prevText = this._textWrapper.text;
|
|
409
|
-
this._textWrapper.removePart(this._cursorInfo.globalStartIndex, this._cursorInfo.globalEndIndex, key);
|
|
410
|
-
this._cursorInfo.globalStartIndex += key.length;
|
|
411
|
-
this._cursorInfo.globalEndIndex = this._cursorInfo.globalStartIndex;
|
|
412
|
-
this._textHasChanged();
|
|
413
532
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
const testLine = n > 0 ? line + " " + words[n] : words[0];
|
|
422
|
-
const metrics = context.measureText(testLine);
|
|
423
|
-
const testWidth = metrics.width;
|
|
424
|
-
if (testWidth > width) {
|
|
425
|
-
if (n > 0) {
|
|
426
|
-
// Avoid first word duplication if of too long
|
|
427
|
-
lineWidth = context.measureText(line).width;
|
|
428
|
-
lines.push({ text: line, width: lineWidth, lineEnding: " " });
|
|
533
|
+
_textHasChanged() {
|
|
534
|
+
if (!this._prevText && this._textWrapper.text && this.placeholderText) {
|
|
535
|
+
this._cursorInfo.currentLineIndex = 0;
|
|
536
|
+
this._cursorInfo.globalStartIndex = 1;
|
|
537
|
+
this._cursorInfo.globalEndIndex = 1;
|
|
538
|
+
this._cursorInfo.relativeStartIndex = 1;
|
|
539
|
+
this._cursorInfo.relativeEndIndex = 1;
|
|
429
540
|
}
|
|
430
|
-
|
|
431
|
-
let flushedLine = "";
|
|
432
|
-
line.split("").map((char) => {
|
|
433
|
-
if (context.measureText(flushedLine + char).width > width) {
|
|
434
|
-
lines.push({ text: flushedLine, width: context.measureText(flushedLine).width, lineEnding: "" });
|
|
435
|
-
flushedLine = "";
|
|
436
|
-
}
|
|
437
|
-
flushedLine += char;
|
|
438
|
-
});
|
|
439
|
-
line = flushedLine;
|
|
440
|
-
// Measure remaining characters
|
|
441
|
-
lineWidth = context.measureText(line).width;
|
|
442
|
-
}
|
|
443
|
-
else {
|
|
444
|
-
lineWidth = testWidth;
|
|
445
|
-
line = testLine;
|
|
541
|
+
super._textHasChanged();
|
|
446
542
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
543
|
+
_computeScroll() {
|
|
544
|
+
this._clipTextLeft = this._currentMeasure.left + this._margin.getValueInPixel(this._host, this._cachedParentMeasure.width);
|
|
545
|
+
this._clipTextTop = this._currentMeasure.top + this._margin.getValueInPixel(this._host, this._cachedParentMeasure.height);
|
|
546
|
+
if (this._isFocused && this._lines[this._cursorInfo.currentLineIndex].width > this._availableWidth) {
|
|
547
|
+
const textLeft = this._clipTextLeft - this._lines[this._cursorInfo.currentLineIndex].width + this._availableWidth;
|
|
548
|
+
if (!this._scrollLeft) {
|
|
549
|
+
this._scrollLeft = textLeft;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
else {
|
|
553
|
+
this._scrollLeft = this._clipTextLeft;
|
|
554
|
+
}
|
|
555
|
+
if (this._isFocused) {
|
|
556
|
+
const selectedHeight = (this._cursorInfo.currentLineIndex + 1) * this._fontOffset.height;
|
|
557
|
+
const textTop = this._clipTextTop - selectedHeight;
|
|
558
|
+
if (!this._scrollTop) {
|
|
559
|
+
this._scrollTop = textTop;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
else {
|
|
563
|
+
this._scrollTop = this._clipTextTop;
|
|
564
|
+
}
|
|
457
565
|
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
566
|
+
/**
|
|
567
|
+
* Processing of child after the parent measurement update
|
|
568
|
+
*
|
|
569
|
+
* @internal
|
|
570
|
+
*/
|
|
571
|
+
_additionalProcessing() {
|
|
572
|
+
// Flush the highlighted text each frame
|
|
573
|
+
this.highlightedText = "";
|
|
574
|
+
this.onLinesReadyObservable.notifyObservers(this);
|
|
462
575
|
}
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
*/
|
|
477
|
-
_preMeasure(parentMeasure, context) {
|
|
478
|
-
if (!this._fontOffset || this._wasDirty) {
|
|
479
|
-
this._fontOffset = Control._GetFontOffset(context.font, this._host.getScene()?.getEngine());
|
|
480
|
-
}
|
|
481
|
-
let text = this._beforeRenderText(this._textWrapper).text;
|
|
482
|
-
// placeholder conditions and color setting
|
|
483
|
-
if (!this.text && this._placeholderText) {
|
|
484
|
-
text = this._placeholderText;
|
|
485
|
-
}
|
|
486
|
-
// measures the textlength -> this.measure.width
|
|
487
|
-
this._textWidth = context.measureText(text).width;
|
|
488
|
-
// we double up the margin width
|
|
489
|
-
const marginWidth = this._margin.getValueInPixel(this._host, parentMeasure.width) * 2;
|
|
490
|
-
if (this._autoStretchWidth) {
|
|
491
|
-
const tmpLines = text.split("\n");
|
|
492
|
-
const longerString = tmpLines.reduce((acc, val) => {
|
|
493
|
-
const valueLength = context.measureText(val).width;
|
|
494
|
-
const accLength = context.measureText(acc).width;
|
|
495
|
-
return valueLength > accLength ? val : acc;
|
|
496
|
-
}, "");
|
|
497
|
-
const longerStringWidth = context.measureText(longerString).width;
|
|
498
|
-
this.width = Math.min(this._maxWidth.getValueInPixel(this._host, parentMeasure.width), longerStringWidth + marginWidth) + "px";
|
|
499
|
-
this.autoStretchWidth = true;
|
|
500
|
-
}
|
|
501
|
-
this._availableWidth = this._width.getValueInPixel(this._host, parentMeasure.width) - marginWidth;
|
|
502
|
-
// Prepare lines
|
|
503
|
-
this._lines = this._breakLines(this._availableWidth, context);
|
|
504
|
-
// can we find a cleaner implementation here?
|
|
505
|
-
this._contextForBreakLines = context;
|
|
506
|
-
if (this._autoStretchHeight) {
|
|
507
|
-
const textHeight = this._lines.length * this._fontOffset.height;
|
|
508
|
-
const totalHeight = textHeight + this._margin.getValueInPixel(this._host, parentMeasure.height) * 2;
|
|
509
|
-
this.height = Math.min(this._maxHeight.getValueInPixel(this._host, parentMeasure.height), totalHeight) + "px";
|
|
510
|
-
this._autoStretchHeight = true;
|
|
511
|
-
}
|
|
512
|
-
const marginHeight = this._margin.getValueInPixel(this._host, parentMeasure.height) * 2;
|
|
513
|
-
this._availableHeight = this._height.getValueInPixel(this._host, parentMeasure.height) - marginHeight;
|
|
514
|
-
if (this._isFocused) {
|
|
515
|
-
this._cursorInfo.currentLineIndex = 0;
|
|
516
|
-
let lineLength = this._lines[this._cursorInfo.currentLineIndex].text.length + this._lines[this._cursorInfo.currentLineIndex].lineEnding.length;
|
|
517
|
-
let tmpLength = 0;
|
|
518
|
-
while (tmpLength + lineLength <= this._cursorInfo.globalStartIndex) {
|
|
519
|
-
tmpLength += lineLength;
|
|
520
|
-
if (this._cursorInfo.currentLineIndex < this._lines.length - 1) {
|
|
521
|
-
this._cursorInfo.currentLineIndex++;
|
|
522
|
-
lineLength = this._lines[this._cursorInfo.currentLineIndex].text.length + this._lines[this._cursorInfo.currentLineIndex].lineEnding.length;
|
|
576
|
+
_drawText(text, textWidth, y, context) {
|
|
577
|
+
const width = this._currentMeasure.width;
|
|
578
|
+
let x = this._scrollLeft;
|
|
579
|
+
switch (this._textHorizontalAlignment) {
|
|
580
|
+
case Control.HORIZONTAL_ALIGNMENT_LEFT:
|
|
581
|
+
x += 0;
|
|
582
|
+
break;
|
|
583
|
+
case Control.HORIZONTAL_ALIGNMENT_RIGHT:
|
|
584
|
+
x += width - textWidth;
|
|
585
|
+
break;
|
|
586
|
+
case Control.HORIZONTAL_ALIGNMENT_CENTER:
|
|
587
|
+
x += (width - textWidth) / 2;
|
|
588
|
+
break;
|
|
523
589
|
}
|
|
590
|
+
if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
|
|
591
|
+
context.shadowColor = this.shadowColor;
|
|
592
|
+
context.shadowBlur = this.shadowBlur;
|
|
593
|
+
context.shadowOffsetX = this.shadowOffsetX * this._host.idealRatio;
|
|
594
|
+
context.shadowOffsetY = this.shadowOffsetY * this._host.idealRatio;
|
|
595
|
+
}
|
|
596
|
+
if (this.outlineWidth) {
|
|
597
|
+
context.strokeText(text, this._currentMeasure.left + x, y);
|
|
598
|
+
}
|
|
599
|
+
context.fillText(text, x, y);
|
|
524
600
|
}
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
this._clipTextTop = this._currentMeasure.top + this._margin.getValueInPixel(this._host, this._cachedParentMeasure.height);
|
|
540
|
-
if (this._isFocused && this._lines[this._cursorInfo.currentLineIndex].width > this._availableWidth) {
|
|
541
|
-
const textLeft = this._clipTextLeft - this._lines[this._cursorInfo.currentLineIndex].width + this._availableWidth;
|
|
542
|
-
if (!this._scrollLeft) {
|
|
543
|
-
this._scrollLeft = textLeft;
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
else {
|
|
547
|
-
this._scrollLeft = this._clipTextLeft;
|
|
548
|
-
}
|
|
549
|
-
if (this._isFocused) {
|
|
550
|
-
const selectedHeight = (this._cursorInfo.currentLineIndex + 1) * this._fontOffset.height;
|
|
551
|
-
const textTop = this._clipTextTop - selectedHeight;
|
|
552
|
-
if (!this._scrollTop) {
|
|
553
|
-
this._scrollTop = textTop;
|
|
601
|
+
/**
|
|
602
|
+
* Copy the text in the clipboard
|
|
603
|
+
*
|
|
604
|
+
* @param ev The clipboard event
|
|
605
|
+
* @internal
|
|
606
|
+
*/
|
|
607
|
+
_onCopyText(ev) {
|
|
608
|
+
this._isTextHighlightOn = false;
|
|
609
|
+
//when write permission to clipbaord data is denied
|
|
610
|
+
try {
|
|
611
|
+
ev.clipboardData && ev.clipboardData.setData("text/plain", this._highlightedText);
|
|
612
|
+
}
|
|
613
|
+
catch { } //pass
|
|
614
|
+
this._host.clipboardData = this._highlightedText;
|
|
554
615
|
}
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
case Control.HORIZONTAL_ALIGNMENT_LEFT:
|
|
575
|
-
x += 0;
|
|
576
|
-
break;
|
|
577
|
-
case Control.HORIZONTAL_ALIGNMENT_RIGHT:
|
|
578
|
-
x += width - textWidth;
|
|
579
|
-
break;
|
|
580
|
-
case Control.HORIZONTAL_ALIGNMENT_CENTER:
|
|
581
|
-
x += (width - textWidth) / 2;
|
|
582
|
-
break;
|
|
583
|
-
}
|
|
584
|
-
if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
|
|
585
|
-
context.shadowColor = this.shadowColor;
|
|
586
|
-
context.shadowBlur = this.shadowBlur;
|
|
587
|
-
context.shadowOffsetX = this.shadowOffsetX * this._host.idealRatio;
|
|
588
|
-
context.shadowOffsetY = this.shadowOffsetY * this._host.idealRatio;
|
|
589
|
-
}
|
|
590
|
-
if (this.outlineWidth) {
|
|
591
|
-
context.strokeText(text, this._currentMeasure.left + x, y);
|
|
592
|
-
}
|
|
593
|
-
context.fillText(text, x, y);
|
|
594
|
-
}
|
|
595
|
-
/**
|
|
596
|
-
* Copy the text in the clipboard
|
|
597
|
-
*
|
|
598
|
-
* @param ev The clipboard event
|
|
599
|
-
* @internal
|
|
600
|
-
*/
|
|
601
|
-
_onCopyText(ev) {
|
|
602
|
-
this._isTextHighlightOn = false;
|
|
603
|
-
//when write permission to clipbaord data is denied
|
|
604
|
-
try {
|
|
605
|
-
ev.clipboardData && ev.clipboardData.setData("text/plain", this._highlightedText);
|
|
606
|
-
}
|
|
607
|
-
catch { } //pass
|
|
608
|
-
this._host.clipboardData = this._highlightedText;
|
|
609
|
-
}
|
|
610
|
-
/**
|
|
611
|
-
* Cut the text and copy it in the clipboard
|
|
612
|
-
*
|
|
613
|
-
* @param ev The clipboard event
|
|
614
|
-
* @internal
|
|
615
|
-
*/
|
|
616
|
-
_onCutText(ev) {
|
|
617
|
-
if (!this._highlightedText) {
|
|
618
|
-
return;
|
|
619
|
-
}
|
|
620
|
-
//when write permission to clipbaord data is denied
|
|
621
|
-
try {
|
|
622
|
-
ev.clipboardData && ev.clipboardData.setData("text/plain", this._highlightedText);
|
|
623
|
-
}
|
|
624
|
-
catch { } //pass
|
|
625
|
-
this._host.clipboardData = this._highlightedText;
|
|
626
|
-
this._prevText = this._textWrapper.text;
|
|
627
|
-
this._textWrapper.removePart(this._cursorInfo.globalStartIndex, this._cursorInfo.globalEndIndex);
|
|
628
|
-
this._textHasChanged();
|
|
629
|
-
}
|
|
630
|
-
/**
|
|
631
|
-
* Paste the copied text from the clipboard
|
|
632
|
-
*
|
|
633
|
-
* @param ev The clipboard event
|
|
634
|
-
* @internal
|
|
635
|
-
*/
|
|
636
|
-
_onPasteText(ev) {
|
|
637
|
-
let data;
|
|
638
|
-
if (ev.clipboardData && ev.clipboardData.types.indexOf("text/plain") !== -1) {
|
|
639
|
-
data = ev.clipboardData.getData("text/plain");
|
|
640
|
-
}
|
|
641
|
-
else {
|
|
642
|
-
//get the cached data; returns blank string by default
|
|
643
|
-
data = this._host.clipboardData;
|
|
644
|
-
}
|
|
645
|
-
this._isTextHighlightOn = false;
|
|
646
|
-
this._prevText = this._textWrapper.text;
|
|
647
|
-
this._textWrapper.removePart(this._cursorInfo.globalStartIndex, this._cursorInfo.globalEndIndex, data);
|
|
648
|
-
const deltaIndex = data.length - (this._cursorInfo.globalEndIndex - this._cursorInfo.globalStartIndex);
|
|
649
|
-
this._cursorInfo.globalStartIndex += deltaIndex;
|
|
650
|
-
this._cursorInfo.globalEndIndex = this._cursorInfo.globalStartIndex;
|
|
651
|
-
this._clickedCoordinateX = null;
|
|
652
|
-
this._clickedCoordinateY = null;
|
|
653
|
-
super._textHasChanged();
|
|
654
|
-
}
|
|
655
|
-
_draw(context) {
|
|
656
|
-
this._computeScroll();
|
|
657
|
-
this._scrollLeft = this._scrollLeft ?? 0;
|
|
658
|
-
this._scrollTop = this._scrollTop ?? 0;
|
|
659
|
-
context.save();
|
|
660
|
-
this._applyStates(context);
|
|
661
|
-
if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
|
|
662
|
-
context.shadowColor = this.shadowColor;
|
|
663
|
-
context.shadowBlur = this.shadowBlur;
|
|
664
|
-
context.shadowOffsetX = this.shadowOffsetX * this._host.idealRatio;
|
|
665
|
-
context.shadowOffsetY = this.shadowOffsetY * this._host.idealRatio;
|
|
666
|
-
}
|
|
667
|
-
// Background
|
|
668
|
-
if (this._isFocused) {
|
|
669
|
-
if (this._focusedBackground) {
|
|
670
|
-
context.fillStyle = this._isEnabled ? this._focusedBackground : this._disabledColor;
|
|
671
|
-
context.fillRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
|
|
616
|
+
/**
|
|
617
|
+
* Cut the text and copy it in the clipboard
|
|
618
|
+
*
|
|
619
|
+
* @param ev The clipboard event
|
|
620
|
+
* @internal
|
|
621
|
+
*/
|
|
622
|
+
_onCutText(ev) {
|
|
623
|
+
if (!this._highlightedText) {
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
//when write permission to clipbaord data is denied
|
|
627
|
+
try {
|
|
628
|
+
ev.clipboardData && ev.clipboardData.setData("text/plain", this._highlightedText);
|
|
629
|
+
}
|
|
630
|
+
catch { } //pass
|
|
631
|
+
this._host.clipboardData = this._highlightedText;
|
|
632
|
+
this._prevText = this._textWrapper.text;
|
|
633
|
+
this._textWrapper.removePart(this._cursorInfo.globalStartIndex, this._cursorInfo.globalEndIndex);
|
|
634
|
+
this._textHasChanged();
|
|
672
635
|
}
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
// sets the color of the rectangle (border if background available)
|
|
684
|
-
if (this.color) {
|
|
685
|
-
context.fillStyle = this.color;
|
|
686
|
-
}
|
|
687
|
-
const height = this._currentMeasure.height;
|
|
688
|
-
const width = this._currentMeasure.width;
|
|
689
|
-
let rootY = 0;
|
|
690
|
-
switch (this._textVerticalAlignment) {
|
|
691
|
-
case Control.VERTICAL_ALIGNMENT_TOP:
|
|
692
|
-
rootY = this._fontOffset.ascent;
|
|
693
|
-
break;
|
|
694
|
-
case Control.VERTICAL_ALIGNMENT_BOTTOM:
|
|
695
|
-
rootY = height - this._fontOffset.height * (this._lines.length - 1) - this._fontOffset.descent;
|
|
696
|
-
break;
|
|
697
|
-
case Control.VERTICAL_ALIGNMENT_CENTER:
|
|
698
|
-
rootY = this._fontOffset.ascent + (height - this._fontOffset.height * this._lines.length) / 2;
|
|
699
|
-
break;
|
|
700
|
-
}
|
|
701
|
-
context.save();
|
|
702
|
-
context.beginPath();
|
|
703
|
-
context.fillStyle = this.fontStyle;
|
|
704
|
-
if (!this._textWrapper.text && this.placeholderText) {
|
|
705
|
-
context.fillStyle = this._placeholderColor;
|
|
706
|
-
}
|
|
707
|
-
// here we define the visible reactangle to clip it in next line
|
|
708
|
-
context.rect(this._clipTextLeft, this._clipTextTop, this._availableWidth + 2, this._availableHeight + 2);
|
|
709
|
-
context.clip();
|
|
710
|
-
// Text
|
|
711
|
-
rootY += this._scrollTop;
|
|
712
|
-
for (let i = 0; i < this._lines.length; i++) {
|
|
713
|
-
const line = this._lines[i];
|
|
714
|
-
if (i !== 0 && this._lineSpacing.internalValue !== 0) {
|
|
715
|
-
if (this._lineSpacing.isPixel) {
|
|
716
|
-
rootY += this._lineSpacing.getValue(this._host);
|
|
636
|
+
/**
|
|
637
|
+
* Paste the copied text from the clipboard
|
|
638
|
+
*
|
|
639
|
+
* @param ev The clipboard event
|
|
640
|
+
* @internal
|
|
641
|
+
*/
|
|
642
|
+
_onPasteText(ev) {
|
|
643
|
+
let data;
|
|
644
|
+
if (ev.clipboardData && ev.clipboardData.types.indexOf("text/plain") !== -1) {
|
|
645
|
+
data = ev.clipboardData.getData("text/plain");
|
|
717
646
|
}
|
|
718
647
|
else {
|
|
719
|
-
|
|
648
|
+
//get the cached data; returns blank string by default
|
|
649
|
+
data = this._host.clipboardData;
|
|
720
650
|
}
|
|
651
|
+
this._isTextHighlightOn = false;
|
|
652
|
+
this._prevText = this._textWrapper.text;
|
|
653
|
+
this._textWrapper.removePart(this._cursorInfo.globalStartIndex, this._cursorInfo.globalEndIndex, data);
|
|
654
|
+
const deltaIndex = data.length - (this._cursorInfo.globalEndIndex - this._cursorInfo.globalStartIndex);
|
|
655
|
+
this._cursorInfo.globalStartIndex += deltaIndex;
|
|
656
|
+
this._cursorInfo.globalEndIndex = this._cursorInfo.globalStartIndex;
|
|
657
|
+
this._clickedCoordinateX = null;
|
|
658
|
+
this._clickedCoordinateY = null;
|
|
659
|
+
super._textHasChanged();
|
|
721
660
|
}
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
cursorLeft = this._clipTextLeft;
|
|
734
|
-
this._markAsDirty();
|
|
661
|
+
_draw(context) {
|
|
662
|
+
this._computeScroll();
|
|
663
|
+
this._scrollLeft = this._scrollLeft ?? 0;
|
|
664
|
+
this._scrollTop = this._scrollTop ?? 0;
|
|
665
|
+
context.save();
|
|
666
|
+
this._applyStates(context);
|
|
667
|
+
if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
|
|
668
|
+
context.shadowColor = this.shadowColor;
|
|
669
|
+
context.shadowBlur = this.shadowBlur;
|
|
670
|
+
context.shadowOffsetX = this.shadowOffsetX * this._host.idealRatio;
|
|
671
|
+
context.shadowOffsetY = this.shadowOffsetY * this._host.idealRatio;
|
|
735
672
|
}
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
673
|
+
// Background
|
|
674
|
+
if (this._isFocused) {
|
|
675
|
+
if (this._focusedBackground) {
|
|
676
|
+
context.fillStyle = this._isEnabled ? this._focusedBackground : this._disabledColor;
|
|
677
|
+
context.fillRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
|
|
678
|
+
}
|
|
740
679
|
}
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
this.
|
|
744
|
-
cursorTop = this._clipTextTop;
|
|
745
|
-
this._markAsDirty();
|
|
680
|
+
else if (this._background) {
|
|
681
|
+
context.fillStyle = this._isEnabled ? this._background : this._disabledColor;
|
|
682
|
+
context.fillRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
|
|
746
683
|
}
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
684
|
+
if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
|
|
685
|
+
context.shadowBlur = 0;
|
|
686
|
+
context.shadowOffsetX = 0;
|
|
687
|
+
context.shadowOffsetY = 0;
|
|
751
688
|
}
|
|
752
|
-
if
|
|
753
|
-
|
|
689
|
+
// sets the color of the rectangle (border if background available)
|
|
690
|
+
if (this.color) {
|
|
691
|
+
context.fillStyle = this.color;
|
|
754
692
|
}
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
693
|
+
const height = this._currentMeasure.height;
|
|
694
|
+
const width = this._currentMeasure.width;
|
|
695
|
+
let rootY = 0;
|
|
696
|
+
switch (this._textVerticalAlignment) {
|
|
697
|
+
case Control.VERTICAL_ALIGNMENT_TOP:
|
|
698
|
+
rootY = this._fontOffset.ascent;
|
|
699
|
+
break;
|
|
700
|
+
case Control.VERTICAL_ALIGNMENT_BOTTOM:
|
|
701
|
+
rootY = height - this._fontOffset.height * (this._lines.length - 1) - this._fontOffset.descent;
|
|
702
|
+
break;
|
|
703
|
+
case Control.VERTICAL_ALIGNMENT_CENTER:
|
|
704
|
+
rootY = this._fontOffset.ascent + (height - this._fontOffset.height * this._lines.length) / 2;
|
|
705
|
+
break;
|
|
706
|
+
}
|
|
707
|
+
context.save();
|
|
708
|
+
context.beginPath();
|
|
709
|
+
context.fillStyle = this.fontStyle;
|
|
710
|
+
if (!this._textWrapper.text && this.placeholderText) {
|
|
711
|
+
context.fillStyle = this._placeholderColor;
|
|
712
|
+
}
|
|
713
|
+
// here we define the visible reactangle to clip it in next line
|
|
714
|
+
context.rect(this._clipTextLeft, this._clipTextTop, this._availableWidth + 2, this._availableHeight + 2);
|
|
715
|
+
context.clip();
|
|
716
|
+
// Text
|
|
717
|
+
rootY += this._scrollTop;
|
|
718
|
+
for (let i = 0; i < this._lines.length; i++) {
|
|
767
719
|
const line = this._lines[i];
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
break;
|
|
776
|
-
case Control.HORIZONTAL_ALIGNMENT_CENTER:
|
|
777
|
-
highlightRootX += (width - line.width) / 2;
|
|
778
|
-
break;
|
|
720
|
+
if (i !== 0 && this._lineSpacing.internalValue !== 0) {
|
|
721
|
+
if (this._lineSpacing.isPixel) {
|
|
722
|
+
rootY += this._lineSpacing.getValue(this._host);
|
|
723
|
+
}
|
|
724
|
+
else {
|
|
725
|
+
rootY = rootY + this._lineSpacing.getValue(this._host) * this._height.getValueInPixel(this._host, this._cachedParentMeasure.height);
|
|
726
|
+
}
|
|
779
727
|
}
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
const leftOffsetWidth = context.measureText(line.text.substring(0, begin)).width;
|
|
783
|
-
const selectedText = line.text.substring(begin, end);
|
|
784
|
-
const hightlightWidth = context.measureText(selectedText).width;
|
|
785
|
-
context.fillRect(highlightRootX + leftOffsetWidth, highlightRootY, hightlightWidth, this._fontOffset.height);
|
|
786
|
-
highlightRootY += this._fontOffset.height;
|
|
728
|
+
this._drawText(line.text, line.width, rootY, context);
|
|
729
|
+
rootY += this._fontOffset.height;
|
|
787
730
|
}
|
|
788
|
-
|
|
731
|
+
context.restore();
|
|
732
|
+
// Cursor
|
|
733
|
+
if (this._isFocused) {
|
|
734
|
+
// Render cursor
|
|
735
|
+
if (!this._blinkIsEven || this._isTextHighlightOn) {
|
|
736
|
+
let cursorLeft = this._scrollLeft + context.measureText(this._lines[this._cursorInfo.currentLineIndex].text.substring(0, this._cursorInfo.relativeStartIndex)).width;
|
|
737
|
+
if (cursorLeft < this._clipTextLeft) {
|
|
738
|
+
this._scrollLeft += this._clipTextLeft - cursorLeft;
|
|
739
|
+
cursorLeft = this._clipTextLeft;
|
|
740
|
+
this._markAsDirty();
|
|
741
|
+
}
|
|
742
|
+
else if (cursorLeft > this._clipTextLeft + this._availableWidth) {
|
|
743
|
+
this._scrollLeft += this._clipTextLeft + this._availableWidth - cursorLeft;
|
|
744
|
+
cursorLeft = this._clipTextLeft + this._availableWidth;
|
|
745
|
+
this._markAsDirty();
|
|
746
|
+
}
|
|
747
|
+
let cursorTop = this._scrollTop + this._cursorInfo.currentLineIndex * this._fontOffset.height; //cursorTop distance from top to cursor start
|
|
748
|
+
if (cursorTop < this._clipTextTop) {
|
|
749
|
+
this._scrollTop += this._clipTextTop - cursorTop;
|
|
750
|
+
cursorTop = this._clipTextTop;
|
|
751
|
+
this._markAsDirty();
|
|
752
|
+
}
|
|
753
|
+
else if (cursorTop + this._fontOffset.height > this._clipTextTop + this._availableHeight && this._availableHeight > this._fontOffset.height) {
|
|
754
|
+
this._scrollTop += this._clipTextTop + this._availableHeight - cursorTop - this._fontOffset.height;
|
|
755
|
+
cursorTop = this._clipTextTop + this._availableHeight - this._fontOffset.height;
|
|
756
|
+
this._markAsDirty();
|
|
757
|
+
}
|
|
758
|
+
if (!this._isTextHighlightOn) {
|
|
759
|
+
context.fillRect(cursorLeft, cursorTop, 2, this._fontOffset.height);
|
|
760
|
+
}
|
|
761
|
+
}
|
|
789
762
|
this._resetBlinking();
|
|
763
|
+
//show the highlighted text
|
|
764
|
+
if (this._isTextHighlightOn) {
|
|
765
|
+
clearTimeout(this._blinkTimeout);
|
|
766
|
+
this._highlightedText = this.text.substring(this._cursorInfo.globalStartIndex, this._cursorInfo.globalEndIndex);
|
|
767
|
+
context.globalAlpha = this._highlighterOpacity;
|
|
768
|
+
context.fillStyle = this._textHighlightColor;
|
|
769
|
+
const startLineIndex = Math.min(this._cursorInfo.currentLineIndex, this._highlightCursorInfo.initialLineIndex);
|
|
770
|
+
const endLineIndex = Math.max(this._cursorInfo.currentLineIndex, this._highlightCursorInfo.initialLineIndex);
|
|
771
|
+
let highlightRootY = this._scrollTop + startLineIndex * this._fontOffset.height;
|
|
772
|
+
for (let i = startLineIndex; i <= endLineIndex; i++) {
|
|
773
|
+
const line = this._lines[i];
|
|
774
|
+
let highlightRootX = this._scrollLeft;
|
|
775
|
+
switch (this._textHorizontalAlignment) {
|
|
776
|
+
case Control.HORIZONTAL_ALIGNMENT_LEFT:
|
|
777
|
+
highlightRootX += 0;
|
|
778
|
+
break;
|
|
779
|
+
case Control.HORIZONTAL_ALIGNMENT_RIGHT:
|
|
780
|
+
highlightRootX += width - line.width;
|
|
781
|
+
break;
|
|
782
|
+
case Control.HORIZONTAL_ALIGNMENT_CENTER:
|
|
783
|
+
highlightRootX += (width - line.width) / 2;
|
|
784
|
+
break;
|
|
785
|
+
}
|
|
786
|
+
const begin = i === startLineIndex ? this._cursorInfo.relativeStartIndex : 0;
|
|
787
|
+
const end = i === endLineIndex ? this._cursorInfo.relativeEndIndex : line.text.length;
|
|
788
|
+
const leftOffsetWidth = context.measureText(line.text.substring(0, begin)).width;
|
|
789
|
+
const selectedText = line.text.substring(begin, end);
|
|
790
|
+
const hightlightWidth = context.measureText(selectedText).width;
|
|
791
|
+
context.fillRect(highlightRootX + leftOffsetWidth, highlightRootY, hightlightWidth, this._fontOffset.height);
|
|
792
|
+
highlightRootY += this._fontOffset.height;
|
|
793
|
+
}
|
|
794
|
+
if (this._cursorInfo.globalEndIndex === this._cursorInfo.globalStartIndex) {
|
|
795
|
+
this._resetBlinking();
|
|
796
|
+
}
|
|
797
|
+
}
|
|
790
798
|
}
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
799
|
+
context.restore();
|
|
800
|
+
// Border
|
|
801
|
+
if (this._thickness) {
|
|
802
|
+
if (this._isFocused) {
|
|
803
|
+
if (this.focusedColor) {
|
|
804
|
+
context.strokeStyle = this.focusedColor;
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
else {
|
|
808
|
+
if (this.color) {
|
|
809
|
+
context.strokeStyle = this.color;
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
context.lineWidth = this._thickness;
|
|
813
|
+
context.strokeRect(this._currentMeasure.left + this._thickness / 2, this._currentMeasure.top + this._thickness / 2, this._currentMeasure.width - this._thickness, this._currentMeasure.height - this._thickness);
|
|
804
814
|
}
|
|
805
815
|
}
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
this._blinkTimeout = setTimeout(() => {
|
|
813
|
-
this._blinkIsEven = !this._blinkIsEven;
|
|
814
|
-
this._markAsDirty();
|
|
815
|
-
}, 500);
|
|
816
|
-
}
|
|
817
|
-
_onPointerDown(target, coordinates, pointerId, buttonIndex, pi) {
|
|
818
|
-
if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex, pi)) {
|
|
819
|
-
return false;
|
|
820
|
-
}
|
|
821
|
-
if (this.isReadOnly) {
|
|
822
|
-
return true;
|
|
823
|
-
}
|
|
824
|
-
this._clickedCoordinateX = coordinates.x;
|
|
825
|
-
this._clickedCoordinateY = coordinates.y;
|
|
826
|
-
this._isTextHighlightOn = false;
|
|
827
|
-
this._highlightedText = "";
|
|
828
|
-
this._isPointerDown = true;
|
|
829
|
-
this._host._capturingControl[pointerId] = this;
|
|
830
|
-
if (this._host.focusedControl === this) {
|
|
831
|
-
// Move cursor
|
|
832
|
-
clearTimeout(this._blinkTimeout);
|
|
833
|
-
this._markAsDirty();
|
|
834
|
-
return true;
|
|
835
|
-
}
|
|
836
|
-
if (!this._isEnabled) {
|
|
837
|
-
return false;
|
|
838
|
-
}
|
|
839
|
-
this._host.focusedControl = this;
|
|
840
|
-
return true;
|
|
841
|
-
}
|
|
842
|
-
// for textselection
|
|
843
|
-
_onPointerMove(target, coordinates, pointerId, pi) {
|
|
844
|
-
// Avoid Chromium-like beahavior when this event is fired right after onPointerDown
|
|
845
|
-
if (pi.event.movementX === 0 && pi.event.movementY === 0) {
|
|
846
|
-
return;
|
|
847
|
-
}
|
|
848
|
-
if (this._host.focusedControl === this && this._isPointerDown && !this.isReadOnly) {
|
|
849
|
-
this._clickedCoordinateX = coordinates.x;
|
|
850
|
-
this._clickedCoordinateY = coordinates.y;
|
|
851
|
-
if (!this._isTextHighlightOn) {
|
|
852
|
-
this._highlightCursorInfo.initialLineIndex = this._cursorInfo.currentLineIndex;
|
|
853
|
-
this._highlightCursorInfo.initialStartIndex = this._cursorInfo.globalStartIndex;
|
|
854
|
-
this._highlightCursorInfo.initialRelativeStartIndex = this._cursorInfo.relativeStartIndex;
|
|
855
|
-
this._isTextHighlightOn = true;
|
|
816
|
+
_resetBlinking() {
|
|
817
|
+
clearTimeout(this._blinkTimeout);
|
|
818
|
+
this._blinkTimeout = setTimeout(() => {
|
|
819
|
+
this._blinkIsEven = !this._blinkIsEven;
|
|
820
|
+
this._markAsDirty();
|
|
821
|
+
}, 500);
|
|
856
822
|
}
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
}
|
|
861
|
-
/**
|
|
862
|
-
* Apply the correct position of cursor according to current modification
|
|
863
|
-
*/
|
|
864
|
-
_updateCursorPosition() {
|
|
865
|
-
if (!this._isFocused) {
|
|
866
|
-
return;
|
|
867
|
-
}
|
|
868
|
-
if (!this._textWrapper.text && this.placeholderText) {
|
|
869
|
-
this._cursorInfo.currentLineIndex = 0;
|
|
870
|
-
this._cursorInfo.globalStartIndex = 0;
|
|
871
|
-
this._cursorInfo.globalEndIndex = 0;
|
|
872
|
-
this._cursorInfo.relativeStartIndex = 0;
|
|
873
|
-
this._cursorInfo.relativeEndIndex = 0;
|
|
874
|
-
}
|
|
875
|
-
else {
|
|
876
|
-
if (this._clickedCoordinateX && this._clickedCoordinateY) {
|
|
877
|
-
if (!this._isTextHighlightOn) {
|
|
878
|
-
this._cursorInfo = {
|
|
879
|
-
globalStartIndex: 0,
|
|
880
|
-
globalEndIndex: 0,
|
|
881
|
-
relativeStartIndex: 0,
|
|
882
|
-
relativeEndIndex: 0,
|
|
883
|
-
currentLineIndex: 0,
|
|
884
|
-
};
|
|
823
|
+
_onPointerDown(target, coordinates, pointerId, buttonIndex, pi) {
|
|
824
|
+
if (!super._onPointerDown(target, coordinates, pointerId, buttonIndex, pi)) {
|
|
825
|
+
return false;
|
|
885
826
|
}
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
const lastClickedCoordinateY = this._clickedCoordinateY - this._scrollTop;
|
|
889
|
-
const relativeCoordinateY = Math.floor(lastClickedCoordinateY / this._fontOffset.height);
|
|
890
|
-
this._cursorInfo.currentLineIndex = Math.min(Math.max(relativeCoordinateY, 0), this._lines.length - 1);
|
|
891
|
-
let currentSize = 0;
|
|
892
|
-
const relativeXPosition = this._clickedCoordinateX - (this._scrollLeft ?? 0);
|
|
893
|
-
let previousDist = 0;
|
|
894
|
-
for (let index = 0; index < this._cursorInfo.currentLineIndex; index++) {
|
|
895
|
-
const line = this._lines[index];
|
|
896
|
-
globalIndex += line.text.length + line.lineEnding.length;
|
|
827
|
+
if (this.isReadOnly) {
|
|
828
|
+
return true;
|
|
897
829
|
}
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
830
|
+
this._clickedCoordinateX = coordinates.x;
|
|
831
|
+
this._clickedCoordinateY = coordinates.y;
|
|
832
|
+
this._isTextHighlightOn = false;
|
|
833
|
+
this._highlightedText = "";
|
|
834
|
+
this._isPointerDown = true;
|
|
835
|
+
this._host._capturingControl[pointerId] = this;
|
|
836
|
+
if (this._host.focusedControl === this) {
|
|
837
|
+
// Move cursor
|
|
838
|
+
clearTimeout(this._blinkTimeout);
|
|
839
|
+
this._markAsDirty();
|
|
840
|
+
return true;
|
|
902
841
|
}
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
relativeIndex--;
|
|
842
|
+
if (!this._isEnabled) {
|
|
843
|
+
return false;
|
|
906
844
|
}
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
845
|
+
this._host.focusedControl = this;
|
|
846
|
+
return true;
|
|
847
|
+
}
|
|
848
|
+
// for textselection
|
|
849
|
+
_onPointerMove(target, coordinates, pointerId, pi) {
|
|
850
|
+
// Avoid Chromium-like beahavior when this event is fired right after onPointerDown
|
|
851
|
+
if (pi.event.movementX === 0 && pi.event.movementY === 0) {
|
|
852
|
+
return;
|
|
913
853
|
}
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
this.
|
|
919
|
-
this.
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
this._cursorInfo.globalStartIndex = this._highlightCursorInfo.initialStartIndex;
|
|
923
|
-
this._cursorInfo.relativeStartIndex = this._highlightCursorInfo.initialRelativeStartIndex;
|
|
924
|
-
this._cursorInfo.globalEndIndex = globalIndex;
|
|
925
|
-
this._cursorInfo.relativeEndIndex = relativeIndex;
|
|
854
|
+
if (this._host.focusedControl === this && this._isPointerDown && !this.isReadOnly) {
|
|
855
|
+
this._clickedCoordinateX = coordinates.x;
|
|
856
|
+
this._clickedCoordinateY = coordinates.y;
|
|
857
|
+
if (!this._isTextHighlightOn) {
|
|
858
|
+
this._highlightCursorInfo.initialLineIndex = this._cursorInfo.currentLineIndex;
|
|
859
|
+
this._highlightCursorInfo.initialStartIndex = this._cursorInfo.globalStartIndex;
|
|
860
|
+
this._highlightCursorInfo.initialRelativeStartIndex = this._cursorInfo.relativeStartIndex;
|
|
861
|
+
this._isTextHighlightOn = true;
|
|
926
862
|
}
|
|
863
|
+
this._markAsDirty();
|
|
927
864
|
}
|
|
928
|
-
|
|
929
|
-
this._blinkIsEven = this._isTextHighlightOn;
|
|
930
|
-
this._clickedCoordinateX = null;
|
|
931
|
-
this._clickedCoordinateY = null;
|
|
865
|
+
super._onPointerMove(target, coordinates, pointerId, pi);
|
|
932
866
|
}
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
while (tmpLength + lineLength <= this._cursorInfo.globalStartIndex) {
|
|
940
|
-
tmpLength += lineLength;
|
|
941
|
-
if (this._cursorInfo.currentLineIndex < this._lines.length - 1) {
|
|
942
|
-
this._cursorInfo.currentLineIndex++;
|
|
943
|
-
lineLength = this._lines[this._cursorInfo.currentLineIndex].text.length + this._lines[this._cursorInfo.currentLineIndex].lineEnding.length;
|
|
944
|
-
}
|
|
867
|
+
/**
|
|
868
|
+
* Apply the correct position of cursor according to current modification
|
|
869
|
+
*/
|
|
870
|
+
_updateCursorPosition() {
|
|
871
|
+
if (!this._isFocused) {
|
|
872
|
+
return;
|
|
945
873
|
}
|
|
946
|
-
this.
|
|
947
|
-
|
|
948
|
-
this._cursorInfo.
|
|
949
|
-
this._cursorInfo.globalEndIndex =
|
|
874
|
+
if (!this._textWrapper.text && this.placeholderText) {
|
|
875
|
+
this._cursorInfo.currentLineIndex = 0;
|
|
876
|
+
this._cursorInfo.globalStartIndex = 0;
|
|
877
|
+
this._cursorInfo.globalEndIndex = 0;
|
|
878
|
+
this._cursorInfo.relativeStartIndex = 0;
|
|
879
|
+
this._cursorInfo.relativeEndIndex = 0;
|
|
950
880
|
}
|
|
951
|
-
else
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
881
|
+
else {
|
|
882
|
+
if (this._clickedCoordinateX && this._clickedCoordinateY) {
|
|
883
|
+
if (!this._isTextHighlightOn) {
|
|
884
|
+
this._cursorInfo = {
|
|
885
|
+
globalStartIndex: 0,
|
|
886
|
+
globalEndIndex: 0,
|
|
887
|
+
relativeStartIndex: 0,
|
|
888
|
+
relativeEndIndex: 0,
|
|
889
|
+
currentLineIndex: 0,
|
|
890
|
+
};
|
|
891
|
+
}
|
|
892
|
+
let globalIndex = 0;
|
|
893
|
+
let relativeIndex = 0;
|
|
894
|
+
const lastClickedCoordinateY = this._clickedCoordinateY - this._scrollTop;
|
|
895
|
+
const relativeCoordinateY = Math.floor(lastClickedCoordinateY / this._fontOffset.height);
|
|
896
|
+
this._cursorInfo.currentLineIndex = Math.min(Math.max(relativeCoordinateY, 0), this._lines.length - 1);
|
|
897
|
+
let currentSize = 0;
|
|
898
|
+
const relativeXPosition = this._clickedCoordinateX - (this._scrollLeft ?? 0);
|
|
899
|
+
let previousDist = 0;
|
|
900
|
+
for (let index = 0; index < this._cursorInfo.currentLineIndex; index++) {
|
|
901
|
+
const line = this._lines[index];
|
|
902
|
+
globalIndex += line.text.length + line.lineEnding.length;
|
|
903
|
+
}
|
|
904
|
+
while (currentSize < relativeXPosition && this._lines[this._cursorInfo.currentLineIndex].text.length > relativeIndex) {
|
|
905
|
+
relativeIndex++;
|
|
906
|
+
previousDist = Math.abs(relativeXPosition - currentSize);
|
|
907
|
+
currentSize = this._contextForBreakLines.measureText(this._lines[this._cursorInfo.currentLineIndex].text.substring(0, relativeIndex)).width;
|
|
908
|
+
}
|
|
909
|
+
// Find closest move
|
|
910
|
+
if (Math.abs(relativeXPosition - currentSize) > previousDist && relativeIndex > 0) {
|
|
911
|
+
relativeIndex--;
|
|
912
|
+
}
|
|
913
|
+
globalIndex += relativeIndex;
|
|
914
|
+
if (!this._isTextHighlightOn) {
|
|
915
|
+
this._cursorInfo.globalStartIndex = globalIndex;
|
|
916
|
+
this._cursorInfo.relativeStartIndex = relativeIndex;
|
|
917
|
+
this._cursorInfo.globalEndIndex = this._cursorInfo.globalStartIndex;
|
|
918
|
+
this._cursorInfo.relativeEndIndex = this._cursorInfo.relativeStartIndex;
|
|
919
|
+
}
|
|
920
|
+
else {
|
|
921
|
+
if (globalIndex < this._highlightCursorInfo.initialStartIndex) {
|
|
922
|
+
this._cursorInfo.globalStartIndex = globalIndex;
|
|
923
|
+
this._cursorInfo.relativeStartIndex = relativeIndex;
|
|
924
|
+
this._cursorInfo.globalEndIndex = this._highlightCursorInfo.initialStartIndex;
|
|
925
|
+
this._cursorInfo.relativeEndIndex = this._highlightCursorInfo.initialRelativeStartIndex;
|
|
926
|
+
}
|
|
927
|
+
else {
|
|
928
|
+
this._cursorInfo.globalStartIndex = this._highlightCursorInfo.initialStartIndex;
|
|
929
|
+
this._cursorInfo.relativeStartIndex = this._highlightCursorInfo.initialRelativeStartIndex;
|
|
930
|
+
this._cursorInfo.globalEndIndex = globalIndex;
|
|
931
|
+
this._cursorInfo.relativeEndIndex = relativeIndex;
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
// Avoid the caret during highlighting
|
|
935
|
+
this._blinkIsEven = this._isTextHighlightOn;
|
|
936
|
+
this._clickedCoordinateX = null;
|
|
937
|
+
this._clickedCoordinateY = null;
|
|
938
|
+
}
|
|
939
|
+
else {
|
|
940
|
+
// Standard behavior same as Current line is at least above the initial highlight index
|
|
941
|
+
this._cursorInfo.relativeStartIndex = 0;
|
|
942
|
+
this._cursorInfo.currentLineIndex = 0;
|
|
943
|
+
let lineLength = this._lines[this._cursorInfo.currentLineIndex].text.length + this._lines[this._cursorInfo.currentLineIndex].lineEnding.length;
|
|
944
|
+
let tmpLength = 0;
|
|
945
|
+
while (tmpLength + lineLength <= this._cursorInfo.globalStartIndex) {
|
|
946
|
+
tmpLength += lineLength;
|
|
947
|
+
if (this._cursorInfo.currentLineIndex < this._lines.length - 1) {
|
|
948
|
+
this._cursorInfo.currentLineIndex++;
|
|
949
|
+
lineLength = this._lines[this._cursorInfo.currentLineIndex].text.length + this._lines[this._cursorInfo.currentLineIndex].lineEnding.length;
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
this._cursorInfo.relativeStartIndex = this._cursorInfo.globalStartIndex - tmpLength;
|
|
953
|
+
if (!this._isTextHighlightOn) {
|
|
954
|
+
this._cursorInfo.relativeEndIndex = this._cursorInfo.relativeStartIndex;
|
|
955
|
+
this._cursorInfo.globalEndIndex = this._cursorInfo.globalStartIndex;
|
|
956
|
+
}
|
|
957
|
+
else if (this._highlightCursorInfo.initialStartIndex !== -1 && this._cursorInfo.globalStartIndex >= this._highlightCursorInfo.initialStartIndex) {
|
|
958
|
+
// Current line is at least below the initial highlight index
|
|
959
|
+
while (tmpLength + lineLength <= this._cursorInfo.globalEndIndex) {
|
|
960
|
+
tmpLength += lineLength;
|
|
961
|
+
if (this._cursorInfo.currentLineIndex < this._lines.length - 1) {
|
|
962
|
+
this._cursorInfo.currentLineIndex++;
|
|
963
|
+
lineLength = this._lines[this._cursorInfo.currentLineIndex].text.length + this._lines[this._cursorInfo.currentLineIndex].lineEnding.length;
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
this._cursorInfo.relativeEndIndex = this._cursorInfo.globalEndIndex - tmpLength;
|
|
958
967
|
}
|
|
959
968
|
}
|
|
960
|
-
this._cursorInfo.relativeEndIndex = this._cursorInfo.globalEndIndex - tmpLength;
|
|
961
969
|
}
|
|
962
970
|
}
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
this.
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
971
|
+
/**
|
|
972
|
+
* Update all values of cursor information based on cursorIndex value
|
|
973
|
+
*
|
|
974
|
+
* @param offset The index to take care of
|
|
975
|
+
* @internal
|
|
976
|
+
*/
|
|
977
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
978
|
+
_updateValueFromCursorIndex(offset) {
|
|
979
|
+
// Override to avoid parent behavior during _onPointerMove
|
|
980
|
+
}
|
|
981
|
+
/**
|
|
982
|
+
* Select the word immediatly under the cursor on double click
|
|
983
|
+
*
|
|
984
|
+
* @param _evt Pointer informations of double click
|
|
985
|
+
* @internal
|
|
986
|
+
*/
|
|
987
|
+
_processDblClick(_evt) {
|
|
988
|
+
//pre-find the start and end index of the word under cursor, speeds up the rendering
|
|
989
|
+
let moveLeft, moveRight;
|
|
990
|
+
do {
|
|
991
|
+
moveLeft = this._cursorInfo.globalStartIndex > 0 && this._textWrapper.isWord(this._cursorInfo.globalStartIndex - 1) ? --this._cursorInfo.globalStartIndex : 0;
|
|
992
|
+
moveRight =
|
|
993
|
+
this._cursorInfo.globalEndIndex < this._textWrapper.length && this._textWrapper.isWord(this._cursorInfo.globalEndIndex) ? ++this._cursorInfo.globalEndIndex : 0;
|
|
994
|
+
} while (moveLeft || moveRight);
|
|
995
|
+
this._highlightCursorInfo.initialLineIndex = this._cursorInfo.currentLineIndex;
|
|
996
|
+
this._highlightCursorInfo.initialStartIndex = this._cursorInfo.globalStartIndex;
|
|
997
|
+
this.onTextHighlightObservable.notifyObservers(this);
|
|
998
|
+
this._isTextHighlightOn = true;
|
|
999
|
+
this._blinkIsEven = true;
|
|
1000
|
+
this._markAsDirty();
|
|
1001
|
+
}
|
|
1002
|
+
/** @internal */
|
|
1003
|
+
selectAllText() {
|
|
1004
|
+
this._isTextHighlightOn = true;
|
|
1005
|
+
this._blinkIsEven = true;
|
|
1006
|
+
this._highlightCursorInfo = {
|
|
1007
|
+
initialStartIndex: 0,
|
|
1008
|
+
initialRelativeStartIndex: 0,
|
|
1009
|
+
initialLineIndex: 0,
|
|
1010
|
+
};
|
|
1011
|
+
this._cursorInfo = {
|
|
1012
|
+
globalStartIndex: 0,
|
|
1013
|
+
globalEndIndex: this._textWrapper.length,
|
|
1014
|
+
relativeEndIndex: this._lines[this._lines.length - 1].text.length,
|
|
1015
|
+
relativeStartIndex: 0,
|
|
1016
|
+
currentLineIndex: this._lines.length - 1,
|
|
1017
|
+
};
|
|
1018
|
+
this._markAsDirty();
|
|
1019
|
+
}
|
|
1020
|
+
dispose() {
|
|
1021
|
+
super.dispose();
|
|
1022
|
+
this.onLinesReadyObservable.clear();
|
|
1023
|
+
}
|
|
1024
|
+
},
|
|
1025
|
+
(() => {
|
|
1026
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
1027
|
+
_get_autoStretchHeight_decorators = [serialize()];
|
|
1028
|
+
_get_maxHeight_decorators = [serialize()];
|
|
1029
|
+
__esDecorate(_a, null, _get_autoStretchHeight_decorators, { kind: "getter", name: "autoStretchHeight", static: false, private: false, access: { has: obj => "autoStretchHeight" in obj, get: obj => obj.autoStretchHeight }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1030
|
+
__esDecorate(_a, null, _get_maxHeight_decorators, { kind: "getter", name: "maxHeight", static: false, private: false, access: { has: obj => "maxHeight" in obj, get: obj => obj.maxHeight }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1031
|
+
if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
1032
|
+
})(),
|
|
1033
|
+
_a;
|
|
1034
|
+
})();
|
|
1035
|
+
export { InputTextArea };
|
|
1025
1036
|
let _Registered = false;
|
|
1026
1037
|
/**
|
|
1027
1038
|
* Registers the InputTextArea class with the type store for serialization support.
|