@opentui/core 0.1.13 → 0.1.15
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/3d.js +3 -3
- package/3d.js.map +3 -3
- package/Renderable.d.ts +50 -18
- package/animation/Timeline.d.ts +11 -0
- package/buffer.d.ts +11 -27
- package/console.d.ts +2 -2
- package/{index-4gez9k7q.js → index-sw194bbj.js} +749 -846
- package/index-sw194bbj.js.map +36 -0
- package/index.js +1069 -137
- package/index.js.map +14 -11
- package/lib/KeyHandler.d.ts +6 -1
- package/lib/selection.d.ts +31 -38
- package/lib/styled-text.d.ts +0 -3
- package/package.json +7 -7
- package/renderables/ASCIIFont.d.ts +4 -2
- package/renderables/Box.d.ts +7 -1
- package/renderables/ScrollBar.d.ts +77 -0
- package/renderables/ScrollBox.d.ts +82 -0
- package/renderables/Slider.d.ts +31 -0
- package/renderables/Text.d.ts +22 -5
- package/renderables/composition/vnode.d.ts +13 -6
- package/renderables/index.d.ts +2 -0
- package/renderer.d.ts +10 -6
- package/text-buffer.d.ts +9 -10
- package/types.d.ts +24 -13
- package/zig.d.ts +24 -24
- package/index-4gez9k7q.js.map +0 -36
package/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
Gutter,
|
|
12
12
|
KeyHandler,
|
|
13
13
|
LayoutEvents,
|
|
14
|
+
LogLevel,
|
|
14
15
|
MeasureMode,
|
|
15
16
|
MouseButton,
|
|
16
17
|
MouseEvent,
|
|
@@ -26,7 +27,6 @@ import {
|
|
|
26
27
|
TerminalConsole,
|
|
27
28
|
TextAttributes,
|
|
28
29
|
TextBuffer,
|
|
29
|
-
TextSelectionHelper,
|
|
30
30
|
TrackedNode,
|
|
31
31
|
bg,
|
|
32
32
|
bgBlack,
|
|
@@ -51,6 +51,7 @@ import {
|
|
|
51
51
|
brightWhite,
|
|
52
52
|
brightYellow,
|
|
53
53
|
capture,
|
|
54
|
+
convertGlobalToLocalSelection,
|
|
54
55
|
coordinateToCharacterIndex,
|
|
55
56
|
createCliRenderer,
|
|
56
57
|
createTextAttributes,
|
|
@@ -74,9 +75,11 @@ import {
|
|
|
74
75
|
isDimensionType,
|
|
75
76
|
isFlexBasisType,
|
|
76
77
|
isMarginType,
|
|
78
|
+
isOverflowType,
|
|
77
79
|
isPaddingType,
|
|
78
80
|
isPositionType,
|
|
79
|
-
|
|
81
|
+
isPositionTypeType,
|
|
82
|
+
isRenderable,
|
|
80
83
|
isSizeType,
|
|
81
84
|
isVNode,
|
|
82
85
|
isValidPercentage,
|
|
@@ -115,7 +118,7 @@ import {
|
|
|
115
118
|
white,
|
|
116
119
|
wrapWithDelegates,
|
|
117
120
|
yellow
|
|
118
|
-
} from "./index-
|
|
121
|
+
} from "./index-sw194bbj.js";
|
|
119
122
|
// src/post/filters.ts
|
|
120
123
|
function applyScanlines(buffer, strength = 0.8, step = 2) {
|
|
121
124
|
const width = buffer.width;
|
|
@@ -958,6 +961,7 @@ class Timeline {
|
|
|
958
961
|
autoplay;
|
|
959
962
|
onComplete;
|
|
960
963
|
onPause;
|
|
964
|
+
stateChangeListeners = [];
|
|
961
965
|
constructor(options = {}) {
|
|
962
966
|
this.duration = options.duration || 1000;
|
|
963
967
|
this.loop = options.loop === true;
|
|
@@ -965,6 +969,17 @@ class Timeline {
|
|
|
965
969
|
this.onComplete = options.onComplete;
|
|
966
970
|
this.onPause = options.onPause;
|
|
967
971
|
}
|
|
972
|
+
addStateChangeListener(listener) {
|
|
973
|
+
this.stateChangeListeners.push(listener);
|
|
974
|
+
}
|
|
975
|
+
removeStateChangeListener(listener) {
|
|
976
|
+
this.stateChangeListeners = this.stateChangeListeners.filter((l) => l !== listener);
|
|
977
|
+
}
|
|
978
|
+
notifyStateChange() {
|
|
979
|
+
for (const listener of this.stateChangeListeners) {
|
|
980
|
+
listener(this);
|
|
981
|
+
}
|
|
982
|
+
}
|
|
968
983
|
add(target, properties, startTime = 0) {
|
|
969
984
|
const resolvedStartTime = typeof startTime === "string" ? 0 : startTime;
|
|
970
985
|
const animationProperties = {};
|
|
@@ -1036,6 +1051,7 @@ class Timeline {
|
|
|
1036
1051
|
}
|
|
1037
1052
|
});
|
|
1038
1053
|
this.isPlaying = true;
|
|
1054
|
+
this.notifyStateChange();
|
|
1039
1055
|
return this;
|
|
1040
1056
|
}
|
|
1041
1057
|
pause() {
|
|
@@ -1046,6 +1062,7 @@ class Timeline {
|
|
|
1046
1062
|
if (this.onPause) {
|
|
1047
1063
|
this.onPause();
|
|
1048
1064
|
}
|
|
1065
|
+
this.notifyStateChange();
|
|
1049
1066
|
return this;
|
|
1050
1067
|
}
|
|
1051
1068
|
resetItems() {
|
|
@@ -1071,6 +1088,7 @@ class Timeline {
|
|
|
1071
1088
|
this.currentTime = 0;
|
|
1072
1089
|
this.isPlaying = true;
|
|
1073
1090
|
this.resetItems();
|
|
1091
|
+
this.notifyStateChange();
|
|
1074
1092
|
return this;
|
|
1075
1093
|
}
|
|
1076
1094
|
update(deltaTime) {
|
|
@@ -1103,23 +1121,75 @@ class Timeline {
|
|
|
1103
1121
|
if (this.onComplete) {
|
|
1104
1122
|
this.onComplete();
|
|
1105
1123
|
}
|
|
1124
|
+
this.notifyStateChange();
|
|
1106
1125
|
}
|
|
1107
1126
|
}
|
|
1108
1127
|
}
|
|
1109
1128
|
|
|
1110
1129
|
class TimelineEngine {
|
|
1111
1130
|
timelines = new Set;
|
|
1131
|
+
renderer = null;
|
|
1132
|
+
frameCallback = null;
|
|
1133
|
+
isLive = false;
|
|
1112
1134
|
defaults = {
|
|
1113
1135
|
frameRate: 60
|
|
1114
1136
|
};
|
|
1137
|
+
attach(renderer) {
|
|
1138
|
+
if (this.renderer) {
|
|
1139
|
+
this.detach();
|
|
1140
|
+
}
|
|
1141
|
+
this.renderer = renderer;
|
|
1142
|
+
this.frameCallback = async (deltaTime) => {
|
|
1143
|
+
this.update(deltaTime);
|
|
1144
|
+
};
|
|
1145
|
+
renderer.setFrameCallback(this.frameCallback);
|
|
1146
|
+
}
|
|
1147
|
+
detach() {
|
|
1148
|
+
if (this.renderer && this.frameCallback) {
|
|
1149
|
+
this.renderer.removeFrameCallback(this.frameCallback);
|
|
1150
|
+
if (this.isLive) {
|
|
1151
|
+
this.renderer.dropLive();
|
|
1152
|
+
this.isLive = false;
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
this.renderer = null;
|
|
1156
|
+
this.frameCallback = null;
|
|
1157
|
+
}
|
|
1158
|
+
updateLiveState() {
|
|
1159
|
+
if (!this.renderer)
|
|
1160
|
+
return;
|
|
1161
|
+
const hasRunningTimelines = Array.from(this.timelines).some((timeline) => !timeline.synced && timeline.isPlaying && !timeline.isComplete);
|
|
1162
|
+
if (hasRunningTimelines && !this.isLive) {
|
|
1163
|
+
this.renderer.requestLive();
|
|
1164
|
+
this.isLive = true;
|
|
1165
|
+
} else if (!hasRunningTimelines && this.isLive) {
|
|
1166
|
+
this.renderer.dropLive();
|
|
1167
|
+
this.isLive = false;
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
onTimelineStateChange = (timeline) => {
|
|
1171
|
+
this.updateLiveState();
|
|
1172
|
+
};
|
|
1115
1173
|
register(timeline) {
|
|
1116
|
-
this.timelines.
|
|
1174
|
+
if (!this.timelines.has(timeline)) {
|
|
1175
|
+
this.timelines.add(timeline);
|
|
1176
|
+
timeline.addStateChangeListener(this.onTimelineStateChange);
|
|
1177
|
+
this.updateLiveState();
|
|
1178
|
+
}
|
|
1117
1179
|
}
|
|
1118
1180
|
unregister(timeline) {
|
|
1119
|
-
this.timelines.
|
|
1181
|
+
if (this.timelines.has(timeline)) {
|
|
1182
|
+
this.timelines.delete(timeline);
|
|
1183
|
+
timeline.removeStateChangeListener(this.onTimelineStateChange);
|
|
1184
|
+
this.updateLiveState();
|
|
1185
|
+
}
|
|
1120
1186
|
}
|
|
1121
1187
|
clear() {
|
|
1188
|
+
for (const timeline of this.timelines) {
|
|
1189
|
+
timeline.removeStateChangeListener(this.onTimelineStateChange);
|
|
1190
|
+
}
|
|
1122
1191
|
this.timelines.clear();
|
|
1192
|
+
this.updateLiveState();
|
|
1123
1193
|
}
|
|
1124
1194
|
update(deltaTime) {
|
|
1125
1195
|
for (const timeline of this.timelines) {
|
|
@@ -1198,7 +1268,7 @@ class BoxRenderable extends Renderable {
|
|
|
1198
1268
|
set customBorderChars(value) {
|
|
1199
1269
|
this._customBorderCharsObj = value;
|
|
1200
1270
|
this._customBorderChars = value ? borderCharsToArray(value) : undefined;
|
|
1201
|
-
this.
|
|
1271
|
+
this.requestRender();
|
|
1202
1272
|
}
|
|
1203
1273
|
get backgroundColor() {
|
|
1204
1274
|
return this._backgroundColor;
|
|
@@ -1207,7 +1277,7 @@ class BoxRenderable extends Renderable {
|
|
|
1207
1277
|
const newColor = parseColor(value ?? this._defaultOptions.backgroundColor);
|
|
1208
1278
|
if (this._backgroundColor !== newColor) {
|
|
1209
1279
|
this._backgroundColor = newColor;
|
|
1210
|
-
this.
|
|
1280
|
+
this.requestRender();
|
|
1211
1281
|
}
|
|
1212
1282
|
}
|
|
1213
1283
|
get border() {
|
|
@@ -1218,7 +1288,7 @@ class BoxRenderable extends Renderable {
|
|
|
1218
1288
|
this._border = value;
|
|
1219
1289
|
this.borderSides = getBorderSides(value);
|
|
1220
1290
|
this.applyYogaBorders();
|
|
1221
|
-
this.
|
|
1291
|
+
this.requestRender();
|
|
1222
1292
|
}
|
|
1223
1293
|
}
|
|
1224
1294
|
get borderStyle() {
|
|
@@ -1229,7 +1299,7 @@ class BoxRenderable extends Renderable {
|
|
|
1229
1299
|
if (this._borderStyle !== _value) {
|
|
1230
1300
|
this._borderStyle = _value;
|
|
1231
1301
|
this._customBorderChars = undefined;
|
|
1232
|
-
this.
|
|
1302
|
+
this.requestRender();
|
|
1233
1303
|
}
|
|
1234
1304
|
}
|
|
1235
1305
|
get borderColor() {
|
|
@@ -1239,7 +1309,7 @@ class BoxRenderable extends Renderable {
|
|
|
1239
1309
|
const newColor = parseColor(value ?? this._defaultOptions.borderColor);
|
|
1240
1310
|
if (this._borderColor !== newColor) {
|
|
1241
1311
|
this._borderColor = newColor;
|
|
1242
|
-
this.
|
|
1312
|
+
this.requestRender();
|
|
1243
1313
|
}
|
|
1244
1314
|
}
|
|
1245
1315
|
get focusedBorderColor() {
|
|
@@ -1250,7 +1320,7 @@ class BoxRenderable extends Renderable {
|
|
|
1250
1320
|
if (this._focusedBorderColor !== newColor) {
|
|
1251
1321
|
this._focusedBorderColor = newColor;
|
|
1252
1322
|
if (this._focused) {
|
|
1253
|
-
this.
|
|
1323
|
+
this.requestRender();
|
|
1254
1324
|
}
|
|
1255
1325
|
}
|
|
1256
1326
|
}
|
|
@@ -1260,7 +1330,7 @@ class BoxRenderable extends Renderable {
|
|
|
1260
1330
|
set title(value) {
|
|
1261
1331
|
if (this._title !== value) {
|
|
1262
1332
|
this._title = value;
|
|
1263
|
-
this.
|
|
1333
|
+
this.requestRender();
|
|
1264
1334
|
}
|
|
1265
1335
|
}
|
|
1266
1336
|
get titleAlignment() {
|
|
@@ -1269,7 +1339,7 @@ class BoxRenderable extends Renderable {
|
|
|
1269
1339
|
set titleAlignment(value) {
|
|
1270
1340
|
if (this._titleAlignment !== value) {
|
|
1271
1341
|
this._titleAlignment = value;
|
|
1272
|
-
this.
|
|
1342
|
+
this.requestRender();
|
|
1273
1343
|
}
|
|
1274
1344
|
}
|
|
1275
1345
|
renderSelf(buffer) {
|
|
@@ -1289,13 +1359,29 @@ class BoxRenderable extends Renderable {
|
|
|
1289
1359
|
titleAlignment: this._titleAlignment
|
|
1290
1360
|
});
|
|
1291
1361
|
}
|
|
1362
|
+
getScissorRect() {
|
|
1363
|
+
const baseRect = super.getScissorRect();
|
|
1364
|
+
if (!this.borderSides.top && !this.borderSides.right && !this.borderSides.bottom && !this.borderSides.left) {
|
|
1365
|
+
return baseRect;
|
|
1366
|
+
}
|
|
1367
|
+
const leftInset = this.borderSides.left ? 1 : 0;
|
|
1368
|
+
const rightInset = this.borderSides.right ? 1 : 0;
|
|
1369
|
+
const topInset = this.borderSides.top ? 1 : 0;
|
|
1370
|
+
const bottomInset = this.borderSides.bottom ? 1 : 0;
|
|
1371
|
+
return {
|
|
1372
|
+
x: baseRect.x + leftInset,
|
|
1373
|
+
y: baseRect.y + topInset,
|
|
1374
|
+
width: Math.max(0, baseRect.width - leftInset - rightInset),
|
|
1375
|
+
height: Math.max(0, baseRect.height - topInset - bottomInset)
|
|
1376
|
+
};
|
|
1377
|
+
}
|
|
1292
1378
|
applyYogaBorders() {
|
|
1293
1379
|
const node = this.layoutNode.yogaNode;
|
|
1294
1380
|
node.setBorder(Edge.Left, this.borderSides.left ? 1 : 0);
|
|
1295
1381
|
node.setBorder(Edge.Right, this.borderSides.right ? 1 : 0);
|
|
1296
1382
|
node.setBorder(Edge.Top, this.borderSides.top ? 1 : 0);
|
|
1297
1383
|
node.setBorder(Edge.Bottom, this.borderSides.bottom ? 1 : 0);
|
|
1298
|
-
this.
|
|
1384
|
+
this.requestRender();
|
|
1299
1385
|
}
|
|
1300
1386
|
applyYogaGap(options) {
|
|
1301
1387
|
const node = this.layoutNode.yogaNode;
|
|
@@ -1312,19 +1398,19 @@ class BoxRenderable extends Renderable {
|
|
|
1312
1398
|
set gap(gap) {
|
|
1313
1399
|
if (isGapType(gap)) {
|
|
1314
1400
|
this.layoutNode.yogaNode.setGap(Gutter.All, gap);
|
|
1315
|
-
this.
|
|
1401
|
+
this.requestRender();
|
|
1316
1402
|
}
|
|
1317
1403
|
}
|
|
1318
1404
|
set rowGap(rowGap) {
|
|
1319
1405
|
if (isGapType(rowGap)) {
|
|
1320
1406
|
this.layoutNode.yogaNode.setGap(Gutter.Row, rowGap);
|
|
1321
|
-
this.
|
|
1407
|
+
this.requestRender();
|
|
1322
1408
|
}
|
|
1323
1409
|
}
|
|
1324
1410
|
set columnGap(columnGap) {
|
|
1325
1411
|
if (isGapType(columnGap)) {
|
|
1326
1412
|
this.layoutNode.yogaNode.setGap(Gutter.Column, columnGap);
|
|
1327
|
-
this.
|
|
1413
|
+
this.requestRender();
|
|
1328
1414
|
}
|
|
1329
1415
|
}
|
|
1330
1416
|
}
|
|
@@ -1336,7 +1422,8 @@ class FrameBufferRenderable extends Renderable {
|
|
|
1336
1422
|
super(ctx, options);
|
|
1337
1423
|
this.respectAlpha = options.respectAlpha || false;
|
|
1338
1424
|
this.frameBuffer = OptimizedBuffer.create(options.width, options.height, this._ctx.widthMethod, {
|
|
1339
|
-
respectAlpha: this.respectAlpha
|
|
1425
|
+
respectAlpha: this.respectAlpha,
|
|
1426
|
+
id: options.id || `framebufferrenderable-${this.id}`
|
|
1340
1427
|
});
|
|
1341
1428
|
}
|
|
1342
1429
|
onResize(width, height) {
|
|
@@ -1345,7 +1432,7 @@ class FrameBufferRenderable extends Renderable {
|
|
|
1345
1432
|
}
|
|
1346
1433
|
this.frameBuffer.resize(width, height);
|
|
1347
1434
|
super.onResize(width, height);
|
|
1348
|
-
this.
|
|
1435
|
+
this.requestRender();
|
|
1349
1436
|
}
|
|
1350
1437
|
renderSelf(buffer) {
|
|
1351
1438
|
if (!this.visible)
|
|
@@ -1360,96 +1447,136 @@ class FrameBufferRenderable extends Renderable {
|
|
|
1360
1447
|
// src/renderables/Text.ts
|
|
1361
1448
|
class TextRenderable extends Renderable {
|
|
1362
1449
|
selectable = true;
|
|
1363
|
-
_text
|
|
1450
|
+
_text;
|
|
1364
1451
|
_defaultFg;
|
|
1365
1452
|
_defaultBg;
|
|
1366
1453
|
_defaultAttributes;
|
|
1367
1454
|
_selectionBg;
|
|
1368
1455
|
_selectionFg;
|
|
1369
|
-
|
|
1456
|
+
lastLocalSelection = null;
|
|
1370
1457
|
textBuffer;
|
|
1371
|
-
_plainText = "";
|
|
1372
1458
|
_lineInfo = { lineStarts: [], lineWidths: [] };
|
|
1459
|
+
_defaultOptions = {
|
|
1460
|
+
content: "",
|
|
1461
|
+
fg: RGBA.fromValues(1, 1, 1, 1),
|
|
1462
|
+
bg: RGBA.fromValues(0, 0, 0, 0),
|
|
1463
|
+
selectionBg: undefined,
|
|
1464
|
+
selectionFg: undefined,
|
|
1465
|
+
selectable: true,
|
|
1466
|
+
attributes: 0
|
|
1467
|
+
};
|
|
1373
1468
|
constructor(ctx, options) {
|
|
1374
1469
|
super(ctx, options);
|
|
1375
|
-
|
|
1376
|
-
const
|
|
1377
|
-
this._text =
|
|
1378
|
-
this._defaultFg =
|
|
1379
|
-
this._defaultBg =
|
|
1380
|
-
this._defaultAttributes = options.attributes ??
|
|
1381
|
-
this._selectionBg = options.selectionBg ? parseColor(options.selectionBg) :
|
|
1382
|
-
this._selectionFg = options.selectionFg ? parseColor(options.selectionFg) :
|
|
1383
|
-
this.selectable = options.selectable ??
|
|
1470
|
+
const content = options.content ?? this._defaultOptions.content;
|
|
1471
|
+
const styledText = typeof content === "string" ? stringToStyledText(content) : content;
|
|
1472
|
+
this._text = styledText;
|
|
1473
|
+
this._defaultFg = parseColor(options.fg ?? this._defaultOptions.fg);
|
|
1474
|
+
this._defaultBg = parseColor(options.bg ?? this._defaultOptions.bg);
|
|
1475
|
+
this._defaultAttributes = options.attributes ?? this._defaultOptions.attributes;
|
|
1476
|
+
this._selectionBg = options.selectionBg ? parseColor(options.selectionBg) : this._defaultOptions.selectionBg;
|
|
1477
|
+
this._selectionFg = options.selectionFg ? parseColor(options.selectionFg) : this._defaultOptions.selectionFg;
|
|
1478
|
+
this.selectable = options.selectable ?? this._defaultOptions.selectable;
|
|
1384
1479
|
this.textBuffer = TextBuffer.create(64, this._ctx.widthMethod);
|
|
1385
1480
|
this.textBuffer.setDefaultFg(this._defaultFg);
|
|
1386
1481
|
this.textBuffer.setDefaultBg(this._defaultBg);
|
|
1387
1482
|
this.textBuffer.setDefaultAttributes(this._defaultAttributes);
|
|
1388
1483
|
this.setupMeasureFunc();
|
|
1389
|
-
this.updateTextInfo();
|
|
1484
|
+
this.updateTextInfo(styledText);
|
|
1390
1485
|
}
|
|
1391
1486
|
get content() {
|
|
1392
1487
|
return this._text;
|
|
1393
1488
|
}
|
|
1394
1489
|
set content(value) {
|
|
1395
|
-
|
|
1396
|
-
this.
|
|
1490
|
+
const styledText = typeof value === "string" ? stringToStyledText(value) : value;
|
|
1491
|
+
this._text = styledText;
|
|
1492
|
+
this.updateTextInfo(styledText);
|
|
1397
1493
|
}
|
|
1398
1494
|
get fg() {
|
|
1399
1495
|
return this._defaultFg;
|
|
1400
1496
|
}
|
|
1401
1497
|
set fg(value) {
|
|
1402
|
-
|
|
1403
|
-
|
|
1498
|
+
const newColor = parseColor(value ?? this._defaultOptions.fg);
|
|
1499
|
+
if (this._defaultFg !== newColor) {
|
|
1500
|
+
this._defaultFg = newColor;
|
|
1404
1501
|
this.textBuffer.setDefaultFg(this._defaultFg);
|
|
1405
|
-
this.
|
|
1502
|
+
this.requestRender();
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
get selectionBg() {
|
|
1506
|
+
return this._selectionBg;
|
|
1507
|
+
}
|
|
1508
|
+
set selectionBg(value) {
|
|
1509
|
+
const newColor = value ? parseColor(value) : this._defaultOptions.selectionBg;
|
|
1510
|
+
if (this._selectionBg !== newColor) {
|
|
1511
|
+
this._selectionBg = newColor;
|
|
1512
|
+
if (this.lastLocalSelection) {
|
|
1513
|
+
this.updateLocalSelection(this.lastLocalSelection);
|
|
1514
|
+
}
|
|
1515
|
+
this.requestRender();
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
get selectionFg() {
|
|
1519
|
+
return this._selectionFg;
|
|
1520
|
+
}
|
|
1521
|
+
set selectionFg(value) {
|
|
1522
|
+
const newColor = value ? parseColor(value) : this._defaultOptions.selectionFg;
|
|
1523
|
+
if (this._selectionFg !== newColor) {
|
|
1524
|
+
this._selectionFg = newColor;
|
|
1525
|
+
if (this.lastLocalSelection) {
|
|
1526
|
+
this.updateLocalSelection(this.lastLocalSelection);
|
|
1527
|
+
}
|
|
1528
|
+
this.requestRender();
|
|
1406
1529
|
}
|
|
1407
1530
|
}
|
|
1408
1531
|
get bg() {
|
|
1409
1532
|
return this._defaultBg;
|
|
1410
1533
|
}
|
|
1411
1534
|
set bg(value) {
|
|
1412
|
-
|
|
1413
|
-
|
|
1535
|
+
const newColor = parseColor(value ?? this._defaultOptions.bg);
|
|
1536
|
+
if (this._defaultBg !== newColor) {
|
|
1537
|
+
this._defaultBg = newColor;
|
|
1414
1538
|
this.textBuffer.setDefaultBg(this._defaultBg);
|
|
1415
|
-
this.
|
|
1539
|
+
this.requestRender();
|
|
1416
1540
|
}
|
|
1417
1541
|
}
|
|
1418
1542
|
get attributes() {
|
|
1419
1543
|
return this._defaultAttributes;
|
|
1420
1544
|
}
|
|
1421
1545
|
set attributes(value) {
|
|
1422
|
-
this._defaultAttributes
|
|
1423
|
-
|
|
1424
|
-
|
|
1546
|
+
if (this._defaultAttributes !== value) {
|
|
1547
|
+
this._defaultAttributes = value;
|
|
1548
|
+
this.textBuffer.setDefaultAttributes(this._defaultAttributes);
|
|
1549
|
+
this.requestRender();
|
|
1550
|
+
}
|
|
1425
1551
|
}
|
|
1426
1552
|
onResize(width, height) {
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1553
|
+
if (this.lastLocalSelection) {
|
|
1554
|
+
const changed = this.updateLocalSelection(this.lastLocalSelection);
|
|
1555
|
+
if (changed) {
|
|
1556
|
+
this.requestRender();
|
|
1557
|
+
}
|
|
1431
1558
|
}
|
|
1432
1559
|
}
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
} else {
|
|
1438
|
-
this.textBuffer.resetSelection();
|
|
1560
|
+
updateLocalSelection(localSelection) {
|
|
1561
|
+
if (!localSelection?.isActive) {
|
|
1562
|
+
this.textBuffer.resetLocalSelection();
|
|
1563
|
+
return true;
|
|
1439
1564
|
}
|
|
1565
|
+
return this.textBuffer.setLocalSelection(localSelection.anchorX, localSelection.anchorY, localSelection.focusX, localSelection.focusY, this._selectionBg, this._selectionFg);
|
|
1440
1566
|
}
|
|
1441
|
-
updateTextInfo() {
|
|
1442
|
-
this.
|
|
1443
|
-
this.updateTextBuffer();
|
|
1567
|
+
updateTextInfo(styledText) {
|
|
1568
|
+
this.updateTextBuffer(styledText);
|
|
1444
1569
|
const lineInfo = this.textBuffer.lineInfo;
|
|
1445
1570
|
this._lineInfo.lineStarts = lineInfo.lineStarts;
|
|
1446
1571
|
this._lineInfo.lineWidths = lineInfo.lineWidths;
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1572
|
+
if (this.lastLocalSelection) {
|
|
1573
|
+
const changed = this.updateLocalSelection(this.lastLocalSelection);
|
|
1574
|
+
if (changed) {
|
|
1575
|
+
this.requestRender();
|
|
1576
|
+
}
|
|
1450
1577
|
}
|
|
1451
1578
|
this.layoutNode.yogaNode.markDirty();
|
|
1452
|
-
this.
|
|
1579
|
+
this.requestRender();
|
|
1453
1580
|
}
|
|
1454
1581
|
setupMeasureFunc() {
|
|
1455
1582
|
const measureFunc = (width, widthMode, height, heightMode) => {
|
|
@@ -1475,27 +1602,32 @@ class TextRenderable extends Renderable {
|
|
|
1475
1602
|
this.layoutNode.yogaNode.setMeasureFunc(measureFunc);
|
|
1476
1603
|
}
|
|
1477
1604
|
shouldStartSelection(x, y) {
|
|
1478
|
-
|
|
1605
|
+
if (!this.selectable)
|
|
1606
|
+
return false;
|
|
1607
|
+
const localX = x - this.x;
|
|
1608
|
+
const localY = y - this.y;
|
|
1609
|
+
return localX >= 0 && localX < this.width && localY >= 0 && localY < this.height;
|
|
1479
1610
|
}
|
|
1480
1611
|
onSelectionChanged(selection) {
|
|
1481
|
-
const
|
|
1612
|
+
const localSelection = convertGlobalToLocalSelection(selection, this.x, this.y);
|
|
1613
|
+
this.lastLocalSelection = localSelection;
|
|
1614
|
+
const changed = this.updateLocalSelection(localSelection);
|
|
1482
1615
|
if (changed) {
|
|
1483
|
-
this.
|
|
1484
|
-
this.needsUpdate();
|
|
1616
|
+
this.requestRender();
|
|
1485
1617
|
}
|
|
1486
|
-
return this.
|
|
1618
|
+
return this.hasSelection();
|
|
1487
1619
|
}
|
|
1488
1620
|
getSelectedText() {
|
|
1489
|
-
|
|
1490
|
-
if (!selection)
|
|
1491
|
-
return "";
|
|
1492
|
-
return this._plainText.slice(selection.start, selection.end);
|
|
1621
|
+
return this.textBuffer.getSelectedText();
|
|
1493
1622
|
}
|
|
1494
1623
|
hasSelection() {
|
|
1495
|
-
return this.
|
|
1624
|
+
return this.textBuffer.hasSelection();
|
|
1625
|
+
}
|
|
1626
|
+
getSelection() {
|
|
1627
|
+
return this.textBuffer.getSelection();
|
|
1496
1628
|
}
|
|
1497
|
-
updateTextBuffer() {
|
|
1498
|
-
this.textBuffer.setStyledText(
|
|
1629
|
+
updateTextBuffer(styledText) {
|
|
1630
|
+
this.textBuffer.setStyledText(styledText);
|
|
1499
1631
|
}
|
|
1500
1632
|
renderSelf(buffer) {
|
|
1501
1633
|
if (this.textBuffer.ptr) {
|
|
@@ -1522,6 +1654,7 @@ class ASCIIFontRenderable extends FrameBufferRenderable {
|
|
|
1522
1654
|
_bg;
|
|
1523
1655
|
_selectionBg;
|
|
1524
1656
|
_selectionFg;
|
|
1657
|
+
lastLocalSelection = null;
|
|
1525
1658
|
selectionHelper;
|
|
1526
1659
|
constructor(ctx, options) {
|
|
1527
1660
|
const font = options.font || "tiny";
|
|
@@ -1540,7 +1673,7 @@ class ASCIIFontRenderable extends FrameBufferRenderable {
|
|
|
1540
1673
|
this._selectionBg = options.selectionBg ? parseColor(options.selectionBg) : undefined;
|
|
1541
1674
|
this._selectionFg = options.selectionFg ? parseColor(options.selectionFg) : undefined;
|
|
1542
1675
|
this.selectable = options.selectable ?? true;
|
|
1543
|
-
this.selectionHelper = new ASCIIFontSelectionHelper(() => this.
|
|
1676
|
+
this.selectionHelper = new ASCIIFontSelectionHelper(() => this._text, () => this._font);
|
|
1544
1677
|
this.renderFontToBuffer();
|
|
1545
1678
|
}
|
|
1546
1679
|
get text() {
|
|
@@ -1549,9 +1682,11 @@ class ASCIIFontRenderable extends FrameBufferRenderable {
|
|
|
1549
1682
|
set text(value) {
|
|
1550
1683
|
this._text = value;
|
|
1551
1684
|
this.updateDimensions();
|
|
1552
|
-
|
|
1685
|
+
if (this.lastLocalSelection) {
|
|
1686
|
+
this.selectionHelper.onLocalSelectionChanged(this.lastLocalSelection, this.width, this.height);
|
|
1687
|
+
}
|
|
1553
1688
|
this.renderFontToBuffer();
|
|
1554
|
-
this.
|
|
1689
|
+
this.requestRender();
|
|
1555
1690
|
}
|
|
1556
1691
|
get font() {
|
|
1557
1692
|
return this._font;
|
|
@@ -1559,9 +1694,11 @@ class ASCIIFontRenderable extends FrameBufferRenderable {
|
|
|
1559
1694
|
set font(value) {
|
|
1560
1695
|
this._font = value;
|
|
1561
1696
|
this.updateDimensions();
|
|
1562
|
-
|
|
1697
|
+
if (this.lastLocalSelection) {
|
|
1698
|
+
this.selectionHelper.onLocalSelectionChanged(this.lastLocalSelection, this.width, this.height);
|
|
1699
|
+
}
|
|
1563
1700
|
this.renderFontToBuffer();
|
|
1564
|
-
this.
|
|
1701
|
+
this.requestRender();
|
|
1565
1702
|
}
|
|
1566
1703
|
get fg() {
|
|
1567
1704
|
return this._fg;
|
|
@@ -1573,7 +1710,7 @@ class ASCIIFontRenderable extends FrameBufferRenderable {
|
|
|
1573
1710
|
this._fg = [typeof value === "string" ? parseColor(value) : value];
|
|
1574
1711
|
}
|
|
1575
1712
|
this.renderFontToBuffer();
|
|
1576
|
-
this.
|
|
1713
|
+
this.requestRender();
|
|
1577
1714
|
}
|
|
1578
1715
|
get bg() {
|
|
1579
1716
|
return this._bg;
|
|
@@ -1581,7 +1718,7 @@ class ASCIIFontRenderable extends FrameBufferRenderable {
|
|
|
1581
1718
|
set bg(value) {
|
|
1582
1719
|
this._bg = typeof value === "string" ? parseColor(value) : value;
|
|
1583
1720
|
this.renderFontToBuffer();
|
|
1584
|
-
this.
|
|
1721
|
+
this.requestRender();
|
|
1585
1722
|
}
|
|
1586
1723
|
updateDimensions() {
|
|
1587
1724
|
const measurements = measureText({ text: this._text, font: this._font });
|
|
@@ -1589,15 +1726,19 @@ class ASCIIFontRenderable extends FrameBufferRenderable {
|
|
|
1589
1726
|
this.height = measurements.height;
|
|
1590
1727
|
}
|
|
1591
1728
|
shouldStartSelection(x, y) {
|
|
1592
|
-
|
|
1729
|
+
const localX = x - this.x;
|
|
1730
|
+
const localY = y - this.y;
|
|
1731
|
+
return this.selectionHelper.shouldStartSelection(localX, localY, this.width, this.height);
|
|
1593
1732
|
}
|
|
1594
1733
|
onSelectionChanged(selection) {
|
|
1595
|
-
const
|
|
1734
|
+
const localSelection = convertGlobalToLocalSelection(selection, this.x, this.y);
|
|
1735
|
+
this.lastLocalSelection = localSelection;
|
|
1736
|
+
const changed = this.selectionHelper.onLocalSelectionChanged(localSelection, this.width, this.height);
|
|
1596
1737
|
if (changed) {
|
|
1597
1738
|
this.renderFontToBuffer();
|
|
1598
|
-
this.
|
|
1739
|
+
this.requestRender();
|
|
1599
1740
|
}
|
|
1600
|
-
return
|
|
1741
|
+
return changed;
|
|
1601
1742
|
}
|
|
1602
1743
|
getSelectedText() {
|
|
1603
1744
|
const selection = this.selectionHelper.getSelection();
|
|
@@ -1771,7 +1912,7 @@ class InputRenderable extends Renderable {
|
|
|
1771
1912
|
if (this._value !== newValue) {
|
|
1772
1913
|
this._value = newValue;
|
|
1773
1914
|
this._cursorPosition = Math.min(this._cursorPosition, this._value.length);
|
|
1774
|
-
this.
|
|
1915
|
+
this.requestRender();
|
|
1775
1916
|
this.updateCursorPosition();
|
|
1776
1917
|
this.emit("input" /* INPUT */, this._value);
|
|
1777
1918
|
}
|
|
@@ -1779,14 +1920,14 @@ class InputRenderable extends Renderable {
|
|
|
1779
1920
|
set placeholder(placeholder) {
|
|
1780
1921
|
if (this._placeholder !== placeholder) {
|
|
1781
1922
|
this._placeholder = placeholder;
|
|
1782
|
-
this.
|
|
1923
|
+
this.requestRender();
|
|
1783
1924
|
}
|
|
1784
1925
|
}
|
|
1785
1926
|
set cursorPosition(position) {
|
|
1786
1927
|
const newPosition = Math.max(0, Math.min(position, this._value.length));
|
|
1787
1928
|
if (this._cursorPosition !== newPosition) {
|
|
1788
1929
|
this._cursorPosition = newPosition;
|
|
1789
|
-
this.
|
|
1930
|
+
this.requestRender();
|
|
1790
1931
|
this.updateCursorPosition();
|
|
1791
1932
|
}
|
|
1792
1933
|
}
|
|
@@ -1798,7 +1939,7 @@ class InputRenderable extends Renderable {
|
|
|
1798
1939
|
const afterCursor = this._value.substring(this._cursorPosition);
|
|
1799
1940
|
this._value = beforeCursor + text + afterCursor;
|
|
1800
1941
|
this._cursorPosition += text.length;
|
|
1801
|
-
this.
|
|
1942
|
+
this.requestRender();
|
|
1802
1943
|
this.updateCursorPosition();
|
|
1803
1944
|
this.emit("input" /* INPUT */, this._value);
|
|
1804
1945
|
}
|
|
@@ -1808,14 +1949,14 @@ class InputRenderable extends Renderable {
|
|
|
1808
1949
|
const afterCursor = this._value.substring(this._cursorPosition);
|
|
1809
1950
|
this._value = beforeCursor + afterCursor;
|
|
1810
1951
|
this._cursorPosition--;
|
|
1811
|
-
this.
|
|
1952
|
+
this.requestRender();
|
|
1812
1953
|
this.updateCursorPosition();
|
|
1813
1954
|
this.emit("input" /* INPUT */, this._value);
|
|
1814
1955
|
} else if (direction === "forward" && this._cursorPosition < this._value.length) {
|
|
1815
1956
|
const beforeCursor = this._value.substring(0, this._cursorPosition);
|
|
1816
1957
|
const afterCursor = this._value.substring(this._cursorPosition + 1);
|
|
1817
1958
|
this._value = beforeCursor + afterCursor;
|
|
1818
|
-
this.
|
|
1959
|
+
this.requestRender();
|
|
1819
1960
|
this.updateCursorPosition();
|
|
1820
1961
|
this.emit("input" /* INPUT */, this._value);
|
|
1821
1962
|
}
|
|
@@ -1863,49 +2004,49 @@ class InputRenderable extends Renderable {
|
|
|
1863
2004
|
this._maxLength = maxLength;
|
|
1864
2005
|
if (this._value.length > maxLength) {
|
|
1865
2006
|
this._value = this._value.substring(0, maxLength);
|
|
1866
|
-
this.
|
|
2007
|
+
this.requestRender();
|
|
1867
2008
|
}
|
|
1868
2009
|
}
|
|
1869
2010
|
set backgroundColor(value) {
|
|
1870
2011
|
const newColor = parseColor(value ?? this._defaultOptions.backgroundColor);
|
|
1871
2012
|
if (this._backgroundColor !== newColor) {
|
|
1872
2013
|
this._backgroundColor = newColor;
|
|
1873
|
-
this.
|
|
2014
|
+
this.requestRender();
|
|
1874
2015
|
}
|
|
1875
2016
|
}
|
|
1876
2017
|
set textColor(value) {
|
|
1877
2018
|
const newColor = parseColor(value ?? this._defaultOptions.textColor);
|
|
1878
2019
|
if (this._textColor !== newColor) {
|
|
1879
2020
|
this._textColor = newColor;
|
|
1880
|
-
this.
|
|
2021
|
+
this.requestRender();
|
|
1881
2022
|
}
|
|
1882
2023
|
}
|
|
1883
2024
|
set focusedBackgroundColor(value) {
|
|
1884
2025
|
const newColor = parseColor(value ?? this._defaultOptions.focusedBackgroundColor);
|
|
1885
2026
|
if (this._focusedBackgroundColor !== newColor) {
|
|
1886
2027
|
this._focusedBackgroundColor = newColor;
|
|
1887
|
-
this.
|
|
2028
|
+
this.requestRender();
|
|
1888
2029
|
}
|
|
1889
2030
|
}
|
|
1890
2031
|
set focusedTextColor(value) {
|
|
1891
2032
|
const newColor = parseColor(value ?? this._defaultOptions.focusedTextColor);
|
|
1892
2033
|
if (this._focusedTextColor !== newColor) {
|
|
1893
2034
|
this._focusedTextColor = newColor;
|
|
1894
|
-
this.
|
|
2035
|
+
this.requestRender();
|
|
1895
2036
|
}
|
|
1896
2037
|
}
|
|
1897
2038
|
set placeholderColor(value) {
|
|
1898
2039
|
const newColor = parseColor(value ?? this._defaultOptions.placeholderColor);
|
|
1899
2040
|
if (this._placeholderColor !== newColor) {
|
|
1900
2041
|
this._placeholderColor = newColor;
|
|
1901
|
-
this.
|
|
2042
|
+
this.requestRender();
|
|
1902
2043
|
}
|
|
1903
2044
|
}
|
|
1904
2045
|
set cursorColor(value) {
|
|
1905
2046
|
const newColor = parseColor(value ?? this._defaultOptions.cursorColor);
|
|
1906
2047
|
if (this._cursorColor !== newColor) {
|
|
1907
2048
|
this._cursorColor = newColor;
|
|
1908
|
-
this.
|
|
2049
|
+
this.requestRender();
|
|
1909
2050
|
}
|
|
1910
2051
|
}
|
|
1911
2052
|
updateFromLayout() {
|
|
@@ -1990,7 +2131,7 @@ class SelectRenderable extends Renderable {
|
|
|
1990
2131
|
this._descriptionColor = parseColor(options.descriptionColor || this._defaultOptions.descriptionColor);
|
|
1991
2132
|
this._selectedDescriptionColor = parseColor(options.selectedDescriptionColor || this._defaultOptions.selectedDescriptionColor);
|
|
1992
2133
|
this._fastScrollStep = options.fastScrollStep || this._defaultOptions.fastScrollStep;
|
|
1993
|
-
this.
|
|
2134
|
+
this.requestRender();
|
|
1994
2135
|
}
|
|
1995
2136
|
renderSelf(buffer, deltaTime) {
|
|
1996
2137
|
if (!this.visible || !this.frameBuffer)
|
|
@@ -2066,7 +2207,7 @@ class SelectRenderable extends Renderable {
|
|
|
2066
2207
|
this._options = options;
|
|
2067
2208
|
this.selectedIndex = Math.min(this.selectedIndex, Math.max(0, options.length - 1));
|
|
2068
2209
|
this.updateScrollOffset();
|
|
2069
|
-
this.
|
|
2210
|
+
this.requestRender();
|
|
2070
2211
|
}
|
|
2071
2212
|
getSelectedOption() {
|
|
2072
2213
|
return this._options[this.selectedIndex] || null;
|
|
@@ -2084,7 +2225,7 @@ class SelectRenderable extends Renderable {
|
|
|
2084
2225
|
this.selectedIndex = 0;
|
|
2085
2226
|
}
|
|
2086
2227
|
this.updateScrollOffset();
|
|
2087
|
-
this.
|
|
2228
|
+
this.requestRender();
|
|
2088
2229
|
this.emit("selectionChanged" /* SELECTION_CHANGED */, this.selectedIndex, this.getSelectedOption());
|
|
2089
2230
|
}
|
|
2090
2231
|
moveDown(steps = 1) {
|
|
@@ -2097,7 +2238,7 @@ class SelectRenderable extends Renderable {
|
|
|
2097
2238
|
this.selectedIndex = this._options.length - 1;
|
|
2098
2239
|
}
|
|
2099
2240
|
this.updateScrollOffset();
|
|
2100
|
-
this.
|
|
2241
|
+
this.requestRender();
|
|
2101
2242
|
this.emit("selectionChanged" /* SELECTION_CHANGED */, this.selectedIndex, this.getSelectedOption());
|
|
2102
2243
|
}
|
|
2103
2244
|
selectCurrent() {
|
|
@@ -2110,7 +2251,7 @@ class SelectRenderable extends Renderable {
|
|
|
2110
2251
|
if (index >= 0 && index < this._options.length) {
|
|
2111
2252
|
this.selectedIndex = index;
|
|
2112
2253
|
this.updateScrollOffset();
|
|
2113
|
-
this.
|
|
2254
|
+
this.requestRender();
|
|
2114
2255
|
this.emit("selectionChanged" /* SELECTION_CHANGED */, this.selectedIndex, this.getSelectedOption());
|
|
2115
2256
|
}
|
|
2116
2257
|
}
|
|
@@ -2121,13 +2262,13 @@ class SelectRenderable extends Renderable {
|
|
|
2121
2262
|
const newScrollOffset = Math.max(0, Math.min(this.selectedIndex - halfVisible, this._options.length - this.maxVisibleItems));
|
|
2122
2263
|
if (newScrollOffset !== this.scrollOffset) {
|
|
2123
2264
|
this.scrollOffset = newScrollOffset;
|
|
2124
|
-
this.
|
|
2265
|
+
this.requestRender();
|
|
2125
2266
|
}
|
|
2126
2267
|
}
|
|
2127
2268
|
onResize(width, height) {
|
|
2128
2269
|
this.maxVisibleItems = Math.max(1, Math.floor(height / this.linesPerItem));
|
|
2129
2270
|
this.updateScrollOffset();
|
|
2130
|
-
this.
|
|
2271
|
+
this.requestRender();
|
|
2131
2272
|
}
|
|
2132
2273
|
handleKeyPress(key) {
|
|
2133
2274
|
const keyName = typeof key === "string" ? key : key.name;
|
|
@@ -2153,7 +2294,7 @@ class SelectRenderable extends Renderable {
|
|
|
2153
2294
|
}
|
|
2154
2295
|
set showScrollIndicator(show) {
|
|
2155
2296
|
this._showScrollIndicator = show;
|
|
2156
|
-
this.
|
|
2297
|
+
this.requestRender();
|
|
2157
2298
|
}
|
|
2158
2299
|
get showDescription() {
|
|
2159
2300
|
return this._showDescription;
|
|
@@ -2165,7 +2306,7 @@ class SelectRenderable extends Renderable {
|
|
|
2165
2306
|
this.linesPerItem += this._itemSpacing;
|
|
2166
2307
|
this.maxVisibleItems = Math.max(1, Math.floor(this.height / this.linesPerItem));
|
|
2167
2308
|
this.updateScrollOffset();
|
|
2168
|
-
this.
|
|
2309
|
+
this.requestRender();
|
|
2169
2310
|
}
|
|
2170
2311
|
}
|
|
2171
2312
|
get wrapSelection() {
|
|
@@ -2178,56 +2319,56 @@ class SelectRenderable extends Renderable {
|
|
|
2178
2319
|
const newColor = parseColor(value ?? this._defaultOptions.backgroundColor);
|
|
2179
2320
|
if (this._backgroundColor !== newColor) {
|
|
2180
2321
|
this._backgroundColor = newColor;
|
|
2181
|
-
this.
|
|
2322
|
+
this.requestRender();
|
|
2182
2323
|
}
|
|
2183
2324
|
}
|
|
2184
2325
|
set textColor(value) {
|
|
2185
2326
|
const newColor = parseColor(value ?? this._defaultOptions.textColor);
|
|
2186
2327
|
if (this._textColor !== newColor) {
|
|
2187
2328
|
this._textColor = newColor;
|
|
2188
|
-
this.
|
|
2329
|
+
this.requestRender();
|
|
2189
2330
|
}
|
|
2190
2331
|
}
|
|
2191
2332
|
set focusedBackgroundColor(value) {
|
|
2192
2333
|
const newColor = parseColor(value ?? this._defaultOptions.focusedBackgroundColor);
|
|
2193
2334
|
if (this._focusedBackgroundColor !== newColor) {
|
|
2194
2335
|
this._focusedBackgroundColor = newColor;
|
|
2195
|
-
this.
|
|
2336
|
+
this.requestRender();
|
|
2196
2337
|
}
|
|
2197
2338
|
}
|
|
2198
2339
|
set focusedTextColor(value) {
|
|
2199
2340
|
const newColor = parseColor(value ?? this._defaultOptions.focusedTextColor);
|
|
2200
2341
|
if (this._focusedTextColor !== newColor) {
|
|
2201
2342
|
this._focusedTextColor = newColor;
|
|
2202
|
-
this.
|
|
2343
|
+
this.requestRender();
|
|
2203
2344
|
}
|
|
2204
2345
|
}
|
|
2205
2346
|
set selectedBackgroundColor(value) {
|
|
2206
2347
|
const newColor = parseColor(value ?? this._defaultOptions.selectedBackgroundColor);
|
|
2207
2348
|
if (this._selectedBackgroundColor !== newColor) {
|
|
2208
2349
|
this._selectedBackgroundColor = newColor;
|
|
2209
|
-
this.
|
|
2350
|
+
this.requestRender();
|
|
2210
2351
|
}
|
|
2211
2352
|
}
|
|
2212
2353
|
set selectedTextColor(value) {
|
|
2213
2354
|
const newColor = parseColor(value ?? this._defaultOptions.selectedTextColor);
|
|
2214
2355
|
if (this._selectedTextColor !== newColor) {
|
|
2215
2356
|
this._selectedTextColor = newColor;
|
|
2216
|
-
this.
|
|
2357
|
+
this.requestRender();
|
|
2217
2358
|
}
|
|
2218
2359
|
}
|
|
2219
2360
|
set descriptionColor(value) {
|
|
2220
2361
|
const newColor = parseColor(value ?? this._defaultOptions.descriptionColor);
|
|
2221
2362
|
if (this._descriptionColor !== newColor) {
|
|
2222
2363
|
this._descriptionColor = newColor;
|
|
2223
|
-
this.
|
|
2364
|
+
this.requestRender();
|
|
2224
2365
|
}
|
|
2225
2366
|
}
|
|
2226
2367
|
set selectedDescriptionColor(value) {
|
|
2227
2368
|
const newColor = parseColor(value ?? this._defaultOptions.selectedDescriptionColor);
|
|
2228
2369
|
if (this._selectedDescriptionColor !== newColor) {
|
|
2229
2370
|
this._selectedDescriptionColor = newColor;
|
|
2230
|
-
this.
|
|
2371
|
+
this.requestRender();
|
|
2231
2372
|
}
|
|
2232
2373
|
}
|
|
2233
2374
|
set font(font) {
|
|
@@ -2237,7 +2378,7 @@ class SelectRenderable extends Renderable {
|
|
|
2237
2378
|
this.linesPerItem += this._itemSpacing;
|
|
2238
2379
|
this.maxVisibleItems = Math.max(1, Math.floor(this.height / this.linesPerItem));
|
|
2239
2380
|
this.updateScrollOffset();
|
|
2240
|
-
this.
|
|
2381
|
+
this.requestRender();
|
|
2241
2382
|
}
|
|
2242
2383
|
set itemSpacing(spacing) {
|
|
2243
2384
|
this._itemSpacing = spacing;
|
|
@@ -2245,7 +2386,7 @@ class SelectRenderable extends Renderable {
|
|
|
2245
2386
|
this.linesPerItem += this._itemSpacing;
|
|
2246
2387
|
this.maxVisibleItems = Math.max(1, Math.floor(this.height / this.linesPerItem));
|
|
2247
2388
|
this.updateScrollOffset();
|
|
2248
|
-
this.
|
|
2389
|
+
this.requestRender();
|
|
2249
2390
|
}
|
|
2250
2391
|
set fastScrollStep(step) {
|
|
2251
2392
|
this._fastScrollStep = step;
|
|
@@ -2379,7 +2520,7 @@ class TabSelectRenderable extends Renderable {
|
|
|
2379
2520
|
this._options = options;
|
|
2380
2521
|
this.selectedIndex = Math.min(this.selectedIndex, Math.max(0, options.length - 1));
|
|
2381
2522
|
this.updateScrollOffset();
|
|
2382
|
-
this.
|
|
2523
|
+
this.requestRender();
|
|
2383
2524
|
}
|
|
2384
2525
|
getSelectedOption() {
|
|
2385
2526
|
return this._options[this.selectedIndex] || null;
|
|
@@ -2396,7 +2537,7 @@ class TabSelectRenderable extends Renderable {
|
|
|
2396
2537
|
return;
|
|
2397
2538
|
}
|
|
2398
2539
|
this.updateScrollOffset();
|
|
2399
|
-
this.
|
|
2540
|
+
this.requestRender();
|
|
2400
2541
|
this.emit("selectionChanged" /* SELECTION_CHANGED */, this.selectedIndex, this.getSelectedOption());
|
|
2401
2542
|
}
|
|
2402
2543
|
moveRight() {
|
|
@@ -2408,7 +2549,7 @@ class TabSelectRenderable extends Renderable {
|
|
|
2408
2549
|
return;
|
|
2409
2550
|
}
|
|
2410
2551
|
this.updateScrollOffset();
|
|
2411
|
-
this.
|
|
2552
|
+
this.requestRender();
|
|
2412
2553
|
this.emit("selectionChanged" /* SELECTION_CHANGED */, this.selectedIndex, this.getSelectedOption());
|
|
2413
2554
|
}
|
|
2414
2555
|
selectCurrent() {
|
|
@@ -2421,7 +2562,7 @@ class TabSelectRenderable extends Renderable {
|
|
|
2421
2562
|
if (index >= 0 && index < this._options.length) {
|
|
2422
2563
|
this.selectedIndex = index;
|
|
2423
2564
|
this.updateScrollOffset();
|
|
2424
|
-
this.
|
|
2565
|
+
this.requestRender();
|
|
2425
2566
|
this.emit("selectionChanged" /* SELECTION_CHANGED */, this.selectedIndex, this.getSelectedOption());
|
|
2426
2567
|
}
|
|
2427
2568
|
}
|
|
@@ -2430,13 +2571,13 @@ class TabSelectRenderable extends Renderable {
|
|
|
2430
2571
|
const newScrollOffset = Math.max(0, Math.min(this.selectedIndex - halfVisible, this._options.length - this.maxVisibleTabs));
|
|
2431
2572
|
if (newScrollOffset !== this.scrollOffset) {
|
|
2432
2573
|
this.scrollOffset = newScrollOffset;
|
|
2433
|
-
this.
|
|
2574
|
+
this.requestRender();
|
|
2434
2575
|
}
|
|
2435
2576
|
}
|
|
2436
2577
|
onResize(width, height) {
|
|
2437
2578
|
this.maxVisibleTabs = Math.max(1, Math.floor(width / this._tabWidth));
|
|
2438
2579
|
this.updateScrollOffset();
|
|
2439
|
-
this.
|
|
2580
|
+
this.requestRender();
|
|
2440
2581
|
}
|
|
2441
2582
|
setTabWidth(tabWidth) {
|
|
2442
2583
|
if (this._tabWidth === tabWidth)
|
|
@@ -2444,7 +2585,7 @@ class TabSelectRenderable extends Renderable {
|
|
|
2444
2585
|
this._tabWidth = tabWidth;
|
|
2445
2586
|
this.maxVisibleTabs = Math.max(1, Math.floor(this.width / this._tabWidth));
|
|
2446
2587
|
this.updateScrollOffset();
|
|
2447
|
-
this.
|
|
2588
|
+
this.requestRender();
|
|
2448
2589
|
}
|
|
2449
2590
|
getTabWidth() {
|
|
2450
2591
|
return this._tabWidth;
|
|
@@ -2474,35 +2615,35 @@ class TabSelectRenderable extends Renderable {
|
|
|
2474
2615
|
this._options = options;
|
|
2475
2616
|
this.selectedIndex = Math.min(this.selectedIndex, Math.max(0, options.length - 1));
|
|
2476
2617
|
this.updateScrollOffset();
|
|
2477
|
-
this.
|
|
2618
|
+
this.requestRender();
|
|
2478
2619
|
}
|
|
2479
2620
|
set backgroundColor(color) {
|
|
2480
2621
|
this._backgroundColor = parseColor(color);
|
|
2481
|
-
this.
|
|
2622
|
+
this.requestRender();
|
|
2482
2623
|
}
|
|
2483
2624
|
set textColor(color) {
|
|
2484
2625
|
this._textColor = parseColor(color);
|
|
2485
|
-
this.
|
|
2626
|
+
this.requestRender();
|
|
2486
2627
|
}
|
|
2487
2628
|
set focusedBackgroundColor(color) {
|
|
2488
2629
|
this._focusedBackgroundColor = parseColor(color);
|
|
2489
|
-
this.
|
|
2630
|
+
this.requestRender();
|
|
2490
2631
|
}
|
|
2491
2632
|
set focusedTextColor(color) {
|
|
2492
2633
|
this._focusedTextColor = parseColor(color);
|
|
2493
|
-
this.
|
|
2634
|
+
this.requestRender();
|
|
2494
2635
|
}
|
|
2495
2636
|
set selectedBackgroundColor(color) {
|
|
2496
2637
|
this._selectedBackgroundColor = parseColor(color);
|
|
2497
|
-
this.
|
|
2638
|
+
this.requestRender();
|
|
2498
2639
|
}
|
|
2499
2640
|
set selectedTextColor(color) {
|
|
2500
2641
|
this._selectedTextColor = parseColor(color);
|
|
2501
|
-
this.
|
|
2642
|
+
this.requestRender();
|
|
2502
2643
|
}
|
|
2503
2644
|
set selectedDescriptionColor(color) {
|
|
2504
2645
|
this._selectedDescriptionColor = parseColor(color);
|
|
2505
|
-
this.
|
|
2646
|
+
this.requestRender();
|
|
2506
2647
|
}
|
|
2507
2648
|
get showDescription() {
|
|
2508
2649
|
return this._showDescription;
|
|
@@ -2512,7 +2653,7 @@ class TabSelectRenderable extends Renderable {
|
|
|
2512
2653
|
this._showDescription = show;
|
|
2513
2654
|
const newHeight = this.calculateDynamicHeight();
|
|
2514
2655
|
this.height = newHeight;
|
|
2515
|
-
this.
|
|
2656
|
+
this.requestRender();
|
|
2516
2657
|
}
|
|
2517
2658
|
}
|
|
2518
2659
|
get showUnderline() {
|
|
@@ -2523,7 +2664,7 @@ class TabSelectRenderable extends Renderable {
|
|
|
2523
2664
|
this._showUnderline = show;
|
|
2524
2665
|
const newHeight = this.calculateDynamicHeight();
|
|
2525
2666
|
this.height = newHeight;
|
|
2526
|
-
this.
|
|
2667
|
+
this.requestRender();
|
|
2527
2668
|
}
|
|
2528
2669
|
}
|
|
2529
2670
|
get showScrollArrows() {
|
|
@@ -2532,7 +2673,7 @@ class TabSelectRenderable extends Renderable {
|
|
|
2532
2673
|
set showScrollArrows(show) {
|
|
2533
2674
|
if (this._showScrollArrows !== show) {
|
|
2534
2675
|
this._showScrollArrows = show;
|
|
2535
|
-
this.
|
|
2676
|
+
this.requestRender();
|
|
2536
2677
|
}
|
|
2537
2678
|
}
|
|
2538
2679
|
get wrapSelection() {
|
|
@@ -2550,7 +2691,792 @@ class TabSelectRenderable extends Renderable {
|
|
|
2550
2691
|
this._tabWidth = tabWidth;
|
|
2551
2692
|
this.maxVisibleTabs = Math.max(1, Math.floor(this.width / this._tabWidth));
|
|
2552
2693
|
this.updateScrollOffset();
|
|
2553
|
-
this.
|
|
2694
|
+
this.requestRender();
|
|
2695
|
+
}
|
|
2696
|
+
}
|
|
2697
|
+
// src/renderables/Slider.ts
|
|
2698
|
+
var defaultThumbBackgroundColor = RGBA.fromHex("#9a9ea3");
|
|
2699
|
+
var defaultTrackBackgroundColor = RGBA.fromHex("#252527");
|
|
2700
|
+
|
|
2701
|
+
class SliderRenderable extends Renderable {
|
|
2702
|
+
orientation;
|
|
2703
|
+
_thumbSize;
|
|
2704
|
+
_thumbPosition;
|
|
2705
|
+
_backgroundColor;
|
|
2706
|
+
_foregroundColor;
|
|
2707
|
+
_onChange;
|
|
2708
|
+
constructor(ctx, options) {
|
|
2709
|
+
super(ctx, options);
|
|
2710
|
+
this.orientation = options.orientation;
|
|
2711
|
+
this._thumbSize = options.thumbSize ?? 1;
|
|
2712
|
+
this._thumbPosition = options.thumbPosition ?? 0;
|
|
2713
|
+
this._onChange = options.onChange;
|
|
2714
|
+
this._backgroundColor = options.backgroundColor ? parseColor(options.backgroundColor) : defaultTrackBackgroundColor;
|
|
2715
|
+
this._foregroundColor = options.foregroundColor ? parseColor(options.foregroundColor) : defaultThumbBackgroundColor;
|
|
2716
|
+
this.setupMouseHandling();
|
|
2717
|
+
}
|
|
2718
|
+
get thumbSize() {
|
|
2719
|
+
return this._thumbSize;
|
|
2720
|
+
}
|
|
2721
|
+
set thumbSize(value) {
|
|
2722
|
+
const clamped = Math.max(1, Math.min(value, this.orientation === "vertical" ? this.height : this.width));
|
|
2723
|
+
if (clamped !== this._thumbSize) {
|
|
2724
|
+
this._thumbSize = clamped;
|
|
2725
|
+
this.requestRender();
|
|
2726
|
+
}
|
|
2727
|
+
}
|
|
2728
|
+
get thumbPosition() {
|
|
2729
|
+
return this._thumbPosition;
|
|
2730
|
+
}
|
|
2731
|
+
set thumbPosition(value) {
|
|
2732
|
+
const clamped = Math.max(0, Math.min(1, value));
|
|
2733
|
+
if (clamped !== this._thumbPosition) {
|
|
2734
|
+
this._thumbPosition = clamped;
|
|
2735
|
+
this._onChange?.(clamped);
|
|
2736
|
+
this.emit("change", { position: clamped });
|
|
2737
|
+
this.requestRender();
|
|
2738
|
+
}
|
|
2739
|
+
}
|
|
2740
|
+
get backgroundColor() {
|
|
2741
|
+
return this._backgroundColor;
|
|
2742
|
+
}
|
|
2743
|
+
set backgroundColor(value) {
|
|
2744
|
+
this._backgroundColor = parseColor(value);
|
|
2745
|
+
this.requestRender();
|
|
2746
|
+
}
|
|
2747
|
+
get foregroundColor() {
|
|
2748
|
+
return this._foregroundColor;
|
|
2749
|
+
}
|
|
2750
|
+
set foregroundColor(value) {
|
|
2751
|
+
this._foregroundColor = parseColor(value);
|
|
2752
|
+
this.requestRender();
|
|
2753
|
+
}
|
|
2754
|
+
setupMouseHandling() {
|
|
2755
|
+
let isDragging = false;
|
|
2756
|
+
let relativeStartPos = 0;
|
|
2757
|
+
this.onMouseDown = (event) => {
|
|
2758
|
+
event.stopPropagation();
|
|
2759
|
+
isDragging = true;
|
|
2760
|
+
const thumbRect = this.getThumbRect();
|
|
2761
|
+
const isOnThumb = event.x >= thumbRect.x && event.x < thumbRect.x + thumbRect.width && event.y >= thumbRect.y && event.y < thumbRect.y + thumbRect.height;
|
|
2762
|
+
if (isOnThumb) {
|
|
2763
|
+
relativeStartPos = this.orientation === "vertical" ? event.y - thumbRect.y : event.x - thumbRect.x;
|
|
2764
|
+
} else {
|
|
2765
|
+
relativeStartPos = this.orientation === "vertical" ? thumbRect.height / 2 : thumbRect.width / 2;
|
|
2766
|
+
}
|
|
2767
|
+
this.updatePositionFromMouse(event, relativeStartPos);
|
|
2768
|
+
};
|
|
2769
|
+
this.onMouseDrag = (event) => {
|
|
2770
|
+
if (!isDragging)
|
|
2771
|
+
return;
|
|
2772
|
+
event.stopPropagation();
|
|
2773
|
+
this.updatePositionFromMouse(event, relativeStartPos);
|
|
2774
|
+
};
|
|
2775
|
+
this.onMouseUp = () => {
|
|
2776
|
+
isDragging = false;
|
|
2777
|
+
};
|
|
2778
|
+
}
|
|
2779
|
+
updatePositionFromMouse(event, relativeStartPos) {
|
|
2780
|
+
const trackStart = this.orientation === "vertical" ? this.y : this.x;
|
|
2781
|
+
const trackSize = this.orientation === "vertical" ? this.height : this.width;
|
|
2782
|
+
const mousePos = this.orientation === "vertical" ? event.y : event.x;
|
|
2783
|
+
const thumbStartPos = mousePos - trackStart - relativeStartPos;
|
|
2784
|
+
const maxThumbStartPos = trackSize - this._thumbSize;
|
|
2785
|
+
const clampedThumbStartPos = Math.max(0, Math.min(maxThumbStartPos, thumbStartPos));
|
|
2786
|
+
const newPosition = maxThumbStartPos > 0 ? clampedThumbStartPos / maxThumbStartPos : 0;
|
|
2787
|
+
this.thumbPosition = newPosition;
|
|
2788
|
+
}
|
|
2789
|
+
getThumbPosition() {
|
|
2790
|
+
const trackSize = this.orientation === "vertical" ? this.height : this.width;
|
|
2791
|
+
const maxPos = trackSize - this._thumbSize;
|
|
2792
|
+
return Math.round(this._thumbPosition * maxPos);
|
|
2793
|
+
}
|
|
2794
|
+
getThumbRect() {
|
|
2795
|
+
const thumbPos = this.getThumbPosition();
|
|
2796
|
+
if (this.orientation === "vertical") {
|
|
2797
|
+
return {
|
|
2798
|
+
x: this.x,
|
|
2799
|
+
y: this.y + thumbPos,
|
|
2800
|
+
width: this.width,
|
|
2801
|
+
height: this._thumbSize
|
|
2802
|
+
};
|
|
2803
|
+
} else {
|
|
2804
|
+
return {
|
|
2805
|
+
x: this.x + thumbPos,
|
|
2806
|
+
y: this.y,
|
|
2807
|
+
width: this._thumbSize,
|
|
2808
|
+
height: this.height
|
|
2809
|
+
};
|
|
2810
|
+
}
|
|
2811
|
+
}
|
|
2812
|
+
renderSelf(buffer) {
|
|
2813
|
+
buffer.fillRect(this.x, this.y, this.width, this.height, this._backgroundColor);
|
|
2814
|
+
const thumbRect = this.getThumbRect();
|
|
2815
|
+
buffer.fillRect(thumbRect.x, thumbRect.y, thumbRect.width, thumbRect.height, this._foregroundColor);
|
|
2816
|
+
}
|
|
2817
|
+
}
|
|
2818
|
+
|
|
2819
|
+
// src/renderables/ScrollBar.ts
|
|
2820
|
+
class ScrollBarRenderable extends Renderable {
|
|
2821
|
+
slider;
|
|
2822
|
+
startArrow;
|
|
2823
|
+
endArrow;
|
|
2824
|
+
orientation;
|
|
2825
|
+
focusable = true;
|
|
2826
|
+
_scrollSize = 0;
|
|
2827
|
+
_scrollPosition = 0;
|
|
2828
|
+
_viewportSize = 0;
|
|
2829
|
+
_showArrows = false;
|
|
2830
|
+
_manualVisibility = false;
|
|
2831
|
+
_onChange;
|
|
2832
|
+
scrollStep = null;
|
|
2833
|
+
get visible() {
|
|
2834
|
+
return super.visible;
|
|
2835
|
+
}
|
|
2836
|
+
set visible(value) {
|
|
2837
|
+
this._manualVisibility = true;
|
|
2838
|
+
super.visible = value;
|
|
2839
|
+
}
|
|
2840
|
+
resetVisibilityControl() {
|
|
2841
|
+
this._manualVisibility = false;
|
|
2842
|
+
this.recalculateVisibility();
|
|
2843
|
+
}
|
|
2844
|
+
get scrollSize() {
|
|
2845
|
+
return this._scrollSize;
|
|
2846
|
+
}
|
|
2847
|
+
get scrollPosition() {
|
|
2848
|
+
return this._scrollPosition;
|
|
2849
|
+
}
|
|
2850
|
+
get viewportSize() {
|
|
2851
|
+
return this._viewportSize;
|
|
2852
|
+
}
|
|
2853
|
+
set scrollSize(value) {
|
|
2854
|
+
if (value === this.scrollSize)
|
|
2855
|
+
return;
|
|
2856
|
+
this._scrollSize = value;
|
|
2857
|
+
this.recalculateVisibility();
|
|
2858
|
+
this.scrollPosition = this.scrollPosition;
|
|
2859
|
+
}
|
|
2860
|
+
set scrollPosition(value) {
|
|
2861
|
+
const newPosition = Math.round(Math.min(Math.max(0, value), this.scrollSize - this.viewportSize));
|
|
2862
|
+
if (newPosition !== this._scrollPosition) {
|
|
2863
|
+
this._scrollPosition = newPosition;
|
|
2864
|
+
this.updateSliderFromScrollState();
|
|
2865
|
+
this._onChange?.(newPosition);
|
|
2866
|
+
this.emit("change", { position: newPosition });
|
|
2867
|
+
}
|
|
2868
|
+
}
|
|
2869
|
+
set viewportSize(value) {
|
|
2870
|
+
if (value === this.viewportSize)
|
|
2871
|
+
return;
|
|
2872
|
+
this._viewportSize = value;
|
|
2873
|
+
this.recalculateVisibility();
|
|
2874
|
+
this.scrollPosition = this.scrollPosition;
|
|
2875
|
+
}
|
|
2876
|
+
get showArrows() {
|
|
2877
|
+
return this._showArrows;
|
|
2878
|
+
}
|
|
2879
|
+
set showArrows(value) {
|
|
2880
|
+
if (value === this._showArrows)
|
|
2881
|
+
return;
|
|
2882
|
+
this._showArrows = value;
|
|
2883
|
+
this.startArrow.visible = value;
|
|
2884
|
+
this.endArrow.visible = value;
|
|
2885
|
+
}
|
|
2886
|
+
constructor(ctx, { trackOptions, arrowOptions, orientation, showArrows = false, ...options }) {
|
|
2887
|
+
super(ctx, {
|
|
2888
|
+
flexDirection: orientation === "vertical" ? "column" : "row",
|
|
2889
|
+
alignSelf: "stretch",
|
|
2890
|
+
alignItems: "stretch",
|
|
2891
|
+
...options
|
|
2892
|
+
});
|
|
2893
|
+
this._onChange = options.onChange;
|
|
2894
|
+
this.orientation = orientation;
|
|
2895
|
+
this._showArrows = showArrows;
|
|
2896
|
+
this.slider = new SliderRenderable(ctx, {
|
|
2897
|
+
orientation,
|
|
2898
|
+
onChange: (position) => {
|
|
2899
|
+
const scrollRange = Math.max(0, this._scrollSize - this._viewportSize);
|
|
2900
|
+
this._scrollPosition = Math.round(position * scrollRange);
|
|
2901
|
+
this._onChange?.(this._scrollPosition);
|
|
2902
|
+
this.emit("change", { position: this._scrollPosition });
|
|
2903
|
+
},
|
|
2904
|
+
...orientation === "vertical" ? {
|
|
2905
|
+
width: 2,
|
|
2906
|
+
height: "100%",
|
|
2907
|
+
marginLeft: "auto"
|
|
2908
|
+
} : {
|
|
2909
|
+
width: "100%",
|
|
2910
|
+
height: 1,
|
|
2911
|
+
marginTop: "auto"
|
|
2912
|
+
},
|
|
2913
|
+
flexGrow: 1,
|
|
2914
|
+
flexShrink: 1,
|
|
2915
|
+
...trackOptions
|
|
2916
|
+
});
|
|
2917
|
+
this.updateSliderFromScrollState();
|
|
2918
|
+
const arrowOpts = arrowOptions ? {
|
|
2919
|
+
foregroundColor: arrowOptions.backgroundColor,
|
|
2920
|
+
backgroundColor: arrowOptions.backgroundColor,
|
|
2921
|
+
attributes: arrowOptions.attributes,
|
|
2922
|
+
...arrowOptions
|
|
2923
|
+
} : {};
|
|
2924
|
+
this.startArrow = new ArrowRenderable(ctx, {
|
|
2925
|
+
alignSelf: "center",
|
|
2926
|
+
visible: this.showArrows,
|
|
2927
|
+
direction: this.orientation === "vertical" ? "up" : "left",
|
|
2928
|
+
height: this.orientation === "vertical" ? 1 : 1,
|
|
2929
|
+
...arrowOpts
|
|
2930
|
+
});
|
|
2931
|
+
this.endArrow = new ArrowRenderable(ctx, {
|
|
2932
|
+
alignSelf: "center",
|
|
2933
|
+
visible: this.showArrows,
|
|
2934
|
+
direction: this.orientation === "vertical" ? "down" : "right",
|
|
2935
|
+
height: this.orientation === "vertical" ? 1 : 1,
|
|
2936
|
+
...arrowOpts
|
|
2937
|
+
});
|
|
2938
|
+
this.add(this.startArrow);
|
|
2939
|
+
this.add(this.slider);
|
|
2940
|
+
this.add(this.endArrow);
|
|
2941
|
+
let startArrowMouseTimeout = undefined;
|
|
2942
|
+
let endArrowMouseTimeout = undefined;
|
|
2943
|
+
this.startArrow.onMouseDown = (event) => {
|
|
2944
|
+
event.stopPropagation();
|
|
2945
|
+
this.scrollBy(-0.5, "viewport");
|
|
2946
|
+
startArrowMouseTimeout = setTimeout(() => {
|
|
2947
|
+
this.scrollBy(-0.5, "viewport");
|
|
2948
|
+
startArrowMouseTimeout = setInterval(() => {
|
|
2949
|
+
this.scrollBy(-0.2, "viewport");
|
|
2950
|
+
}, 200);
|
|
2951
|
+
}, 500);
|
|
2952
|
+
};
|
|
2953
|
+
this.startArrow.onMouseUp = (event) => {
|
|
2954
|
+
event.stopPropagation();
|
|
2955
|
+
clearInterval(startArrowMouseTimeout);
|
|
2956
|
+
};
|
|
2957
|
+
this.endArrow.onMouseDown = (event) => {
|
|
2958
|
+
event.stopPropagation();
|
|
2959
|
+
this.scrollBy(0.5, "viewport");
|
|
2960
|
+
endArrowMouseTimeout = setTimeout(() => {
|
|
2961
|
+
this.scrollBy(0.5, "viewport");
|
|
2962
|
+
endArrowMouseTimeout = setInterval(() => {
|
|
2963
|
+
this.scrollBy(0.2, "viewport");
|
|
2964
|
+
}, 200);
|
|
2965
|
+
}, 500);
|
|
2966
|
+
};
|
|
2967
|
+
this.endArrow.onMouseUp = (event) => {
|
|
2968
|
+
event.stopPropagation();
|
|
2969
|
+
clearInterval(endArrowMouseTimeout);
|
|
2970
|
+
};
|
|
2971
|
+
}
|
|
2972
|
+
set arrowOptions(options) {
|
|
2973
|
+
Object.assign(this.startArrow, options);
|
|
2974
|
+
Object.assign(this.endArrow, options);
|
|
2975
|
+
this.requestRender();
|
|
2976
|
+
}
|
|
2977
|
+
set trackOptions(options) {
|
|
2978
|
+
Object.assign(this.slider, options);
|
|
2979
|
+
this.requestRender();
|
|
2980
|
+
}
|
|
2981
|
+
updateSliderFromScrollState() {
|
|
2982
|
+
const trackSize = this.orientation === "vertical" ? this.slider.height : this.slider.width;
|
|
2983
|
+
const scrollRange = Math.max(0, this._scrollSize - this._viewportSize);
|
|
2984
|
+
if (scrollRange === 0) {
|
|
2985
|
+
this.slider.thumbSize = trackSize;
|
|
2986
|
+
this.slider.thumbPosition = 0;
|
|
2987
|
+
} else {
|
|
2988
|
+
const sizeRatio = this._viewportSize / this._scrollSize;
|
|
2989
|
+
this.slider.thumbSize = Math.max(1, Math.round(sizeRatio * trackSize));
|
|
2990
|
+
const positionRatio = this._scrollPosition / scrollRange;
|
|
2991
|
+
this.slider.thumbPosition = Math.max(0, Math.min(1, positionRatio));
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2994
|
+
scrollBy(delta, unit = "absolute") {
|
|
2995
|
+
const multiplier = unit === "viewport" ? this.viewportSize : unit === "content" ? this.scrollSize : unit === "step" ? this.scrollStep ?? 1 : 1;
|
|
2996
|
+
const resolvedDelta = multiplier * delta;
|
|
2997
|
+
this.scrollPosition += resolvedDelta;
|
|
2998
|
+
}
|
|
2999
|
+
recalculateVisibility() {
|
|
3000
|
+
if (!this._manualVisibility) {
|
|
3001
|
+
const sizeRatio = this.scrollSize <= this.viewportSize ? 1 : this.viewportSize / this.scrollSize;
|
|
3002
|
+
super.visible = sizeRatio < 1;
|
|
3003
|
+
}
|
|
3004
|
+
}
|
|
3005
|
+
handleKeyPress(key) {
|
|
3006
|
+
const keyName = typeof key === "string" ? key : key.name;
|
|
3007
|
+
switch (keyName) {
|
|
3008
|
+
case "left":
|
|
3009
|
+
case "h":
|
|
3010
|
+
if (this.orientation !== "horizontal")
|
|
3011
|
+
return false;
|
|
3012
|
+
this.scrollBy(-1 / 5, "viewport");
|
|
3013
|
+
return true;
|
|
3014
|
+
case "right":
|
|
3015
|
+
case "l":
|
|
3016
|
+
if (this.orientation !== "horizontal")
|
|
3017
|
+
return false;
|
|
3018
|
+
this.scrollBy(1 / 5, "viewport");
|
|
3019
|
+
return true;
|
|
3020
|
+
case "up":
|
|
3021
|
+
case "k":
|
|
3022
|
+
if (this.orientation !== "vertical")
|
|
3023
|
+
return false;
|
|
3024
|
+
this.scrollBy(-1 / 5, "viewport");
|
|
3025
|
+
return true;
|
|
3026
|
+
case "down":
|
|
3027
|
+
case "j":
|
|
3028
|
+
if (this.orientation !== "vertical")
|
|
3029
|
+
return false;
|
|
3030
|
+
this.scrollBy(1 / 5, "viewport");
|
|
3031
|
+
return true;
|
|
3032
|
+
case "pageup":
|
|
3033
|
+
this.scrollBy(-1 / 2, "viewport");
|
|
3034
|
+
return true;
|
|
3035
|
+
case "pagedown":
|
|
3036
|
+
this.scrollBy(1 / 2, "viewport");
|
|
3037
|
+
return true;
|
|
3038
|
+
case "home":
|
|
3039
|
+
this.scrollBy(-1, "content");
|
|
3040
|
+
return true;
|
|
3041
|
+
case "end":
|
|
3042
|
+
this.scrollBy(1, "content");
|
|
3043
|
+
return true;
|
|
3044
|
+
}
|
|
3045
|
+
return false;
|
|
3046
|
+
}
|
|
3047
|
+
}
|
|
3048
|
+
|
|
3049
|
+
class ArrowRenderable extends Renderable {
|
|
3050
|
+
_direction;
|
|
3051
|
+
_foregroundColor;
|
|
3052
|
+
_backgroundColor;
|
|
3053
|
+
_attributes;
|
|
3054
|
+
_arrowChars;
|
|
3055
|
+
constructor(ctx, options) {
|
|
3056
|
+
super(ctx, options);
|
|
3057
|
+
this._direction = options.direction;
|
|
3058
|
+
this._foregroundColor = options.foregroundColor ? parseColor(options.foregroundColor) : RGBA.fromValues(1, 1, 1, 1);
|
|
3059
|
+
this._backgroundColor = options.backgroundColor ? parseColor(options.backgroundColor) : RGBA.fromValues(0, 0, 0, 0);
|
|
3060
|
+
this._attributes = options.attributes ?? 0;
|
|
3061
|
+
this._arrowChars = {
|
|
3062
|
+
up: "\u25E2\u25E3",
|
|
3063
|
+
down: "\u25E5\u25E4",
|
|
3064
|
+
left: " \u25C0 ",
|
|
3065
|
+
right: " \u25B6 ",
|
|
3066
|
+
...options.arrowChars
|
|
3067
|
+
};
|
|
3068
|
+
if (!options.width) {
|
|
3069
|
+
this.width = Bun.stringWidth(this.getArrowChar());
|
|
3070
|
+
}
|
|
3071
|
+
}
|
|
3072
|
+
get direction() {
|
|
3073
|
+
return this._direction;
|
|
3074
|
+
}
|
|
3075
|
+
set direction(value) {
|
|
3076
|
+
if (this._direction !== value) {
|
|
3077
|
+
this._direction = value;
|
|
3078
|
+
this.requestRender();
|
|
3079
|
+
}
|
|
3080
|
+
}
|
|
3081
|
+
get foregroundColor() {
|
|
3082
|
+
return this._foregroundColor;
|
|
3083
|
+
}
|
|
3084
|
+
set foregroundColor(value) {
|
|
3085
|
+
if (this._foregroundColor !== value) {
|
|
3086
|
+
this._foregroundColor = parseColor(value);
|
|
3087
|
+
this.requestRender();
|
|
3088
|
+
}
|
|
3089
|
+
}
|
|
3090
|
+
get backgroundColor() {
|
|
3091
|
+
return this._backgroundColor;
|
|
3092
|
+
}
|
|
3093
|
+
set backgroundColor(value) {
|
|
3094
|
+
if (this._backgroundColor !== value) {
|
|
3095
|
+
this._backgroundColor = parseColor(value);
|
|
3096
|
+
this.requestRender();
|
|
3097
|
+
}
|
|
3098
|
+
}
|
|
3099
|
+
get attributes() {
|
|
3100
|
+
return this._attributes;
|
|
3101
|
+
}
|
|
3102
|
+
set attributes(value) {
|
|
3103
|
+
if (this._attributes !== value) {
|
|
3104
|
+
this._attributes = value;
|
|
3105
|
+
this.requestRender();
|
|
3106
|
+
}
|
|
3107
|
+
}
|
|
3108
|
+
set arrowChars(value) {
|
|
3109
|
+
this._arrowChars = {
|
|
3110
|
+
...this._arrowChars,
|
|
3111
|
+
...value
|
|
3112
|
+
};
|
|
3113
|
+
this.requestRender();
|
|
3114
|
+
}
|
|
3115
|
+
renderSelf(buffer) {
|
|
3116
|
+
const char = this.getArrowChar();
|
|
3117
|
+
buffer.drawText(char, this.x, this.y, this._foregroundColor, this._backgroundColor, this._attributes);
|
|
3118
|
+
}
|
|
3119
|
+
getArrowChar() {
|
|
3120
|
+
switch (this._direction) {
|
|
3121
|
+
case "up":
|
|
3122
|
+
return this._arrowChars.up;
|
|
3123
|
+
case "down":
|
|
3124
|
+
return this._arrowChars.down;
|
|
3125
|
+
case "left":
|
|
3126
|
+
return this._arrowChars.left;
|
|
3127
|
+
case "right":
|
|
3128
|
+
return this._arrowChars.right;
|
|
3129
|
+
default:
|
|
3130
|
+
return "?";
|
|
3131
|
+
}
|
|
3132
|
+
}
|
|
3133
|
+
}
|
|
3134
|
+
|
|
3135
|
+
// src/renderables/ScrollBox.ts
|
|
3136
|
+
class ContentRenderable extends BoxRenderable {
|
|
3137
|
+
viewport;
|
|
3138
|
+
constructor(ctx, viewport, options) {
|
|
3139
|
+
super(ctx, options);
|
|
3140
|
+
this.viewport = viewport;
|
|
3141
|
+
}
|
|
3142
|
+
_getChildren() {
|
|
3143
|
+
return this.getChildrenInViewport(this.viewport);
|
|
3144
|
+
}
|
|
3145
|
+
}
|
|
3146
|
+
|
|
3147
|
+
class ScrollBoxRenderable extends BoxRenderable {
|
|
3148
|
+
static idCounter = 0;
|
|
3149
|
+
internalId = 0;
|
|
3150
|
+
wrapper;
|
|
3151
|
+
viewport;
|
|
3152
|
+
content;
|
|
3153
|
+
horizontalScrollBar;
|
|
3154
|
+
verticalScrollBar;
|
|
3155
|
+
focusable = true;
|
|
3156
|
+
selectionListener;
|
|
3157
|
+
autoScrollMouseX = 0;
|
|
3158
|
+
autoScrollMouseY = 0;
|
|
3159
|
+
autoScrollThresholdVertical = 3;
|
|
3160
|
+
autoScrollThresholdHorizontal = 3;
|
|
3161
|
+
autoScrollSpeedSlow = 6;
|
|
3162
|
+
autoScrollSpeedMedium = 36;
|
|
3163
|
+
autoScrollSpeedFast = 72;
|
|
3164
|
+
isAutoScrolling = false;
|
|
3165
|
+
cachedAutoScrollSpeed = 3;
|
|
3166
|
+
autoScrollAccumulatorX = 0;
|
|
3167
|
+
autoScrollAccumulatorY = 0;
|
|
3168
|
+
get scrollTop() {
|
|
3169
|
+
return this.verticalScrollBar.scrollPosition;
|
|
3170
|
+
}
|
|
3171
|
+
set scrollTop(value) {
|
|
3172
|
+
this.verticalScrollBar.scrollPosition = value;
|
|
3173
|
+
}
|
|
3174
|
+
get scrollLeft() {
|
|
3175
|
+
return this.horizontalScrollBar.scrollPosition;
|
|
3176
|
+
}
|
|
3177
|
+
set scrollLeft(value) {
|
|
3178
|
+
this.horizontalScrollBar.scrollPosition = value;
|
|
3179
|
+
}
|
|
3180
|
+
get scrollWidth() {
|
|
3181
|
+
return this.horizontalScrollBar.scrollSize;
|
|
3182
|
+
}
|
|
3183
|
+
get scrollHeight() {
|
|
3184
|
+
return this.verticalScrollBar.scrollSize;
|
|
3185
|
+
}
|
|
3186
|
+
constructor(ctx, {
|
|
3187
|
+
wrapperOptions,
|
|
3188
|
+
viewportOptions,
|
|
3189
|
+
contentOptions,
|
|
3190
|
+
rootOptions,
|
|
3191
|
+
scrollbarOptions,
|
|
3192
|
+
verticalScrollbarOptions,
|
|
3193
|
+
horizontalScrollbarOptions,
|
|
3194
|
+
...options
|
|
3195
|
+
}) {
|
|
3196
|
+
super(ctx, {
|
|
3197
|
+
flexShrink: 1,
|
|
3198
|
+
flexGrow: 1,
|
|
3199
|
+
flexDirection: "row",
|
|
3200
|
+
flexWrap: "wrap",
|
|
3201
|
+
alignItems: "stretch",
|
|
3202
|
+
...options,
|
|
3203
|
+
...rootOptions
|
|
3204
|
+
});
|
|
3205
|
+
this.internalId = ScrollBoxRenderable.idCounter++;
|
|
3206
|
+
this.wrapper = new BoxRenderable(ctx, {
|
|
3207
|
+
flexDirection: "column",
|
|
3208
|
+
flexGrow: 1,
|
|
3209
|
+
flexShrink: 1,
|
|
3210
|
+
flexBasis: "auto",
|
|
3211
|
+
maxHeight: "100%",
|
|
3212
|
+
maxWidth: "100%",
|
|
3213
|
+
...wrapperOptions,
|
|
3214
|
+
id: `scroll-box-wrapper-${this.internalId}`
|
|
3215
|
+
});
|
|
3216
|
+
super.add(this.wrapper);
|
|
3217
|
+
this.viewport = new BoxRenderable(ctx, {
|
|
3218
|
+
flexDirection: "column",
|
|
3219
|
+
flexGrow: 1,
|
|
3220
|
+
flexShrink: 1,
|
|
3221
|
+
flexBasis: "auto",
|
|
3222
|
+
maxHeight: "100%",
|
|
3223
|
+
maxWidth: "100%",
|
|
3224
|
+
overflow: "scroll",
|
|
3225
|
+
onSizeChange: () => {
|
|
3226
|
+
this.recalculateBarProps();
|
|
3227
|
+
},
|
|
3228
|
+
...viewportOptions,
|
|
3229
|
+
id: `scroll-box-viewport-${this.internalId}`
|
|
3230
|
+
});
|
|
3231
|
+
this.wrapper.add(this.viewport);
|
|
3232
|
+
this.content = new ContentRenderable(ctx, this.viewport, {
|
|
3233
|
+
alignSelf: "flex-start",
|
|
3234
|
+
onSizeChange: () => {
|
|
3235
|
+
this.recalculateBarProps();
|
|
3236
|
+
},
|
|
3237
|
+
...contentOptions,
|
|
3238
|
+
id: `scroll-box-content-${this.internalId}`
|
|
3239
|
+
});
|
|
3240
|
+
this.viewport.add(this.content);
|
|
3241
|
+
this.verticalScrollBar = new ScrollBarRenderable(ctx, {
|
|
3242
|
+
...scrollbarOptions,
|
|
3243
|
+
...verticalScrollbarOptions,
|
|
3244
|
+
arrowOptions: {
|
|
3245
|
+
...scrollbarOptions?.arrowOptions,
|
|
3246
|
+
...verticalScrollbarOptions?.arrowOptions
|
|
3247
|
+
},
|
|
3248
|
+
id: `scroll-box-vertical-scrollbar-${this.internalId}`,
|
|
3249
|
+
orientation: "vertical",
|
|
3250
|
+
onChange: (position) => {
|
|
3251
|
+
this.content.translateY = -position;
|
|
3252
|
+
}
|
|
3253
|
+
});
|
|
3254
|
+
super.add(this.verticalScrollBar);
|
|
3255
|
+
this.horizontalScrollBar = new ScrollBarRenderable(ctx, {
|
|
3256
|
+
...scrollbarOptions,
|
|
3257
|
+
...horizontalScrollbarOptions,
|
|
3258
|
+
arrowOptions: {
|
|
3259
|
+
...scrollbarOptions?.arrowOptions,
|
|
3260
|
+
...horizontalScrollbarOptions?.arrowOptions
|
|
3261
|
+
},
|
|
3262
|
+
id: `scroll-box-horizontal-scrollbar-${this.internalId}`,
|
|
3263
|
+
orientation: "horizontal",
|
|
3264
|
+
onChange: (position) => {
|
|
3265
|
+
this.content.translateX = -position;
|
|
3266
|
+
}
|
|
3267
|
+
});
|
|
3268
|
+
this.wrapper.add(this.horizontalScrollBar);
|
|
3269
|
+
this.recalculateBarProps();
|
|
3270
|
+
this.selectionListener = () => {
|
|
3271
|
+
const selection = this._ctx.getSelection();
|
|
3272
|
+
if (!selection || !selection.isSelecting) {
|
|
3273
|
+
this.stopAutoScroll();
|
|
3274
|
+
}
|
|
3275
|
+
};
|
|
3276
|
+
this._ctx.on("selection", this.selectionListener);
|
|
3277
|
+
}
|
|
3278
|
+
onUpdate(deltaTime) {
|
|
3279
|
+
this.handleAutoScroll(deltaTime);
|
|
3280
|
+
}
|
|
3281
|
+
scrollBy(delta, unit = "absolute") {
|
|
3282
|
+
if (typeof delta === "number") {
|
|
3283
|
+
this.verticalScrollBar.scrollBy(delta, unit);
|
|
3284
|
+
} else {
|
|
3285
|
+
this.verticalScrollBar.scrollBy(delta.y, unit);
|
|
3286
|
+
this.horizontalScrollBar.scrollBy(delta.x, unit);
|
|
3287
|
+
}
|
|
3288
|
+
}
|
|
3289
|
+
scrollTo(position) {
|
|
3290
|
+
if (typeof position === "number") {
|
|
3291
|
+
this.scrollTop = position;
|
|
3292
|
+
} else {
|
|
3293
|
+
this.scrollTop = position.y;
|
|
3294
|
+
this.scrollLeft = position.x;
|
|
3295
|
+
}
|
|
3296
|
+
}
|
|
3297
|
+
add(obj, index) {
|
|
3298
|
+
return this.content.add(obj, index);
|
|
3299
|
+
}
|
|
3300
|
+
remove(id) {
|
|
3301
|
+
this.content.remove(id);
|
|
3302
|
+
}
|
|
3303
|
+
getChildren() {
|
|
3304
|
+
return this.content.getChildren();
|
|
3305
|
+
}
|
|
3306
|
+
onMouseEvent(event) {
|
|
3307
|
+
if (event.type === "scroll") {
|
|
3308
|
+
let dir = event.scroll?.direction;
|
|
3309
|
+
if (event.modifiers.shift)
|
|
3310
|
+
dir = dir === "up" ? "left" : dir === "down" ? "right" : dir === "right" ? "down" : "up";
|
|
3311
|
+
if (dir === "up")
|
|
3312
|
+
this.scrollTop -= event.scroll?.delta ?? 0;
|
|
3313
|
+
else if (dir === "down")
|
|
3314
|
+
this.scrollTop += event.scroll?.delta ?? 0;
|
|
3315
|
+
else if (dir === "left")
|
|
3316
|
+
this.scrollLeft -= event.scroll?.delta ?? 0;
|
|
3317
|
+
else if (dir === "right")
|
|
3318
|
+
this.scrollLeft += event.scroll?.delta ?? 0;
|
|
3319
|
+
}
|
|
3320
|
+
if (event.type === "drag" && event.isSelecting) {
|
|
3321
|
+
this.updateAutoScroll(event.x, event.y);
|
|
3322
|
+
} else if (event.type === "up") {
|
|
3323
|
+
this.stopAutoScroll();
|
|
3324
|
+
}
|
|
3325
|
+
}
|
|
3326
|
+
handleKeyPress(key) {
|
|
3327
|
+
if (this.verticalScrollBar.handleKeyPress(key))
|
|
3328
|
+
return true;
|
|
3329
|
+
if (this.horizontalScrollBar.handleKeyPress(key))
|
|
3330
|
+
return true;
|
|
3331
|
+
return false;
|
|
3332
|
+
}
|
|
3333
|
+
startAutoScroll(mouseX, mouseY) {
|
|
3334
|
+
this.stopAutoScroll();
|
|
3335
|
+
this.autoScrollMouseX = mouseX;
|
|
3336
|
+
this.autoScrollMouseY = mouseY;
|
|
3337
|
+
this.cachedAutoScrollSpeed = this.getAutoScrollSpeed(mouseX, mouseY);
|
|
3338
|
+
this.isAutoScrolling = true;
|
|
3339
|
+
if (!this.live) {
|
|
3340
|
+
this.live = true;
|
|
3341
|
+
}
|
|
3342
|
+
}
|
|
3343
|
+
updateAutoScroll(mouseX, mouseY) {
|
|
3344
|
+
this.autoScrollMouseX = mouseX;
|
|
3345
|
+
this.autoScrollMouseY = mouseY;
|
|
3346
|
+
this.cachedAutoScrollSpeed = this.getAutoScrollSpeed(mouseX, mouseY);
|
|
3347
|
+
const scrollX = this.getAutoScrollDirectionX(mouseX);
|
|
3348
|
+
const scrollY = this.getAutoScrollDirectionY(mouseY);
|
|
3349
|
+
if (scrollX === 0 && scrollY === 0) {
|
|
3350
|
+
this.stopAutoScroll();
|
|
3351
|
+
} else if (!this.isAutoScrolling) {
|
|
3352
|
+
this.startAutoScroll(mouseX, mouseY);
|
|
3353
|
+
}
|
|
3354
|
+
}
|
|
3355
|
+
stopAutoScroll() {
|
|
3356
|
+
const wasAutoScrolling = this.isAutoScrolling;
|
|
3357
|
+
this.isAutoScrolling = false;
|
|
3358
|
+
this.autoScrollAccumulatorX = 0;
|
|
3359
|
+
this.autoScrollAccumulatorY = 0;
|
|
3360
|
+
if (wasAutoScrolling && !this.hasOtherLiveReasons()) {
|
|
3361
|
+
this.live = false;
|
|
3362
|
+
}
|
|
3363
|
+
}
|
|
3364
|
+
hasOtherLiveReasons() {
|
|
3365
|
+
return false;
|
|
3366
|
+
}
|
|
3367
|
+
handleAutoScroll(deltaTime) {
|
|
3368
|
+
if (!this.isAutoScrolling)
|
|
3369
|
+
return;
|
|
3370
|
+
const scrollX = this.getAutoScrollDirectionX(this.autoScrollMouseX);
|
|
3371
|
+
const scrollY = this.getAutoScrollDirectionY(this.autoScrollMouseY);
|
|
3372
|
+
const scrollAmount = this.cachedAutoScrollSpeed * (deltaTime / 1000);
|
|
3373
|
+
let scrolled = false;
|
|
3374
|
+
if (scrollX !== 0) {
|
|
3375
|
+
this.autoScrollAccumulatorX += scrollX * scrollAmount;
|
|
3376
|
+
const integerScrollX = Math.trunc(this.autoScrollAccumulatorX);
|
|
3377
|
+
if (integerScrollX !== 0) {
|
|
3378
|
+
this.scrollLeft += integerScrollX;
|
|
3379
|
+
this.autoScrollAccumulatorX -= integerScrollX;
|
|
3380
|
+
scrolled = true;
|
|
3381
|
+
}
|
|
3382
|
+
}
|
|
3383
|
+
if (scrollY !== 0) {
|
|
3384
|
+
this.autoScrollAccumulatorY += scrollY * scrollAmount;
|
|
3385
|
+
const integerScrollY = Math.trunc(this.autoScrollAccumulatorY);
|
|
3386
|
+
if (integerScrollY !== 0) {
|
|
3387
|
+
this.scrollTop += integerScrollY;
|
|
3388
|
+
this.autoScrollAccumulatorY -= integerScrollY;
|
|
3389
|
+
scrolled = true;
|
|
3390
|
+
}
|
|
3391
|
+
}
|
|
3392
|
+
if (scrolled) {
|
|
3393
|
+
this._ctx.requestSelectionUpdate();
|
|
3394
|
+
}
|
|
3395
|
+
if (scrollX === 0 && scrollY === 0) {
|
|
3396
|
+
this.stopAutoScroll();
|
|
3397
|
+
}
|
|
3398
|
+
}
|
|
3399
|
+
getAutoScrollDirectionX(mouseX) {
|
|
3400
|
+
const relativeX = mouseX - this.x;
|
|
3401
|
+
const distToLeft = relativeX;
|
|
3402
|
+
const distToRight = this.width - relativeX;
|
|
3403
|
+
if (distToLeft <= this.autoScrollThresholdHorizontal) {
|
|
3404
|
+
return this.scrollLeft > 0 ? -1 : 0;
|
|
3405
|
+
} else if (distToRight <= this.autoScrollThresholdHorizontal) {
|
|
3406
|
+
const maxScrollLeft = this.scrollWidth - this.viewport.width;
|
|
3407
|
+
return this.scrollLeft < maxScrollLeft ? 1 : 0;
|
|
3408
|
+
}
|
|
3409
|
+
return 0;
|
|
3410
|
+
}
|
|
3411
|
+
getAutoScrollDirectionY(mouseY) {
|
|
3412
|
+
const relativeY = mouseY - this.y;
|
|
3413
|
+
const distToTop = relativeY;
|
|
3414
|
+
const distToBottom = this.height - relativeY;
|
|
3415
|
+
if (distToTop <= this.autoScrollThresholdVertical) {
|
|
3416
|
+
return this.scrollTop > 0 ? -1 : 0;
|
|
3417
|
+
} else if (distToBottom <= this.autoScrollThresholdVertical) {
|
|
3418
|
+
const maxScrollTop = this.scrollHeight - this.viewport.height;
|
|
3419
|
+
return this.scrollTop < maxScrollTop ? 1 : 0;
|
|
3420
|
+
}
|
|
3421
|
+
return 0;
|
|
3422
|
+
}
|
|
3423
|
+
getAutoScrollSpeed(mouseX, mouseY) {
|
|
3424
|
+
const relativeX = mouseX - this.x;
|
|
3425
|
+
const relativeY = mouseY - this.y;
|
|
3426
|
+
const distToLeft = relativeX;
|
|
3427
|
+
const distToRight = this.width - relativeX;
|
|
3428
|
+
const distToTop = relativeY;
|
|
3429
|
+
const distToBottom = this.height - relativeY;
|
|
3430
|
+
const minDistance = Math.min(distToLeft, distToRight, distToTop, distToBottom);
|
|
3431
|
+
if (minDistance <= 1) {
|
|
3432
|
+
return this.autoScrollSpeedFast;
|
|
3433
|
+
} else if (minDistance <= 2) {
|
|
3434
|
+
return this.autoScrollSpeedMedium;
|
|
3435
|
+
} else {
|
|
3436
|
+
return this.autoScrollSpeedSlow;
|
|
3437
|
+
}
|
|
3438
|
+
}
|
|
3439
|
+
recalculateBarProps() {
|
|
3440
|
+
this.verticalScrollBar.scrollSize = this.content.height;
|
|
3441
|
+
this.verticalScrollBar.viewportSize = this.viewport.height;
|
|
3442
|
+
this.horizontalScrollBar.scrollSize = this.content.width;
|
|
3443
|
+
this.horizontalScrollBar.viewportSize = this.viewport.width;
|
|
3444
|
+
}
|
|
3445
|
+
set rootOptions(options) {
|
|
3446
|
+
Object.assign(this, options);
|
|
3447
|
+
this.requestRender();
|
|
3448
|
+
}
|
|
3449
|
+
set wrapperOptions(options) {
|
|
3450
|
+
Object.assign(this.wrapper, options);
|
|
3451
|
+
this.requestRender();
|
|
3452
|
+
}
|
|
3453
|
+
set viewportOptions(options) {
|
|
3454
|
+
Object.assign(this.viewport, options);
|
|
3455
|
+
this.requestRender();
|
|
3456
|
+
}
|
|
3457
|
+
set contentOptions(options) {
|
|
3458
|
+
Object.assign(this.content, options);
|
|
3459
|
+
this.requestRender();
|
|
3460
|
+
}
|
|
3461
|
+
set scrollbarOptions(options) {
|
|
3462
|
+
Object.assign(this.verticalScrollBar, options);
|
|
3463
|
+
Object.assign(this.horizontalScrollBar, options);
|
|
3464
|
+
this.requestRender();
|
|
3465
|
+
}
|
|
3466
|
+
set verticalScrollbarOptions(options) {
|
|
3467
|
+
Object.assign(this.verticalScrollBar, options);
|
|
3468
|
+
this.requestRender();
|
|
3469
|
+
}
|
|
3470
|
+
set horizontalScrollbarOptions(options) {
|
|
3471
|
+
Object.assign(this.horizontalScrollBar, options);
|
|
3472
|
+
this.requestRender();
|
|
3473
|
+
}
|
|
3474
|
+
destroySelf() {
|
|
3475
|
+
if (this.selectionListener) {
|
|
3476
|
+
this._ctx.off("selection", this.selectionListener);
|
|
3477
|
+
this.selectionListener = undefined;
|
|
3478
|
+
}
|
|
3479
|
+
super.destroySelf();
|
|
2554
3480
|
}
|
|
2555
3481
|
}
|
|
2556
3482
|
// src/renderables/composition/constructs.ts
|
|
@@ -2630,9 +3556,11 @@ export {
|
|
|
2630
3556
|
isValidPercentage,
|
|
2631
3557
|
isVNode,
|
|
2632
3558
|
isSizeType,
|
|
2633
|
-
|
|
3559
|
+
isRenderable,
|
|
3560
|
+
isPositionTypeType,
|
|
2634
3561
|
isPositionType,
|
|
2635
3562
|
isPaddingType,
|
|
3563
|
+
isOverflowType,
|
|
2636
3564
|
isMarginType,
|
|
2637
3565
|
isFlexBasisType,
|
|
2638
3566
|
isDimensionType,
|
|
@@ -2658,6 +3586,7 @@ export {
|
|
|
2658
3586
|
createTextAttributes,
|
|
2659
3587
|
createCliRenderer,
|
|
2660
3588
|
coordinateToCharacterIndex,
|
|
3589
|
+
convertGlobalToLocalSelection,
|
|
2661
3590
|
capture,
|
|
2662
3591
|
brightYellow,
|
|
2663
3592
|
brightWhite,
|
|
@@ -2692,7 +3621,6 @@ export {
|
|
|
2692
3621
|
VRenderable,
|
|
2693
3622
|
TrackedNode,
|
|
2694
3623
|
Timeline,
|
|
2695
|
-
TextSelectionHelper,
|
|
2696
3624
|
TextRenderable,
|
|
2697
3625
|
TextBuffer,
|
|
2698
3626
|
TextAttributes,
|
|
@@ -2707,6 +3635,8 @@ export {
|
|
|
2707
3635
|
SelectRenderableEvents,
|
|
2708
3636
|
SelectRenderable,
|
|
2709
3637
|
Select,
|
|
3638
|
+
ScrollBoxRenderable,
|
|
3639
|
+
ScrollBarRenderable,
|
|
2710
3640
|
RootRenderable,
|
|
2711
3641
|
RenderableEvents,
|
|
2712
3642
|
Renderable,
|
|
@@ -2715,6 +3645,7 @@ export {
|
|
|
2715
3645
|
MouseParser,
|
|
2716
3646
|
MouseEvent,
|
|
2717
3647
|
MouseButton,
|
|
3648
|
+
LogLevel,
|
|
2718
3649
|
LayoutEvents,
|
|
2719
3650
|
KeyHandler,
|
|
2720
3651
|
InputRenderableEvents,
|
|
@@ -2735,10 +3666,11 @@ export {
|
|
|
2735
3666
|
BorderCharArrays,
|
|
2736
3667
|
BlurEffect,
|
|
2737
3668
|
BloomEffect,
|
|
3669
|
+
ArrowRenderable,
|
|
2738
3670
|
ASCIIFontSelectionHelper,
|
|
2739
3671
|
ASCIIFontRenderable,
|
|
2740
3672
|
ASCIIFont
|
|
2741
3673
|
};
|
|
2742
3674
|
|
|
2743
|
-
//# debugId=
|
|
3675
|
+
//# debugId=B627209D76BECE1A64756E2164756E21
|
|
2744
3676
|
//# sourceMappingURL=index.js.map
|