@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.
Files changed (64) hide show
  1. package/2D/controls/checkbox.pure.js +164 -153
  2. package/2D/controls/checkbox.pure.js.map +1 -1
  3. package/2D/controls/colorpicker.pure.js +1300 -1289
  4. package/2D/controls/colorpicker.pure.js.map +1 -1
  5. package/2D/controls/container.pure.js +597 -582
  6. package/2D/controls/container.pure.js.map +1 -1
  7. package/2D/controls/control.pure.js +2474 -2434
  8. package/2D/controls/control.pure.js.map +1 -1
  9. package/2D/controls/displayGrid.pure.js +201 -190
  10. package/2D/controls/displayGrid.pure.js.map +1 -1
  11. package/2D/controls/ellipse.pure.js +96 -85
  12. package/2D/controls/ellipse.pure.js.map +1 -1
  13. package/2D/controls/grid.pure.js +511 -500
  14. package/2D/controls/grid.pure.js.map +1 -1
  15. package/2D/controls/image.pure.js +888 -877
  16. package/2D/controls/image.pure.js.map +1 -1
  17. package/2D/controls/inputText.pure.js +988 -973
  18. package/2D/controls/inputText.pure.js.map +1 -1
  19. package/2D/controls/inputTextArea.pure.js +955 -944
  20. package/2D/controls/inputTextArea.pure.js.map +1 -1
  21. package/2D/controls/line.pure.js +237 -226
  22. package/2D/controls/line.pure.js.map +1 -1
  23. package/2D/controls/multiLine.pure.js +233 -222
  24. package/2D/controls/multiLine.pure.js.map +1 -1
  25. package/2D/controls/radioButton.pure.js +182 -169
  26. package/2D/controls/radioButton.pure.js.map +1 -1
  27. package/2D/controls/rectangle.pure.js +211 -200
  28. package/2D/controls/rectangle.pure.js.map +1 -1
  29. package/2D/controls/scrollViewers/scrollViewer.pure.js +579 -567
  30. package/2D/controls/scrollViewers/scrollViewer.pure.js.map +1 -1
  31. package/2D/controls/sliders/baseSlider.js +291 -280
  32. package/2D/controls/sliders/baseSlider.js.map +1 -1
  33. package/2D/controls/sliders/imageBasedSlider.pure.js +158 -147
  34. package/2D/controls/sliders/imageBasedSlider.pure.js.map +1 -1
  35. package/2D/controls/sliders/imageScrollBar.js +237 -223
  36. package/2D/controls/sliders/imageScrollBar.js.map +1 -1
  37. package/2D/controls/sliders/scrollBar.pure.js +169 -158
  38. package/2D/controls/sliders/scrollBar.pure.js.map +1 -1
  39. package/2D/controls/sliders/slider.pure.js +251 -240
  40. package/2D/controls/sliders/slider.pure.js.map +1 -1
  41. package/2D/controls/stackPanel.pure.js +236 -221
  42. package/2D/controls/stackPanel.pure.js.map +1 -1
  43. package/2D/controls/textBlock.pure.js +637 -626
  44. package/2D/controls/textBlock.pure.js.map +1 -1
  45. package/3D/materials/fluent/fluentMaterial.pure.d.ts +4 -4
  46. package/3D/materials/fluent/fluentMaterial.pure.js +322 -273
  47. package/3D/materials/fluent/fluentMaterial.pure.js.map +1 -1
  48. package/3D/materials/fluentBackplate/fluentBackplateMaterial.pure.js +510 -454
  49. package/3D/materials/fluentBackplate/fluentBackplateMaterial.pure.js.map +1 -1
  50. package/3D/materials/fluentButton/fluentButtonMaterial.pure.js +612 -529
  51. package/3D/materials/fluentButton/fluentButtonMaterial.pure.js.map +1 -1
  52. package/3D/materials/mrdl/mrdlBackglowMaterial.pure.js +313 -274
  53. package/3D/materials/mrdl/mrdlBackglowMaterial.pure.js.map +1 -1
  54. package/3D/materials/mrdl/mrdlBackplateMaterial.pure.js +462 -405
  55. package/3D/materials/mrdl/mrdlBackplateMaterial.pure.js.map +1 -1
  56. package/3D/materials/mrdl/mrdlFrontplateMaterial.pure.js +583 -501
  57. package/3D/materials/mrdl/mrdlFrontplateMaterial.pure.js.map +1 -1
  58. package/3D/materials/mrdl/mrdlInnerquadMaterial.pure.js +226 -203
  59. package/3D/materials/mrdl/mrdlInnerquadMaterial.pure.js.map +1 -1
  60. package/3D/materials/mrdl/mrdlSliderBarMaterial.pure.js +961 -825
  61. package/3D/materials/mrdl/mrdlSliderBarMaterial.pure.js.map +1 -1
  62. package/3D/materials/mrdl/mrdlSliderThumbMaterial.pure.js +961 -825
  63. package/3D/materials/mrdl/mrdlSliderThumbMaterial.pure.js.map +1 -1
  64. package/package.json +2 -2
@@ -1,4 +1,4 @@
1
- import { __decorate } from "@babylonjs/core/tslib.es6.js";
1
+ import { __esDecorate, __runInitializers } from "@babylonjs/core/tslib.es6.js";
2
2
  import { Observable } from "@babylonjs/core/Misc/observable.js";
3
3
  import { ValueAndUnit } from "../valueAndUnit.js";
4
4
  import { Control } from "./control.pure.js";
@@ -34,647 +34,658 @@ export var TextWrapping;
34
34
  /**
35
35
  * Class used to create text block control
36
36
  */
37
- export class TextBlock extends Control {
38
- /**
39
- * Return the line list (you may need to use the onLinesReadyObservable to make sure the list is ready)
40
- */
41
- get lines() {
42
- return this._lines;
43
- }
44
- /**
45
- * Gets or sets a boolean indicating that the TextBlock will be resized to fit its content
46
-
47
- */
48
- get resizeToFit() {
49
- return this._resizeToFit;
50
- }
51
- /**
52
- * Gets or sets a boolean indicating that the TextBlock will be resized to fit its content
53
-
54
- */
55
- set resizeToFit(value) {
56
- if (this._resizeToFit === value) {
57
- return;
58
- }
59
- this._resizeToFit = value;
60
- if (this._resizeToFit) {
61
- this._width.ignoreAdaptiveScaling = true;
62
- this._height.ignoreAdaptiveScaling = true;
63
- }
64
- this._markAsDirty();
65
- }
66
- /**
67
- * Gets or sets a boolean indicating if text must be wrapped
68
- */
69
- get textWrapping() {
70
- return this._textWrapping;
71
- }
72
- /**
73
- * Gets or sets a boolean indicating if text must be wrapped
74
- */
75
- set textWrapping(value) {
76
- if (this._textWrapping === value) {
77
- return;
78
- }
79
- this._textWrapping = +value;
80
- this._markAsDirty();
81
- }
82
- /**
83
- * Gets or sets text to display
84
- */
85
- get text() {
86
- return this._text;
87
- }
88
- /**
89
- * Gets or sets text to display
90
- */
91
- set text(value) {
92
- if (this._text === value) {
93
- return;
94
- }
95
- this._text = value + ""; // Making sure it is a text
96
- this._markAsDirty();
97
- this.onTextChangedObservable.notifyObservers(this);
98
- }
99
- /**
100
- * Gets or sets text horizontal alignment (BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER by default)
101
- */
102
- get textHorizontalAlignment() {
103
- return this._textHorizontalAlignment;
104
- }
105
- /**
106
- * Gets or sets text horizontal alignment (BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER by default)
107
- */
108
- set textHorizontalAlignment(value) {
109
- if (this._textHorizontalAlignment === value) {
110
- return;
111
- }
112
- this._textHorizontalAlignment = value;
113
- this._markAsDirty();
114
- }
115
- /**
116
- * Gets or sets text vertical alignment (BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER by default)
117
- */
118
- get textVerticalAlignment() {
119
- return this._textVerticalAlignment;
120
- }
121
- /**
122
- * Gets or sets text vertical alignment (BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER by default)
123
- */
124
- set textVerticalAlignment(value) {
125
- if (this._textVerticalAlignment === value) {
126
- return;
127
- }
128
- this._textVerticalAlignment = value;
129
- this._markAsDirty();
130
- }
131
- /**
132
- * Gets or sets line spacing value
133
- */
134
- set lineSpacing(value) {
135
- if (this._lineSpacing.fromString(value)) {
136
- this._markAsDirty();
137
- }
138
- }
139
- /**
140
- * Gets or sets line spacing value
141
- */
142
- get lineSpacing() {
143
- return this._lineSpacing.toString(this._host);
144
- }
145
- /**
146
- * Gets or sets outlineWidth of the text to display
147
- */
148
- get outlineWidth() {
149
- return this._outlineWidth;
150
- }
151
- /**
152
- * Gets or sets outlineWidth of the text to display
153
- */
154
- set outlineWidth(value) {
155
- if (this._outlineWidth === value) {
156
- return;
157
- }
158
- this._outlineWidth = value;
159
- this._markAsDirty();
160
- }
161
- /**
162
- * Gets or sets a boolean indicating that text must have underline
163
- */
164
- get underline() {
165
- return this._underline;
166
- }
167
- /**
168
- * Gets or sets a boolean indicating that text must have underline
169
- */
170
- set underline(value) {
171
- if (this._underline === value) {
172
- return;
173
- }
174
- this._underline = value;
175
- this._markAsDirty();
176
- }
177
- /**
178
- * Gets or sets an boolean indicating that text must be crossed out
179
- */
180
- get lineThrough() {
181
- return this._lineThrough;
182
- }
183
- /**
184
- * Gets or sets an boolean indicating that text must be crossed out
185
- */
186
- set lineThrough(value) {
187
- if (this._lineThrough === value) {
188
- return;
189
- }
190
- this._lineThrough = value;
191
- this._markAsDirty();
192
- }
193
- /**
194
- * If the outline should be applied to the underline/strike-through too. Has different behavior in Edge/Chrome vs Firefox.
195
- */
196
- get applyOutlineToUnderline() {
197
- return this._applyOutlineToUnderline;
198
- }
199
- set applyOutlineToUnderline(value) {
200
- if (this._applyOutlineToUnderline === value) {
201
- return;
202
- }
203
- this._applyOutlineToUnderline = value;
204
- this._markAsDirty();
205
- }
206
- /**
207
- * Gets or sets outlineColor of the text to display
208
- */
209
- get outlineColor() {
210
- return this._outlineColor;
211
- }
212
- /**
213
- * Gets or sets outlineColor of the text to display
214
- */
215
- set outlineColor(value) {
216
- if (this._outlineColor === value) {
217
- return;
218
- }
219
- this._outlineColor = value;
220
- this._markAsDirty();
221
- }
222
- /**
223
- * Gets or sets word divider
224
- */
225
- get wordDivider() {
226
- return this._wordDivider;
227
- }
228
- /**
229
- * Gets or sets word divider
230
- */
231
- set wordDivider(value) {
232
- if (this._wordDivider === value) {
233
- return;
234
- }
235
- this._wordDivider = value;
236
- this._markAsDirty();
237
- }
238
- /**
239
- * By default, if a text block has text wrapping other than Clip, its width
240
- * is not resized even if resizeToFit = true. This parameter forces the width
241
- * to be resized.
242
- */
243
- get forceResizeWidth() {
244
- return this._forceResizeWidth;
245
- }
246
- set forceResizeWidth(value) {
247
- if (this._forceResizeWidth === value) {
248
- return;
249
- }
250
- this._forceResizeWidth = value;
251
- this._markAsDirty();
252
- }
253
- /**
254
- * Creates a new TextBlock object
255
- * @param name defines the name of the control
256
- * @param text defines the text to display (empty string by default)
257
- */
258
- constructor(
259
- /**
260
- * Defines the name of the control
261
- */
262
- name, text = "") {
263
- super(name);
264
- this.name = name;
265
- this._text = "";
266
- this._textWrapping = 0 /* TextWrapping.Clip */;
267
- this._textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
268
- this._textVerticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
269
- this._resizeToFit = false;
270
- this._lineSpacing = new ValueAndUnit(0);
271
- this._outlineWidth = 0;
272
- this._outlineColor = "white";
273
- this._underline = false;
274
- this._lineThrough = false;
275
- this._wordDivider = " ";
276
- this._forceResizeWidth = false;
277
- this._applyOutlineToUnderline = false;
278
- /**
279
- * An event triggered after the text is changed
280
- */
281
- this.onTextChangedObservable = new Observable();
282
- /**
283
- * An event triggered after the text was broken up into lines
284
- */
285
- this.onLinesReadyObservable = new Observable();
286
- /**
287
- * Gets or sets a boolean indicating if the HTML element generated for word wrapping should be reused or removed after each wrapping.
288
- */
289
- this.reuseHTMLForWordWrapping = false;
290
- this._linesTemp = [];
291
- this._htmlElement = null;
292
- this.text = text;
293
- }
294
- _getTypeName() {
295
- return "TextBlock";
296
- }
297
- _processMeasures(parentMeasure, context) {
298
- super._processMeasures(parentMeasure, context);
299
- // Apply states so we can use the right font to measure
300
- context.save();
301
- this._applyStates(context);
302
- // Measure the font
303
- if (!this._fontOffset || this.isDirty) {
304
- this._fontOffset = Control._GetFontOffset(context.font, this._host.getScene()?.getEngine());
305
- }
306
- // Prepare lines
307
- this._lines = this._breakLines(this._currentMeasure.width, this._currentMeasure.height, context);
308
- this.onLinesReadyObservable.notifyObservers(this);
309
- // Restore context now that we're done measuring the font
310
- context.restore();
311
- let maxLineWidth = 0;
312
- for (let i = 0; i < this._lines.length; i++) {
313
- const line = this._lines[i];
314
- if (line.width > maxLineWidth) {
315
- maxLineWidth = line.width;
316
- }
317
- }
318
- if (this._resizeToFit) {
319
- if (this._textWrapping === 0 /* TextWrapping.Clip */ || this._forceResizeWidth) {
320
- const newWidth = Math.ceil(this._paddingLeftInPixels) + Math.ceil(this._paddingRightInPixels) + Math.ceil(maxLineWidth);
321
- if (newWidth !== this._width.getValueInPixel(this._host, this._tempParentMeasure.width)) {
322
- this._width.updateInPlace(newWidth, ValueAndUnit.UNITMODE_PIXEL);
323
- this._rebuildLayout = true;
324
- }
325
- }
326
- let newHeight = (this._paddingTopInPixels + this._paddingBottomInPixels + this._fontOffset.height * this._lines.length) | 0;
327
- if (this._lines.length > 0 && this._lineSpacing.internalValue !== 0) {
328
- let lineSpacing;
329
- if (this._lineSpacing.isPixel) {
330
- lineSpacing = this._lineSpacing.getValue(this._host);
37
+ let TextBlock = (() => {
38
+ var _a;
39
+ let _classSuper = Control;
40
+ let _instanceExtraInitializers = [];
41
+ let _get_resizeToFit_decorators;
42
+ let _get_textWrapping_decorators;
43
+ let _get_text_decorators;
44
+ let _get_textHorizontalAlignment_decorators;
45
+ let _get_textVerticalAlignment_decorators;
46
+ let _set_lineSpacing_decorators;
47
+ let _get_outlineWidth_decorators;
48
+ let _get_underline_decorators;
49
+ let _get_lineThrough_decorators;
50
+ let _get_applyOutlineToUnderline_decorators;
51
+ let _get_outlineColor_decorators;
52
+ let _get_wordDivider_decorators;
53
+ let _get_forceResizeWidth_decorators;
54
+ return _a = class TextBlock extends _classSuper {
55
+ /**
56
+ * Return the line list (you may need to use the onLinesReadyObservable to make sure the list is ready)
57
+ */
58
+ get lines() {
59
+ return this._lines;
60
+ }
61
+ /**
62
+ * Gets or sets a boolean indicating that the TextBlock will be resized to fit its content
63
+
64
+ */
65
+ get resizeToFit() {
66
+ return this._resizeToFit;
67
+ }
68
+ /**
69
+ * Gets or sets a boolean indicating that the TextBlock will be resized to fit its content
70
+
71
+ */
72
+ set resizeToFit(value) {
73
+ if (this._resizeToFit === value) {
74
+ return;
75
+ }
76
+ this._resizeToFit = value;
77
+ if (this._resizeToFit) {
78
+ this._width.ignoreAdaptiveScaling = true;
79
+ this._height.ignoreAdaptiveScaling = true;
80
+ }
81
+ this._markAsDirty();
82
+ }
83
+ /**
84
+ * Gets or sets a boolean indicating if text must be wrapped
85
+ */
86
+ get textWrapping() {
87
+ return this._textWrapping;
88
+ }
89
+ /**
90
+ * Gets or sets a boolean indicating if text must be wrapped
91
+ */
92
+ set textWrapping(value) {
93
+ if (this._textWrapping === value) {
94
+ return;
95
+ }
96
+ this._textWrapping = +value;
97
+ this._markAsDirty();
98
+ }
99
+ /**
100
+ * Gets or sets text to display
101
+ */
102
+ get text() {
103
+ return this._text;
104
+ }
105
+ /**
106
+ * Gets or sets text to display
107
+ */
108
+ set text(value) {
109
+ if (this._text === value) {
110
+ return;
111
+ }
112
+ this._text = value + ""; // Making sure it is a text
113
+ this._markAsDirty();
114
+ this.onTextChangedObservable.notifyObservers(this);
115
+ }
116
+ /**
117
+ * Gets or sets text horizontal alignment (BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER by default)
118
+ */
119
+ get textHorizontalAlignment() {
120
+ return this._textHorizontalAlignment;
121
+ }
122
+ /**
123
+ * Gets or sets text horizontal alignment (BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER by default)
124
+ */
125
+ set textHorizontalAlignment(value) {
126
+ if (this._textHorizontalAlignment === value) {
127
+ return;
128
+ }
129
+ this._textHorizontalAlignment = value;
130
+ this._markAsDirty();
131
+ }
132
+ /**
133
+ * Gets or sets text vertical alignment (BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER by default)
134
+ */
135
+ get textVerticalAlignment() {
136
+ return this._textVerticalAlignment;
137
+ }
138
+ /**
139
+ * Gets or sets text vertical alignment (BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER by default)
140
+ */
141
+ set textVerticalAlignment(value) {
142
+ if (this._textVerticalAlignment === value) {
143
+ return;
144
+ }
145
+ this._textVerticalAlignment = value;
146
+ this._markAsDirty();
147
+ }
148
+ /**
149
+ * Gets or sets line spacing value
150
+ */
151
+ set lineSpacing(value) {
152
+ if (this._lineSpacing.fromString(value)) {
153
+ this._markAsDirty();
154
+ }
155
+ }
156
+ /**
157
+ * Gets or sets line spacing value
158
+ */
159
+ get lineSpacing() {
160
+ return this._lineSpacing.toString(this._host);
161
+ }
162
+ /**
163
+ * Gets or sets outlineWidth of the text to display
164
+ */
165
+ get outlineWidth() {
166
+ return this._outlineWidth;
167
+ }
168
+ /**
169
+ * Gets or sets outlineWidth of the text to display
170
+ */
171
+ set outlineWidth(value) {
172
+ if (this._outlineWidth === value) {
173
+ return;
174
+ }
175
+ this._outlineWidth = value;
176
+ this._markAsDirty();
177
+ }
178
+ /**
179
+ * Gets or sets a boolean indicating that text must have underline
180
+ */
181
+ get underline() {
182
+ return this._underline;
183
+ }
184
+ /**
185
+ * Gets or sets a boolean indicating that text must have underline
186
+ */
187
+ set underline(value) {
188
+ if (this._underline === value) {
189
+ return;
190
+ }
191
+ this._underline = value;
192
+ this._markAsDirty();
193
+ }
194
+ /**
195
+ * Gets or sets an boolean indicating that text must be crossed out
196
+ */
197
+ get lineThrough() {
198
+ return this._lineThrough;
199
+ }
200
+ /**
201
+ * Gets or sets an boolean indicating that text must be crossed out
202
+ */
203
+ set lineThrough(value) {
204
+ if (this._lineThrough === value) {
205
+ return;
206
+ }
207
+ this._lineThrough = value;
208
+ this._markAsDirty();
209
+ }
210
+ /**
211
+ * If the outline should be applied to the underline/strike-through too. Has different behavior in Edge/Chrome vs Firefox.
212
+ */
213
+ get applyOutlineToUnderline() {
214
+ return this._applyOutlineToUnderline;
215
+ }
216
+ set applyOutlineToUnderline(value) {
217
+ if (this._applyOutlineToUnderline === value) {
218
+ return;
219
+ }
220
+ this._applyOutlineToUnderline = value;
221
+ this._markAsDirty();
222
+ }
223
+ /**
224
+ * Gets or sets outlineColor of the text to display
225
+ */
226
+ get outlineColor() {
227
+ return this._outlineColor;
228
+ }
229
+ /**
230
+ * Gets or sets outlineColor of the text to display
231
+ */
232
+ set outlineColor(value) {
233
+ if (this._outlineColor === value) {
234
+ return;
235
+ }
236
+ this._outlineColor = value;
237
+ this._markAsDirty();
238
+ }
239
+ /**
240
+ * Gets or sets word divider
241
+ */
242
+ get wordDivider() {
243
+ return this._wordDivider;
244
+ }
245
+ /**
246
+ * Gets or sets word divider
247
+ */
248
+ set wordDivider(value) {
249
+ if (this._wordDivider === value) {
250
+ return;
251
+ }
252
+ this._wordDivider = value;
253
+ this._markAsDirty();
254
+ }
255
+ /**
256
+ * By default, if a text block has text wrapping other than Clip, its width
257
+ * is not resized even if resizeToFit = true. This parameter forces the width
258
+ * to be resized.
259
+ */
260
+ get forceResizeWidth() {
261
+ return this._forceResizeWidth;
262
+ }
263
+ set forceResizeWidth(value) {
264
+ if (this._forceResizeWidth === value) {
265
+ return;
266
+ }
267
+ this._forceResizeWidth = value;
268
+ this._markAsDirty();
269
+ }
270
+ /**
271
+ * Creates a new TextBlock object
272
+ * @param name defines the name of the control
273
+ * @param text defines the text to display (empty string by default)
274
+ */
275
+ constructor(
276
+ /**
277
+ * Defines the name of the control
278
+ */
279
+ name, text = "") {
280
+ super(name);
281
+ this.name = (__runInitializers(this, _instanceExtraInitializers), name);
282
+ this._text = "";
283
+ this._textWrapping = 0 /* TextWrapping.Clip */;
284
+ this._textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
285
+ this._textVerticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
286
+ this._resizeToFit = false;
287
+ this._lineSpacing = new ValueAndUnit(0);
288
+ this._outlineWidth = 0;
289
+ this._outlineColor = "white";
290
+ this._underline = false;
291
+ this._lineThrough = false;
292
+ this._wordDivider = " ";
293
+ this._forceResizeWidth = false;
294
+ this._applyOutlineToUnderline = false;
295
+ /**
296
+ * An event triggered after the text is changed
297
+ */
298
+ this.onTextChangedObservable = new Observable();
299
+ /**
300
+ * An event triggered after the text was broken up into lines
301
+ */
302
+ this.onLinesReadyObservable = new Observable();
303
+ /**
304
+ * Gets or sets a boolean indicating if the HTML element generated for word wrapping should be reused or removed after each wrapping.
305
+ */
306
+ this.reuseHTMLForWordWrapping = false;
307
+ this._linesTemp = [];
308
+ this._htmlElement = null;
309
+ this.text = text;
310
+ }
311
+ _getTypeName() {
312
+ return "TextBlock";
313
+ }
314
+ _processMeasures(parentMeasure, context) {
315
+ super._processMeasures(parentMeasure, context);
316
+ // Apply states so we can use the right font to measure
317
+ context.save();
318
+ this._applyStates(context);
319
+ // Measure the font
320
+ if (!this._fontOffset || this.isDirty) {
321
+ this._fontOffset = Control._GetFontOffset(context.font, this._host.getScene()?.getEngine());
322
+ }
323
+ // Prepare lines
324
+ this._lines = this._breakLines(this._currentMeasure.width, this._currentMeasure.height, context);
325
+ this.onLinesReadyObservable.notifyObservers(this);
326
+ // Restore context now that we're done measuring the font
327
+ context.restore();
328
+ let maxLineWidth = 0;
329
+ for (let i = 0; i < this._lines.length; i++) {
330
+ const line = this._lines[i];
331
+ if (line.width > maxLineWidth) {
332
+ maxLineWidth = line.width;
333
+ }
334
+ }
335
+ if (this._resizeToFit) {
336
+ if (this._textWrapping === 0 /* TextWrapping.Clip */ || this._forceResizeWidth) {
337
+ const newWidth = Math.ceil(this._paddingLeftInPixels) + Math.ceil(this._paddingRightInPixels) + Math.ceil(maxLineWidth);
338
+ if (newWidth !== this._width.getValueInPixel(this._host, this._tempParentMeasure.width)) {
339
+ this._width.updateInPlace(newWidth, ValueAndUnit.UNITMODE_PIXEL);
340
+ this._rebuildLayout = true;
341
+ }
342
+ }
343
+ let newHeight = (this._paddingTopInPixels + this._paddingBottomInPixels + this._fontOffset.height * this._lines.length) | 0;
344
+ if (this._lines.length > 0 && this._lineSpacing.internalValue !== 0) {
345
+ let lineSpacing;
346
+ if (this._lineSpacing.isPixel) {
347
+ lineSpacing = this._lineSpacing.getValue(this._host);
348
+ }
349
+ else {
350
+ lineSpacing = this._lineSpacing.getValue(this._host) * this._height.getValueInPixel(this._host, this._cachedParentMeasure.height);
351
+ }
352
+ newHeight += (this._lines.length - 1) * lineSpacing;
353
+ }
354
+ if (newHeight !== this._height.internalValue) {
355
+ this._height.updateInPlace(newHeight, ValueAndUnit.UNITMODE_PIXEL);
356
+ this._rebuildLayout = true;
357
+ }
358
+ }
359
+ }
360
+ _drawText(text, textWidth, y, context) {
361
+ const width = this._currentMeasure.width;
362
+ let x = 0;
363
+ switch (this._textHorizontalAlignment) {
364
+ case Control.HORIZONTAL_ALIGNMENT_LEFT:
365
+ x = 0;
366
+ break;
367
+ case Control.HORIZONTAL_ALIGNMENT_RIGHT:
368
+ x = width - textWidth;
369
+ break;
370
+ case Control.HORIZONTAL_ALIGNMENT_CENTER:
371
+ x = (width - textWidth) / 2;
372
+ break;
373
+ }
374
+ if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
375
+ context.shadowColor = this.shadowColor;
376
+ context.shadowBlur = this.shadowBlur;
377
+ const idealRatio = this.host.idealRatio;
378
+ context.shadowOffsetX = this.shadowOffsetX * idealRatio;
379
+ context.shadowOffsetY = this.shadowOffsetY * idealRatio;
380
+ }
381
+ if (this.outlineWidth) {
382
+ context.strokeText(text, this._currentMeasure.left + x, y);
383
+ }
384
+ context.fillText(text, this._currentMeasure.left + x, y);
385
+ if (this._underline) {
386
+ this._drawLine(this._currentMeasure.left + x, y + 3, this._currentMeasure.left + x + textWidth, y + 3, context);
387
+ }
388
+ if (this._lineThrough) {
389
+ this._drawLine(this._currentMeasure.left + x, y - this.fontSizeInPixels / 3, this._currentMeasure.left + x + textWidth, y - this.fontSizeInPixels / 3, context);
390
+ }
391
+ }
392
+ _drawLine(xFrom, yFrom, xTo, yTo, context) {
393
+ context.beginPath();
394
+ context.lineWidth = Math.round(this.fontSizeInPixels * 0.05);
395
+ context.moveTo(xFrom, yFrom);
396
+ context.lineTo(xTo, yTo);
397
+ if (this.outlineWidth && this.applyOutlineToUnderline) {
398
+ context.stroke();
399
+ context.fill();
331
400
  }
332
401
  else {
333
- lineSpacing = this._lineSpacing.getValue(this._host) * this._height.getValueInPixel(this._host, this._cachedParentMeasure.height);
402
+ const currentStroke = context.strokeStyle;
403
+ context.strokeStyle = context.fillStyle;
404
+ context.stroke();
405
+ context.strokeStyle = currentStroke;
334
406
  }
335
- newHeight += (this._lines.length - 1) * lineSpacing;
407
+ context.closePath();
336
408
  }
337
- if (newHeight !== this._height.internalValue) {
338
- this._height.updateInPlace(newHeight, ValueAndUnit.UNITMODE_PIXEL);
339
- this._rebuildLayout = true;
409
+ /**
410
+ * @internal
411
+ */
412
+ _draw(context) {
413
+ context.save();
414
+ this._applyStates(context);
415
+ // Render lines
416
+ this._renderLines(context);
417
+ context.restore();
340
418
  }
341
- }
342
- }
343
- _drawText(text, textWidth, y, context) {
344
- const width = this._currentMeasure.width;
345
- let x = 0;
346
- switch (this._textHorizontalAlignment) {
347
- case Control.HORIZONTAL_ALIGNMENT_LEFT:
348
- x = 0;
349
- break;
350
- case Control.HORIZONTAL_ALIGNMENT_RIGHT:
351
- x = width - textWidth;
352
- break;
353
- case Control.HORIZONTAL_ALIGNMENT_CENTER:
354
- x = (width - textWidth) / 2;
355
- break;
356
- }
357
- if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
358
- context.shadowColor = this.shadowColor;
359
- context.shadowBlur = this.shadowBlur;
360
- const idealRatio = this.host.idealRatio;
361
- context.shadowOffsetX = this.shadowOffsetX * idealRatio;
362
- context.shadowOffsetY = this.shadowOffsetY * idealRatio;
363
- }
364
- if (this.outlineWidth) {
365
- context.strokeText(text, this._currentMeasure.left + x, y);
366
- }
367
- context.fillText(text, this._currentMeasure.left + x, y);
368
- if (this._underline) {
369
- this._drawLine(this._currentMeasure.left + x, y + 3, this._currentMeasure.left + x + textWidth, y + 3, context);
370
- }
371
- if (this._lineThrough) {
372
- this._drawLine(this._currentMeasure.left + x, y - this.fontSizeInPixels / 3, this._currentMeasure.left + x + textWidth, y - this.fontSizeInPixels / 3, context);
373
- }
374
- }
375
- _drawLine(xFrom, yFrom, xTo, yTo, context) {
376
- context.beginPath();
377
- context.lineWidth = Math.round(this.fontSizeInPixels * 0.05);
378
- context.moveTo(xFrom, yFrom);
379
- context.lineTo(xTo, yTo);
380
- if (this.outlineWidth && this.applyOutlineToUnderline) {
381
- context.stroke();
382
- context.fill();
383
- }
384
- else {
385
- const currentStroke = context.strokeStyle;
386
- context.strokeStyle = context.fillStyle;
387
- context.stroke();
388
- context.strokeStyle = currentStroke;
389
- }
390
- context.closePath();
391
- }
392
- /**
393
- * @internal
394
- */
395
- _draw(context) {
396
- context.save();
397
- this._applyStates(context);
398
- // Render lines
399
- this._renderLines(context);
400
- context.restore();
401
- }
402
- _applyStates(context) {
403
- super._applyStates(context);
404
- if (this.outlineWidth) {
405
- context.lineWidth = this.outlineWidth;
406
- context.strokeStyle = this.outlineColor;
407
- context.lineJoin = "miter";
408
- context.miterLimit = 2;
409
- }
410
- }
411
- _breakLines(refWidth, refHeight, context) {
412
- this._linesTemp.length = 0;
413
- const _lines = this._textWrapping === 4 /* TextWrapping.HTML */ ? this._parseHTMLText(refWidth, refHeight, context) : this.text.split("\n");
414
- switch (this._textWrapping) {
415
- case 1 /* TextWrapping.WordWrap */:
416
- for (const _line of _lines) {
417
- this._linesTemp.push(...this._parseLineWordWrap(_line, refWidth, context));
418
- }
419
- break;
420
- case 2 /* TextWrapping.Ellipsis */:
421
- for (const _line of _lines) {
422
- this._linesTemp.push(this._parseLineEllipsis(_line, refWidth, context));
423
- }
424
- break;
425
- case 3 /* TextWrapping.WordWrapEllipsis */:
426
- for (const _line of _lines) {
427
- this._linesTemp.push(...this._parseLineWordWrapEllipsis(_line, refWidth, refHeight, context));
428
- }
429
- break;
430
- case 4 /* TextWrapping.HTML */:
431
- default:
432
- for (const _line of _lines) {
433
- this._linesTemp.push(this._parseLine(_line, context));
434
- }
435
- break;
436
- }
437
- return this._linesTemp;
438
- }
439
- _parseHTMLText(refWidth, refHeight, context) {
440
- const lines = [];
441
- if (!this._htmlElement) {
442
- this._htmlElement = document.createElement("div");
443
- document.body.appendChild(this._htmlElement);
444
- }
445
- const htmlElement = this._htmlElement;
446
- htmlElement.textContent = this.text;
447
- htmlElement.style.font = context.font;
448
- htmlElement.style.position = "absolute";
449
- htmlElement.style.visibility = "hidden";
450
- htmlElement.style.top = "-1000px";
451
- htmlElement.style.left = "-1000px";
452
- this.adjustWordWrappingHTMLElement?.(htmlElement);
453
- htmlElement.style.width = refWidth + "px";
454
- htmlElement.style.height = refHeight + "px";
455
- const textContent = htmlElement.textContent;
456
- if (!textContent) {
457
- return lines;
458
- }
459
- // get the text node
460
- const textNode = htmlElement.childNodes[0];
461
- const range = document.createRange();
462
- let idx = 0;
463
- for (const c of textContent) {
464
- range.setStart(textNode, 0);
465
- range.setEnd(textNode, idx + 1);
466
- // "select" text from beginning to this position to determine the line
467
- const lineIndex = range.getClientRects().length - 1;
468
- lines[lineIndex] = (lines[lineIndex] || "") + c;
469
- idx++;
470
- }
471
- if (!this.reuseHTMLForWordWrapping) {
472
- htmlElement.remove();
473
- this._htmlElement = null;
474
- }
475
- return lines;
476
- }
477
- _parseLine(line = "", context) {
478
- return { text: line, width: this._getTextMetricsWidth(context.measureText(line)) };
479
- }
480
- //Calculate how many characters approximately we need to remove
481
- _getCharsToRemove(lineWidth, width, lineLength) {
482
- const diff = lineWidth > width ? lineWidth - width : 0;
483
- // This isn't exact unless the font is monospaced
484
- const charWidth = lineWidth / lineLength;
485
- const removeChars = Math.max(Math.floor(diff / charWidth), 1);
486
- return removeChars;
487
- }
488
- _parseLineEllipsis(line = "", width, context) {
489
- let lineWidth = this._getTextMetricsWidth(context.measureText(line));
490
- let removeChars = this._getCharsToRemove(lineWidth, width, line.length);
491
- // unicode support. split('') does not work with unicode!
492
- // make sure Array.from is available
493
- const characters = Array.from && Array.from(line);
494
- if (!characters) {
495
- // no array.from, use the old method
496
- while (line.length > 2 && lineWidth > width) {
497
- line = line.slice(0, -removeChars);
498
- lineWidth = this._getTextMetricsWidth(context.measureText(line + "…"));
499
- removeChars = this._getCharsToRemove(lineWidth, width, line.length);
500
- }
501
- // Add on the end
502
- line += "…";
503
- }
504
- else {
505
- while (characters.length && lineWidth > width) {
506
- characters.splice(characters.length - removeChars, removeChars);
507
- line = `${characters.join("")}…`;
508
- lineWidth = this._getTextMetricsWidth(context.measureText(line));
509
- removeChars = this._getCharsToRemove(lineWidth, width, line.length);
510
- }
511
- }
512
- return { text: line, width: lineWidth };
513
- }
514
- _getTextMetricsWidth(textMetrics) {
515
- if (textMetrics.actualBoundingBoxLeft !== undefined) {
516
- return Math.abs(textMetrics.actualBoundingBoxLeft) + Math.abs(textMetrics.actualBoundingBoxRight);
517
- }
518
- return textMetrics.width;
519
- }
520
- _parseLineWordWrap(line = "", width, context) {
521
- const lines = [];
522
- const words = this.wordSplittingFunction ? this.wordSplittingFunction(line) : line.split(this._wordDivider);
523
- let lineWidth = this._getTextMetricsWidth(context.measureText(line));
524
- for (let n = 0; n < words.length; n++) {
525
- const testLine = n > 0 ? line + this._wordDivider + words[n] : words[0];
526
- const testWidth = this._getTextMetricsWidth(context.measureText(testLine));
527
- if (testWidth > width && n > 0) {
528
- lines.push({ text: line, width: lineWidth });
529
- line = words[n];
530
- lineWidth = this._getTextMetricsWidth(context.measureText(line));
419
+ _applyStates(context) {
420
+ super._applyStates(context);
421
+ if (this.outlineWidth) {
422
+ context.lineWidth = this.outlineWidth;
423
+ context.strokeStyle = this.outlineColor;
424
+ context.lineJoin = "miter";
425
+ context.miterLimit = 2;
426
+ }
531
427
  }
532
- else {
533
- lineWidth = testWidth;
534
- line = testLine;
428
+ _breakLines(refWidth, refHeight, context) {
429
+ this._linesTemp.length = 0;
430
+ const _lines = this._textWrapping === 4 /* TextWrapping.HTML */ ? this._parseHTMLText(refWidth, refHeight, context) : this.text.split("\n");
431
+ switch (this._textWrapping) {
432
+ case 1 /* TextWrapping.WordWrap */:
433
+ for (const _line of _lines) {
434
+ this._linesTemp.push(...this._parseLineWordWrap(_line, refWidth, context));
435
+ }
436
+ break;
437
+ case 2 /* TextWrapping.Ellipsis */:
438
+ for (const _line of _lines) {
439
+ this._linesTemp.push(this._parseLineEllipsis(_line, refWidth, context));
440
+ }
441
+ break;
442
+ case 3 /* TextWrapping.WordWrapEllipsis */:
443
+ for (const _line of _lines) {
444
+ this._linesTemp.push(...this._parseLineWordWrapEllipsis(_line, refWidth, refHeight, context));
445
+ }
446
+ break;
447
+ case 4 /* TextWrapping.HTML */:
448
+ default:
449
+ for (const _line of _lines) {
450
+ this._linesTemp.push(this._parseLine(_line, context));
451
+ }
452
+ break;
453
+ }
454
+ return this._linesTemp;
535
455
  }
536
- }
537
- lines.push({ text: line, width: lineWidth });
538
- return lines;
539
- }
540
- _parseLineWordWrapEllipsis(line = "", width, height, context) {
541
- const lines = this._parseLineWordWrap(line, width, context);
542
- for (let n = 1; n <= lines.length; n++) {
543
- const currentHeight = this._computeHeightForLinesOf(n);
544
- if (currentHeight > height && n > 1) {
545
- const lastLine = lines[n - 2];
546
- const currentLine = lines[n - 1];
547
- lines[n - 2] = this._parseLineEllipsis(lastLine.text + this._wordDivider + currentLine.text, width, context);
548
- const linesToRemove = lines.length - n + 1;
549
- for (let i = 0; i < linesToRemove; i++) {
550
- lines.pop();
456
+ _parseHTMLText(refWidth, refHeight, context) {
457
+ const lines = [];
458
+ if (!this._htmlElement) {
459
+ this._htmlElement = document.createElement("div");
460
+ document.body.appendChild(this._htmlElement);
461
+ }
462
+ const htmlElement = this._htmlElement;
463
+ htmlElement.textContent = this.text;
464
+ htmlElement.style.font = context.font;
465
+ htmlElement.style.position = "absolute";
466
+ htmlElement.style.visibility = "hidden";
467
+ htmlElement.style.top = "-1000px";
468
+ htmlElement.style.left = "-1000px";
469
+ this.adjustWordWrappingHTMLElement?.(htmlElement);
470
+ htmlElement.style.width = refWidth + "px";
471
+ htmlElement.style.height = refHeight + "px";
472
+ const textContent = htmlElement.textContent;
473
+ if (!textContent) {
474
+ return lines;
475
+ }
476
+ // get the text node
477
+ const textNode = htmlElement.childNodes[0];
478
+ const range = document.createRange();
479
+ let idx = 0;
480
+ for (const c of textContent) {
481
+ range.setStart(textNode, 0);
482
+ range.setEnd(textNode, idx + 1);
483
+ // "select" text from beginning to this position to determine the line
484
+ const lineIndex = range.getClientRects().length - 1;
485
+ lines[lineIndex] = (lines[lineIndex] || "") + c;
486
+ idx++;
487
+ }
488
+ if (!this.reuseHTMLForWordWrapping) {
489
+ htmlElement.remove();
490
+ this._htmlElement = null;
551
491
  }
552
492
  return lines;
553
493
  }
554
- }
555
- return lines;
556
- }
557
- _renderLines(context) {
558
- if (!this._fontOffset || !this._lines) {
559
- return;
560
- }
561
- const height = this._currentMeasure.height;
562
- let rootY = 0;
563
- switch (this._textVerticalAlignment) {
564
- case Control.VERTICAL_ALIGNMENT_TOP:
565
- rootY = this._fontOffset.ascent;
566
- break;
567
- case Control.VERTICAL_ALIGNMENT_BOTTOM:
568
- rootY = height - this._fontOffset.height * (this._lines.length - 1) - this._fontOffset.descent;
569
- break;
570
- case Control.VERTICAL_ALIGNMENT_CENTER:
571
- rootY = this._fontOffset.ascent + (height - this._fontOffset.height * this._lines.length) / 2;
572
- break;
573
- }
574
- rootY += this._currentMeasure.top;
575
- for (let i = 0; i < this._lines.length; i++) {
576
- const line = this._lines[i];
577
- if (i !== 0 && this._lineSpacing.internalValue !== 0) {
578
- if (this._lineSpacing.isPixel) {
579
- rootY += this._lineSpacing.getValue(this._host);
494
+ _parseLine(line = "", context) {
495
+ return { text: line, width: this._getTextMetricsWidth(context.measureText(line)) };
496
+ }
497
+ //Calculate how many characters approximately we need to remove
498
+ _getCharsToRemove(lineWidth, width, lineLength) {
499
+ const diff = lineWidth > width ? lineWidth - width : 0;
500
+ // This isn't exact unless the font is monospaced
501
+ const charWidth = lineWidth / lineLength;
502
+ const removeChars = Math.max(Math.floor(diff / charWidth), 1);
503
+ return removeChars;
504
+ }
505
+ _parseLineEllipsis(line = "", width, context) {
506
+ let lineWidth = this._getTextMetricsWidth(context.measureText(line));
507
+ let removeChars = this._getCharsToRemove(lineWidth, width, line.length);
508
+ // unicode support. split('') does not work with unicode!
509
+ // make sure Array.from is available
510
+ const characters = Array.from && Array.from(line);
511
+ if (!characters) {
512
+ // no array.from, use the old method
513
+ while (line.length > 2 && lineWidth > width) {
514
+ line = line.slice(0, -removeChars);
515
+ lineWidth = this._getTextMetricsWidth(context.measureText(line + "…"));
516
+ removeChars = this._getCharsToRemove(lineWidth, width, line.length);
517
+ }
518
+ // Add on the end
519
+ line += "…";
580
520
  }
581
521
  else {
582
- rootY = rootY + this._lineSpacing.getValue(this._host) * this._height.getValueInPixel(this._host, this._cachedParentMeasure.height);
522
+ while (characters.length && lineWidth > width) {
523
+ characters.splice(characters.length - removeChars, removeChars);
524
+ line = `${characters.join("")}…`;
525
+ lineWidth = this._getTextMetricsWidth(context.measureText(line));
526
+ removeChars = this._getCharsToRemove(lineWidth, width, line.length);
527
+ }
583
528
  }
529
+ return { text: line, width: lineWidth };
584
530
  }
585
- this._drawText(line.text, line.width, rootY, context);
586
- rootY += this._fontOffset.height;
587
- }
588
- }
589
- _computeHeightForLinesOf(lineCount) {
590
- let newHeight = this._paddingTopInPixels + this._paddingBottomInPixels + this._fontOffset.height * lineCount;
591
- if (lineCount > 0 && this._lineSpacing.internalValue !== 0) {
592
- let lineSpacing;
593
- if (this._lineSpacing.isPixel) {
594
- lineSpacing = this._lineSpacing.getValue(this._host);
595
- }
596
- else {
597
- lineSpacing = this._lineSpacing.getValue(this._host) * this._height.getValueInPixel(this._host, this._cachedParentMeasure.height);
598
- }
599
- newHeight += (lineCount - 1) * lineSpacing;
600
- }
601
- return newHeight;
602
- }
603
- isDimensionFullyDefined(dim) {
604
- if (this.resizeToFit) {
605
- return true;
606
- }
607
- return super.isDimensionFullyDefined(dim);
608
- }
609
- /**
610
- * Given a width constraint applied on the text block, find the expected height
611
- * @returns expected height
612
- */
613
- computeExpectedHeight() {
614
- if (this.text && this.widthInPixels) {
615
- // Should abstract platform instead of using LastCreatedEngine
616
- const context = EngineStore.LastCreatedEngine?.createCanvas(0, 0).getContext("2d");
617
- if (context) {
618
- // This is a temporary context, no need to save/restore
619
- // eslint-disable-next-line babylonjs/require-context-save-before-apply-states
620
- this._applyStates(context);
621
- if (!this._fontOffset) {
622
- this._fontOffset = Control._GetFontOffset(context.font, this._host.getScene()?.getEngine());
531
+ _getTextMetricsWidth(textMetrics) {
532
+ if (textMetrics.actualBoundingBoxLeft !== undefined) {
533
+ return Math.abs(textMetrics.actualBoundingBoxLeft) + Math.abs(textMetrics.actualBoundingBoxRight);
623
534
  }
624
- const lines = this._lines
625
- ? this._lines
626
- : this._breakLines(this.widthInPixels - this._paddingLeftInPixels - this._paddingRightInPixels, this.heightInPixels - this._paddingTopInPixels - this._paddingBottomInPixels, context);
627
- return this._computeHeightForLinesOf(lines.length);
535
+ return textMetrics.width;
628
536
  }
629
- }
630
- return 0;
631
- }
632
- dispose() {
633
- super.dispose();
634
- this.onTextChangedObservable.clear();
635
- this._htmlElement?.remove();
636
- this._htmlElement = null;
637
- }
638
- }
639
- __decorate([
640
- serialize()
641
- ], TextBlock.prototype, "resizeToFit", null);
642
- __decorate([
643
- serialize()
644
- ], TextBlock.prototype, "textWrapping", null);
645
- __decorate([
646
- serialize()
647
- ], TextBlock.prototype, "text", null);
648
- __decorate([
649
- serialize()
650
- ], TextBlock.prototype, "textHorizontalAlignment", null);
651
- __decorate([
652
- serialize()
653
- ], TextBlock.prototype, "textVerticalAlignment", null);
654
- __decorate([
655
- serialize()
656
- ], TextBlock.prototype, "lineSpacing", null);
657
- __decorate([
658
- serialize()
659
- ], TextBlock.prototype, "outlineWidth", null);
660
- __decorate([
661
- serialize()
662
- ], TextBlock.prototype, "underline", null);
663
- __decorate([
664
- serialize()
665
- ], TextBlock.prototype, "lineThrough", null);
666
- __decorate([
667
- serialize()
668
- ], TextBlock.prototype, "applyOutlineToUnderline", null);
669
- __decorate([
670
- serialize()
671
- ], TextBlock.prototype, "outlineColor", null);
672
- __decorate([
673
- serialize()
674
- ], TextBlock.prototype, "wordDivider", null);
675
- __decorate([
676
- serialize()
677
- ], TextBlock.prototype, "forceResizeWidth", null);
537
+ _parseLineWordWrap(line = "", width, context) {
538
+ const lines = [];
539
+ const words = this.wordSplittingFunction ? this.wordSplittingFunction(line) : line.split(this._wordDivider);
540
+ let lineWidth = this._getTextMetricsWidth(context.measureText(line));
541
+ for (let n = 0; n < words.length; n++) {
542
+ const testLine = n > 0 ? line + this._wordDivider + words[n] : words[0];
543
+ const testWidth = this._getTextMetricsWidth(context.measureText(testLine));
544
+ if (testWidth > width && n > 0) {
545
+ lines.push({ text: line, width: lineWidth });
546
+ line = words[n];
547
+ lineWidth = this._getTextMetricsWidth(context.measureText(line));
548
+ }
549
+ else {
550
+ lineWidth = testWidth;
551
+ line = testLine;
552
+ }
553
+ }
554
+ lines.push({ text: line, width: lineWidth });
555
+ return lines;
556
+ }
557
+ _parseLineWordWrapEllipsis(line = "", width, height, context) {
558
+ const lines = this._parseLineWordWrap(line, width, context);
559
+ for (let n = 1; n <= lines.length; n++) {
560
+ const currentHeight = this._computeHeightForLinesOf(n);
561
+ if (currentHeight > height && n > 1) {
562
+ const lastLine = lines[n - 2];
563
+ const currentLine = lines[n - 1];
564
+ lines[n - 2] = this._parseLineEllipsis(lastLine.text + this._wordDivider + currentLine.text, width, context);
565
+ const linesToRemove = lines.length - n + 1;
566
+ for (let i = 0; i < linesToRemove; i++) {
567
+ lines.pop();
568
+ }
569
+ return lines;
570
+ }
571
+ }
572
+ return lines;
573
+ }
574
+ _renderLines(context) {
575
+ if (!this._fontOffset || !this._lines) {
576
+ return;
577
+ }
578
+ const height = this._currentMeasure.height;
579
+ let rootY = 0;
580
+ switch (this._textVerticalAlignment) {
581
+ case Control.VERTICAL_ALIGNMENT_TOP:
582
+ rootY = this._fontOffset.ascent;
583
+ break;
584
+ case Control.VERTICAL_ALIGNMENT_BOTTOM:
585
+ rootY = height - this._fontOffset.height * (this._lines.length - 1) - this._fontOffset.descent;
586
+ break;
587
+ case Control.VERTICAL_ALIGNMENT_CENTER:
588
+ rootY = this._fontOffset.ascent + (height - this._fontOffset.height * this._lines.length) / 2;
589
+ break;
590
+ }
591
+ rootY += this._currentMeasure.top;
592
+ for (let i = 0; i < this._lines.length; i++) {
593
+ const line = this._lines[i];
594
+ if (i !== 0 && this._lineSpacing.internalValue !== 0) {
595
+ if (this._lineSpacing.isPixel) {
596
+ rootY += this._lineSpacing.getValue(this._host);
597
+ }
598
+ else {
599
+ rootY = rootY + this._lineSpacing.getValue(this._host) * this._height.getValueInPixel(this._host, this._cachedParentMeasure.height);
600
+ }
601
+ }
602
+ this._drawText(line.text, line.width, rootY, context);
603
+ rootY += this._fontOffset.height;
604
+ }
605
+ }
606
+ _computeHeightForLinesOf(lineCount) {
607
+ let newHeight = this._paddingTopInPixels + this._paddingBottomInPixels + this._fontOffset.height * lineCount;
608
+ if (lineCount > 0 && this._lineSpacing.internalValue !== 0) {
609
+ let lineSpacing;
610
+ if (this._lineSpacing.isPixel) {
611
+ lineSpacing = this._lineSpacing.getValue(this._host);
612
+ }
613
+ else {
614
+ lineSpacing = this._lineSpacing.getValue(this._host) * this._height.getValueInPixel(this._host, this._cachedParentMeasure.height);
615
+ }
616
+ newHeight += (lineCount - 1) * lineSpacing;
617
+ }
618
+ return newHeight;
619
+ }
620
+ isDimensionFullyDefined(dim) {
621
+ if (this.resizeToFit) {
622
+ return true;
623
+ }
624
+ return super.isDimensionFullyDefined(dim);
625
+ }
626
+ /**
627
+ * Given a width constraint applied on the text block, find the expected height
628
+ * @returns expected height
629
+ */
630
+ computeExpectedHeight() {
631
+ if (this.text && this.widthInPixels) {
632
+ // Should abstract platform instead of using LastCreatedEngine
633
+ const context = EngineStore.LastCreatedEngine?.createCanvas(0, 0).getContext("2d");
634
+ if (context) {
635
+ // This is a temporary context, no need to save/restore
636
+ // eslint-disable-next-line babylonjs/require-context-save-before-apply-states
637
+ this._applyStates(context);
638
+ if (!this._fontOffset) {
639
+ this._fontOffset = Control._GetFontOffset(context.font, this._host.getScene()?.getEngine());
640
+ }
641
+ const lines = this._lines
642
+ ? this._lines
643
+ : this._breakLines(this.widthInPixels - this._paddingLeftInPixels - this._paddingRightInPixels, this.heightInPixels - this._paddingTopInPixels - this._paddingBottomInPixels, context);
644
+ return this._computeHeightForLinesOf(lines.length);
645
+ }
646
+ }
647
+ return 0;
648
+ }
649
+ dispose() {
650
+ super.dispose();
651
+ this.onTextChangedObservable.clear();
652
+ this._htmlElement?.remove();
653
+ this._htmlElement = null;
654
+ }
655
+ },
656
+ (() => {
657
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
658
+ _get_resizeToFit_decorators = [serialize()];
659
+ _get_textWrapping_decorators = [serialize()];
660
+ _get_text_decorators = [serialize()];
661
+ _get_textHorizontalAlignment_decorators = [serialize()];
662
+ _get_textVerticalAlignment_decorators = [serialize()];
663
+ _set_lineSpacing_decorators = [serialize()];
664
+ _get_outlineWidth_decorators = [serialize()];
665
+ _get_underline_decorators = [serialize()];
666
+ _get_lineThrough_decorators = [serialize()];
667
+ _get_applyOutlineToUnderline_decorators = [serialize()];
668
+ _get_outlineColor_decorators = [serialize()];
669
+ _get_wordDivider_decorators = [serialize()];
670
+ _get_forceResizeWidth_decorators = [serialize()];
671
+ __esDecorate(_a, null, _get_resizeToFit_decorators, { kind: "getter", name: "resizeToFit", static: false, private: false, access: { has: obj => "resizeToFit" in obj, get: obj => obj.resizeToFit }, metadata: _metadata }, null, _instanceExtraInitializers);
672
+ __esDecorate(_a, null, _get_textWrapping_decorators, { kind: "getter", name: "textWrapping", static: false, private: false, access: { has: obj => "textWrapping" in obj, get: obj => obj.textWrapping }, metadata: _metadata }, null, _instanceExtraInitializers);
673
+ __esDecorate(_a, null, _get_text_decorators, { kind: "getter", name: "text", static: false, private: false, access: { has: obj => "text" in obj, get: obj => obj.text }, metadata: _metadata }, null, _instanceExtraInitializers);
674
+ __esDecorate(_a, null, _get_textHorizontalAlignment_decorators, { kind: "getter", name: "textHorizontalAlignment", static: false, private: false, access: { has: obj => "textHorizontalAlignment" in obj, get: obj => obj.textHorizontalAlignment }, metadata: _metadata }, null, _instanceExtraInitializers);
675
+ __esDecorate(_a, null, _get_textVerticalAlignment_decorators, { kind: "getter", name: "textVerticalAlignment", static: false, private: false, access: { has: obj => "textVerticalAlignment" in obj, get: obj => obj.textVerticalAlignment }, metadata: _metadata }, null, _instanceExtraInitializers);
676
+ __esDecorate(_a, null, _set_lineSpacing_decorators, { kind: "setter", name: "lineSpacing", static: false, private: false, access: { has: obj => "lineSpacing" in obj, set: (obj, value) => { obj.lineSpacing = value; } }, metadata: _metadata }, null, _instanceExtraInitializers);
677
+ __esDecorate(_a, null, _get_outlineWidth_decorators, { kind: "getter", name: "outlineWidth", static: false, private: false, access: { has: obj => "outlineWidth" in obj, get: obj => obj.outlineWidth }, metadata: _metadata }, null, _instanceExtraInitializers);
678
+ __esDecorate(_a, null, _get_underline_decorators, { kind: "getter", name: "underline", static: false, private: false, access: { has: obj => "underline" in obj, get: obj => obj.underline }, metadata: _metadata }, null, _instanceExtraInitializers);
679
+ __esDecorate(_a, null, _get_lineThrough_decorators, { kind: "getter", name: "lineThrough", static: false, private: false, access: { has: obj => "lineThrough" in obj, get: obj => obj.lineThrough }, metadata: _metadata }, null, _instanceExtraInitializers);
680
+ __esDecorate(_a, null, _get_applyOutlineToUnderline_decorators, { kind: "getter", name: "applyOutlineToUnderline", static: false, private: false, access: { has: obj => "applyOutlineToUnderline" in obj, get: obj => obj.applyOutlineToUnderline }, metadata: _metadata }, null, _instanceExtraInitializers);
681
+ __esDecorate(_a, null, _get_outlineColor_decorators, { kind: "getter", name: "outlineColor", static: false, private: false, access: { has: obj => "outlineColor" in obj, get: obj => obj.outlineColor }, metadata: _metadata }, null, _instanceExtraInitializers);
682
+ __esDecorate(_a, null, _get_wordDivider_decorators, { kind: "getter", name: "wordDivider", static: false, private: false, access: { has: obj => "wordDivider" in obj, get: obj => obj.wordDivider }, metadata: _metadata }, null, _instanceExtraInitializers);
683
+ __esDecorate(_a, null, _get_forceResizeWidth_decorators, { kind: "getter", name: "forceResizeWidth", static: false, private: false, access: { has: obj => "forceResizeWidth" in obj, get: obj => obj.forceResizeWidth }, metadata: _metadata }, null, _instanceExtraInitializers);
684
+ if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
685
+ })(),
686
+ _a;
687
+ })();
688
+ export { TextBlock };
678
689
  let _Registered = false;
679
690
  /**
680
691
  * Registers the TextBlock class with the type store for serialization support.