@nsshunt/stsui 1.11.24 → 1.11.25
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/dist/stsui.mjs +439 -460
- package/dist/stsui.mjs.map +1 -1
- package/dist/stsui.umd.js +440 -461
- package/dist/stsui.umd.js.map +1 -1
- package/package.json +3 -3
package/dist/stsui.mjs
CHANGED
|
@@ -1,21 +1,9 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __typeError = (msg) => {
|
|
3
|
-
throw TypeError(msg);
|
|
4
|
-
};
|
|
5
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
7
|
-
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
8
|
-
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
9
|
-
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
10
|
-
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
11
|
-
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
12
|
-
var _cursor, _renderPanelFn, _cursorInfo, _CalcBoxPos, _UpdateUIBoxPos, _ReSize, _UpdatePanelPosition, _STSUIFrame_instances, SetupPanels_fn, UpdateUI_fn;
|
|
13
1
|
import EventEmitter from "node:events";
|
|
14
2
|
import blessed from "blessed";
|
|
15
3
|
class MenuBar {
|
|
4
|
+
listb = null;
|
|
16
5
|
// options := { screen: <blessed screen>, top: <bool>, menuitems: [ { text: <string>, key: <string>, cb: <call back func> } ] }
|
|
17
6
|
constructor(screen, options) {
|
|
18
|
-
__publicField(this, "listb", null);
|
|
19
7
|
const compoptions = {
|
|
20
8
|
parent: screen,
|
|
21
9
|
left: 0,
|
|
@@ -62,6 +50,23 @@ class MenuBar {
|
|
|
62
50
|
}
|
|
63
51
|
}
|
|
64
52
|
class STSUIFrame extends EventEmitter {
|
|
53
|
+
//export class STSUIFrame {
|
|
54
|
+
uiBoxes = {};
|
|
55
|
+
// { box: <<blessed box>>, boxHeader: <<blessed box>> }
|
|
56
|
+
screen = null;
|
|
57
|
+
#cursor = 0;
|
|
58
|
+
// panel index with the complete model data.
|
|
59
|
+
#renderPanelFn = null;
|
|
60
|
+
screenHeaderText = "...";
|
|
61
|
+
minRows = 1;
|
|
62
|
+
minCols = 1;
|
|
63
|
+
minWidth = 40;
|
|
64
|
+
minHeight = 7;
|
|
65
|
+
#cursorInfo = null;
|
|
66
|
+
sortInfo = null;
|
|
67
|
+
// Current sort mode UI box control
|
|
68
|
+
screenHeader = null;
|
|
69
|
+
uidata;
|
|
65
70
|
/**
|
|
66
71
|
*
|
|
67
72
|
* @param {*} data The screen layout data. Schema: { title: <str>,
|
|
@@ -71,353 +76,254 @@ class STSUIFrame extends EventEmitter {
|
|
|
71
76
|
*/
|
|
72
77
|
constructor(data, renderPanelFn = null) {
|
|
73
78
|
super();
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const rows = this.uidata.grid.rows;
|
|
106
|
-
const cols = this.uidata.grid.cols;
|
|
107
|
-
const pos = panel.pos;
|
|
108
|
-
const colWidth = Math.floor(screenWidth / cols);
|
|
109
|
-
const rowHeight = Math.floor(screenHeight / rows);
|
|
110
|
-
let topoffset = 0;
|
|
111
|
-
if (this.uidata.menu !== null) {
|
|
112
|
-
for (const [, value] of Object.entries(this.uidata.menu)) {
|
|
113
|
-
if (value.top === true) {
|
|
114
|
-
topoffset = 1;
|
|
115
|
-
break;
|
|
116
|
-
}
|
|
79
|
+
this.uidata = data;
|
|
80
|
+
this.#renderPanelFn = renderPanelFn;
|
|
81
|
+
this.SetupUI();
|
|
82
|
+
}
|
|
83
|
+
get blessed() {
|
|
84
|
+
return blessed;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
*
|
|
88
|
+
* @param {number} position The index (0 based) for the panel item to be calculated
|
|
89
|
+
* @returns object with top, left, width and height correctly set
|
|
90
|
+
*/
|
|
91
|
+
#CalcBoxPos = (panel) => {
|
|
92
|
+
if (!this.screen) return null;
|
|
93
|
+
if (!panel.pos) return null;
|
|
94
|
+
let screenHeight = this.screen.height;
|
|
95
|
+
if (this.uidata.menu !== null) {
|
|
96
|
+
screenHeight -= this.uidata.menu.length;
|
|
97
|
+
}
|
|
98
|
+
const screenWidth = this.screen.width;
|
|
99
|
+
const rows = this.uidata.grid.rows;
|
|
100
|
+
const cols = this.uidata.grid.cols;
|
|
101
|
+
const pos = panel.pos;
|
|
102
|
+
const colWidth = Math.floor(screenWidth / cols);
|
|
103
|
+
const rowHeight = Math.floor(screenHeight / rows);
|
|
104
|
+
let topoffset = 0;
|
|
105
|
+
if (this.uidata.menu !== null) {
|
|
106
|
+
for (const [, value] of Object.entries(this.uidata.menu)) {
|
|
107
|
+
if (value.top === true) {
|
|
108
|
+
topoffset = 1;
|
|
109
|
+
break;
|
|
117
110
|
}
|
|
118
111
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
112
|
+
}
|
|
113
|
+
const boxPos = {
|
|
114
|
+
top: pos.row * rowHeight + topoffset,
|
|
115
|
+
left: pos.col * colWidth,
|
|
116
|
+
width: colWidth * pos.colSpan,
|
|
117
|
+
height: rowHeight * pos.rowSpan
|
|
118
|
+
};
|
|
119
|
+
if (pos.col + pos.colSpan === cols) {
|
|
120
|
+
boxPos.width = screenWidth - pos.col * colWidth;
|
|
121
|
+
}
|
|
122
|
+
if (pos.row + pos.rowSpan === rows) {
|
|
123
|
+
boxPos.height = screenHeight - pos.row * rowHeight;
|
|
124
|
+
}
|
|
125
|
+
return boxPos;
|
|
126
|
+
};
|
|
127
|
+
#UpdateUIBoxPos = (panel, uiBox) => {
|
|
128
|
+
const pos = this.#CalcBoxPos(panel);
|
|
129
|
+
if (!pos) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
uiBox.box.top = pos.top;
|
|
133
|
+
uiBox.box.left = pos.left;
|
|
134
|
+
uiBox.box.width = pos.width;
|
|
135
|
+
uiBox.box.height = pos.height;
|
|
136
|
+
uiBox.boxHeader.top = pos.top;
|
|
137
|
+
uiBox.boxHeader.left = pos.left + 2;
|
|
138
|
+
if (typeof panel.widgets !== "undefined" && panel.widgets !== null) {
|
|
139
|
+
for (const [, value] of Object.entries(panel.widgets)) {
|
|
140
|
+
if (value.widget === "log") {
|
|
141
|
+
const widget = uiBox.box.get(value.widget);
|
|
142
|
+
if (widget.position.top >= uiBox.box.height - 4) {
|
|
143
|
+
widget.position.top = uiBox.box.height - 4;
|
|
144
|
+
} else {
|
|
145
|
+
if (value.options.top) {
|
|
146
|
+
widget.position.top = value.options.top;
|
|
154
147
|
}
|
|
155
148
|
}
|
|
156
149
|
}
|
|
157
150
|
}
|
|
158
|
-
});
|
|
159
|
-
/**
|
|
160
|
-
* ReSize the grid layout
|
|
161
|
-
*/
|
|
162
|
-
__privateAdd(this, _ReSize, () => {
|
|
163
|
-
for (const [, value] of Object.entries(this.uiBoxes)) {
|
|
164
|
-
__privateGet(this, _UpdateUIBoxPos).call(this, value.box.get("panel"), value);
|
|
165
|
-
}
|
|
166
|
-
});
|
|
167
|
-
__privateAdd(this, _UpdatePanelPosition, (panel, row, col, uiBox) => {
|
|
168
|
-
panel.pos = { row, col, rowSpan: 1, colSpan: 1 };
|
|
169
|
-
__privateGet(this, _UpdateUIBoxPos).call(this, panel, uiBox);
|
|
170
|
-
uiBox.boxHeader.setContent(panel.panelHeader);
|
|
171
|
-
});
|
|
172
|
-
/*
|
|
173
|
-
ClickEx(panel: any) {
|
|
174
|
-
//@@ override in sub-class
|
|
175
151
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
//@@ override in sub-class
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
EscapeEx() {
|
|
213
|
-
//@@ override in sub-class
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* ReSize the grid layout
|
|
155
|
+
*/
|
|
156
|
+
#ReSize = () => {
|
|
157
|
+
for (const [, value] of Object.entries(this.uiBoxes)) {
|
|
158
|
+
this.#UpdateUIBoxPos(value.box.get("panel"), value);
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
#UpdatePanelPosition = (panel, row, col, uiBox) => {
|
|
162
|
+
panel.pos = { row, col, rowSpan: 1, colSpan: 1 };
|
|
163
|
+
this.#UpdateUIBoxPos(panel, uiBox);
|
|
164
|
+
uiBox.boxHeader.setContent(panel.panelHeader);
|
|
165
|
+
};
|
|
166
|
+
/*
|
|
167
|
+
ClickEx(panel: any) {
|
|
168
|
+
//@@ override in sub-class
|
|
169
|
+
}
|
|
170
|
+
*/
|
|
171
|
+
CreateWidget = (widgetName, widgetoptions) => {
|
|
172
|
+
const widget = blessed[widgetName].call(this, widgetoptions);
|
|
173
|
+
return widget;
|
|
174
|
+
};
|
|
175
|
+
CreateWidgetEx(widgetName, widgetoptions) {
|
|
176
|
+
const widget = blessed[widgetName].call(this, widgetoptions);
|
|
177
|
+
return widget;
|
|
178
|
+
}
|
|
179
|
+
SetupWidgets = (box, panel, parent, blessedWidgets) => {
|
|
180
|
+
for (const [blessedWidgetKey, blessedWidgetDetails] of Object.entries(blessedWidgets)) {
|
|
181
|
+
const widgetoptions = { ...blessedWidgetDetails.options };
|
|
182
|
+
if (box) {
|
|
183
|
+
if (widgetoptions.top && widgetoptions.top >= box.height - 3) {
|
|
184
|
+
widgetoptions.top = box.height - 4;
|
|
214
185
|
}
|
|
215
|
-
*/
|
|
216
|
-
// https://www.npmjs.com/package/blessed
|
|
217
|
-
// data:= { title: <str>,
|
|
218
|
-
// grid: { rows: <int>, cols: <int> },
|
|
219
|
-
// menu: [ { top: <bool>, menuitems: [ { text: <string>, key: <string>, cb: <func> } ] } ]
|
|
220
|
-
// panels: [ { id: <str>, pos: { row: <int>, col: <int>, rowSpan: <int>, colSpan: <int> }, template: <str> } ] }
|
|
221
|
-
/**
|
|
222
|
-
*
|
|
223
|
-
* @param {*} data UI Data
|
|
224
|
-
*/
|
|
225
|
-
__publicField(this, "SetupUI", () => {
|
|
226
|
-
this.DestroyUI();
|
|
227
|
-
if (this.screen === null) {
|
|
228
|
-
this.screen = blessed.screen({
|
|
229
|
-
smartCSR: true
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
if (!this.screen) {
|
|
233
|
-
return;
|
|
234
186
|
}
|
|
235
|
-
const
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
187
|
+
const widget = blessed[blessedWidgetDetails.widget].call(this, widgetoptions);
|
|
188
|
+
widget.set("id", blessedWidgetDetails.id);
|
|
189
|
+
parent.append(widget);
|
|
190
|
+
parent.set(blessedWidgetDetails.widget, widget);
|
|
191
|
+
parent.set(`__blessedWidgetKey__${blessedWidgetKey}`, widget);
|
|
192
|
+
if (blessedWidgetDetails.events) {
|
|
193
|
+
for (const [eventName, eventDetails] of Object.entries(blessedWidgetDetails.events)) {
|
|
194
|
+
widget.on(eventName, () => {
|
|
195
|
+
eventDetails.cb(panel, widget, parent);
|
|
196
|
+
});
|
|
244
197
|
}
|
|
245
198
|
}
|
|
246
|
-
this.
|
|
247
|
-
|
|
248
|
-
this.
|
|
249
|
-
});
|
|
250
|
-
this.screen.key(["escape"], () => {
|
|
251
|
-
this.emit("escape");
|
|
252
|
-
});
|
|
253
|
-
__privateMethod(this, _STSUIFrame_instances, SetupPanels_fn).call(this);
|
|
254
|
-
__privateSet(this, _cursorInfo, blessed.box({
|
|
255
|
-
parent: this.screen,
|
|
256
|
-
bottom: 0,
|
|
257
|
-
right: 0,
|
|
258
|
-
width: "shrink",
|
|
259
|
-
height: 1,
|
|
260
|
-
style: {
|
|
261
|
-
bg: "gray",
|
|
262
|
-
fg: "white"
|
|
263
|
-
},
|
|
264
|
-
keys: false,
|
|
265
|
-
// Do not allow default key handling for this box
|
|
266
|
-
mouse: false,
|
|
267
|
-
content: "",
|
|
268
|
-
tags: true
|
|
269
|
-
// Allow style in-line tags such as bolt, italics, etc.
|
|
270
|
-
}));
|
|
271
|
-
this.sortInfo = blessed.box({
|
|
272
|
-
parent: this.screen,
|
|
273
|
-
top: 0,
|
|
274
|
-
right: 0,
|
|
275
|
-
width: "shrink",
|
|
276
|
-
height: 1,
|
|
277
|
-
style: {
|
|
278
|
-
bg: "gray",
|
|
279
|
-
fg: "white"
|
|
280
|
-
},
|
|
281
|
-
keys: false,
|
|
282
|
-
// Do not allow default key handling for this box
|
|
283
|
-
mouse: false,
|
|
284
|
-
content: "",
|
|
285
|
-
tags: true
|
|
286
|
-
// Allow style in-line tags such as bolt, italics, etc.
|
|
287
|
-
});
|
|
288
|
-
this.screenHeader = blessed.box({
|
|
289
|
-
parent: this.screen,
|
|
290
|
-
top: 0,
|
|
291
|
-
left: "center",
|
|
292
|
-
width: "shrink",
|
|
293
|
-
height: 1,
|
|
294
|
-
style: {
|
|
295
|
-
bg: "gray",
|
|
296
|
-
fg: "white"
|
|
297
|
-
},
|
|
298
|
-
keys: false,
|
|
299
|
-
// Do not allow default key handling for this box
|
|
300
|
-
mouse: false,
|
|
301
|
-
content: `[ ... ]`,
|
|
302
|
-
tags: true
|
|
303
|
-
// Allow style in-line tags such as bolt, italics, etc.
|
|
304
|
-
});
|
|
305
|
-
this.UpdateCursorInfo();
|
|
306
|
-
this.UpdateSortInfo("Default");
|
|
307
|
-
this.UpdateScreenHeader(this.screenHeaderText);
|
|
308
|
-
this.Render();
|
|
309
|
-
});
|
|
310
|
-
__publicField(this, "UpdateCursorInfo", () => {
|
|
311
|
-
if (__privateGet(this, _cursorInfo)) {
|
|
312
|
-
__privateGet(this, _cursorInfo).setContent(`Cursor: ${__privateGet(this, _cursor)} / ${this.TotalPanelNumber}`);
|
|
199
|
+
this.emit("widgetsetup", box, panel, widget);
|
|
200
|
+
if (blessedWidgetDetails.children) {
|
|
201
|
+
this.SetupWidgets(null, panel, widget, blessedWidgetDetails.children);
|
|
313
202
|
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
if (
|
|
328
|
-
this.
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
this.uidata.grid.rows--;
|
|
336
|
-
this.CheckCursor();
|
|
337
|
-
__privateMethod(this, _STSUIFrame_instances, UpdateUI_fn).call(this);
|
|
338
|
-
}
|
|
339
|
-
});
|
|
340
|
-
__publicField(this, "IncCols", () => {
|
|
341
|
-
if (this.screen && this.screen.width / (this.uidata.grid.cols + 1) > this.minWidth) {
|
|
342
|
-
this.uidata.grid.cols++;
|
|
343
|
-
this.CheckCursor();
|
|
344
|
-
__privateMethod(this, _STSUIFrame_instances, UpdateUI_fn).call(this);
|
|
345
|
-
}
|
|
346
|
-
});
|
|
347
|
-
__publicField(this, "DecCols", () => {
|
|
348
|
-
if (this.uidata.grid.cols > this.minCols) {
|
|
349
|
-
this.uidata.grid.cols--;
|
|
350
|
-
this.CheckCursor();
|
|
351
|
-
__privateMethod(this, _STSUIFrame_instances, UpdateUI_fn).call(this);
|
|
352
|
-
}
|
|
353
|
-
});
|
|
354
|
-
__publicField(this, "CheckCursor", () => {
|
|
355
|
-
if (__privateGet(this, _cursor) > this.TotalPanelNumber - this.ScreenCells) {
|
|
356
|
-
__privateSet(this, _cursor, this.TotalPanelNumber - this.ScreenCells);
|
|
357
|
-
if (__privateGet(this, _cursor) < 0) {
|
|
358
|
-
__privateSet(this, _cursor, 0);
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
/**
|
|
206
|
+
*
|
|
207
|
+
* Setup all panels
|
|
208
|
+
*/
|
|
209
|
+
#SetupPanels() {
|
|
210
|
+
if (!this.screen) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
const panelKeys = Object.keys(this.uidata.panels);
|
|
214
|
+
const uiBoxIds = Object.keys(this.uiBoxes);
|
|
215
|
+
for (let i = 0; i < uiBoxIds.length; i++) {
|
|
216
|
+
if (typeof this.uidata.panels[uiBoxIds[i]] === "undefined") {
|
|
217
|
+
let uiBox = this.uiBoxes[uiBoxIds[i]];
|
|
218
|
+
if (typeof uiBox !== "undefined") {
|
|
219
|
+
this.emit("preremovebox", uiBox.box, uiBox.box.get("panel"));
|
|
220
|
+
this.screen.remove(uiBox.boxHeader);
|
|
221
|
+
this.screen.remove(uiBox.box);
|
|
222
|
+
uiBox = null;
|
|
223
|
+
delete this.uiBoxes[uiBoxIds[i]];
|
|
359
224
|
}
|
|
360
225
|
}
|
|
361
|
-
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
const
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
226
|
+
}
|
|
227
|
+
const touched = {};
|
|
228
|
+
for (let i = 0; i < this.uidata.grid.cols * this.uidata.grid.rows; i++) {
|
|
229
|
+
const gridPos = this.#cursor + i;
|
|
230
|
+
const col = i % this.uidata.grid.cols;
|
|
231
|
+
const row = Math.floor(i / this.uidata.grid.cols);
|
|
232
|
+
const panel = this.uidata.panels[panelKeys[gridPos]];
|
|
233
|
+
if (typeof panel !== "undefined") {
|
|
234
|
+
if (typeof this.uiBoxes[panel.id] === "undefined") {
|
|
235
|
+
panel.pos = { row, col, rowSpan: 1, colSpan: 1 };
|
|
236
|
+
const calculatedBoxPos = this.#CalcBoxPos(panel);
|
|
237
|
+
if (!calculatedBoxPos) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
const { top, left, width, height } = this.#CalcBoxPos(panel);
|
|
241
|
+
const box = blessed.box({
|
|
242
|
+
parent: this.screen,
|
|
243
|
+
top,
|
|
244
|
+
left,
|
|
245
|
+
width,
|
|
246
|
+
height,
|
|
247
|
+
style: {
|
|
248
|
+
bg: "#101010",
|
|
249
|
+
fg: "white"
|
|
250
|
+
},
|
|
251
|
+
border: {
|
|
252
|
+
type: "line"
|
|
253
|
+
},
|
|
254
|
+
keys: false,
|
|
255
|
+
// Do not allow default key handling for this box
|
|
256
|
+
tags: true
|
|
257
|
+
// Allow style in-line tags such as bolt, italics, etc.
|
|
258
|
+
});
|
|
259
|
+
const boxHeader = blessed.box({
|
|
260
|
+
parent: this.screen,
|
|
261
|
+
top,
|
|
262
|
+
left: left + 2,
|
|
263
|
+
width: "shrink",
|
|
264
|
+
height: 1,
|
|
265
|
+
style: {
|
|
266
|
+
bg: "gray",
|
|
267
|
+
fg: "white"
|
|
268
|
+
},
|
|
269
|
+
keys: false,
|
|
270
|
+
// Do not allow default key handling for this box
|
|
271
|
+
mouse: false,
|
|
272
|
+
content: panel.panelHeader,
|
|
273
|
+
tags: true
|
|
274
|
+
// Allow style in-line tags such as bold, italics, etc.
|
|
275
|
+
});
|
|
276
|
+
this.uiBoxes[panel.id] = { box, boxHeader };
|
|
277
|
+
boxHeader.setIndex(-1);
|
|
278
|
+
box.on("click", () => {
|
|
279
|
+
this.emit("click", box.get("panel"));
|
|
280
|
+
});
|
|
281
|
+
box.on("destroy", () => {
|
|
282
|
+
this.emit("destroy", box, panel);
|
|
283
|
+
});
|
|
284
|
+
box.on("remove", () => {
|
|
285
|
+
this.emit("remove", box, panel);
|
|
286
|
+
});
|
|
287
|
+
box.on("detach", () => {
|
|
288
|
+
this.emit("detach", box, panel);
|
|
289
|
+
});
|
|
290
|
+
box.set("panel", panel);
|
|
291
|
+
this.uiBoxes[panel.id].box = box;
|
|
292
|
+
this.emit("boxsetup", box, panel);
|
|
293
|
+
if (typeof panel.widgets !== "undefined" && panel.widgets !== null) {
|
|
294
|
+
this.SetupWidgets(box, panel, box, panel.widgets);
|
|
295
|
+
this.emit("widgetsetupcomplete", box, panel, panel.widgets);
|
|
296
|
+
}
|
|
297
|
+
touched[panel.id] = true;
|
|
298
|
+
} else {
|
|
299
|
+
this.#UpdatePanelPosition(panel, row, col, this.uiBoxes[panel.id]);
|
|
300
|
+
touched[panel.id] = true;
|
|
369
301
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
});
|
|
373
|
-
__publicField(this, "PrevPage", () => {
|
|
374
|
-
if (__privateGet(this, _cursor) > 0) {
|
|
375
|
-
__privateSet(this, _cursor, __privateGet(this, _cursor) - this.ScreenCells);
|
|
376
|
-
if (__privateGet(this, _cursor) < 0) {
|
|
377
|
-
__privateSet(this, _cursor, 0);
|
|
302
|
+
if (this.#renderPanelFn) {
|
|
303
|
+
this.#renderPanelFn(this.uiBoxes[panel.id].box, panel);
|
|
378
304
|
}
|
|
379
|
-
__privateMethod(this, _STSUIFrame_instances, UpdateUI_fn).call(this);
|
|
380
305
|
}
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
this.
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
this.uiBoxes
|
|
392
|
-
this.
|
|
393
|
-
this.screen = null;
|
|
394
|
-
}
|
|
395
|
-
});
|
|
396
|
-
/**
|
|
397
|
-
* Render the screen.
|
|
398
|
-
*/
|
|
399
|
-
__publicField(this, "Render", () => {
|
|
400
|
-
if (this.screen) {
|
|
401
|
-
this.screen.render();
|
|
306
|
+
}
|
|
307
|
+
for (const [key] of Object.entries(this.uiBoxes)) {
|
|
308
|
+
const box = this.uiBoxes[key].box;
|
|
309
|
+
const panel = box.get("panel");
|
|
310
|
+
if (typeof touched[key] === "undefined") {
|
|
311
|
+
box.hide();
|
|
312
|
+
this.uiBoxes[key].boxHeader.hide();
|
|
313
|
+
this.emit("boxhide", this.uiBoxes[key].box, panel, panel.widgets);
|
|
314
|
+
} else {
|
|
315
|
+
box.show();
|
|
316
|
+
this.uiBoxes[key].boxHeader.show();
|
|
317
|
+
this.emit("boxshow", this.uiBoxes[key].box, panel, panel.widgets);
|
|
402
318
|
}
|
|
403
|
-
}
|
|
404
|
-
this.uidata = data;
|
|
405
|
-
__privateSet(this, _renderPanelFn, renderPanelFn);
|
|
406
|
-
this.SetupUI();
|
|
407
|
-
}
|
|
408
|
-
get blessed() {
|
|
409
|
-
return blessed;
|
|
410
|
-
}
|
|
411
|
-
CreateWidgetEx(widgetName, widgetoptions) {
|
|
412
|
-
const widget = blessed[widgetName].call(this, widgetoptions);
|
|
413
|
-
return widget;
|
|
319
|
+
}
|
|
414
320
|
}
|
|
415
321
|
get gridData() {
|
|
416
322
|
return this.uidata;
|
|
417
323
|
}
|
|
418
324
|
set gridData(gridData) {
|
|
419
325
|
this.uidata = gridData;
|
|
420
|
-
|
|
326
|
+
this.#SetupPanels();
|
|
421
327
|
this.UpdateCursorInfo();
|
|
422
328
|
this.Render();
|
|
423
329
|
}
|
|
@@ -426,153 +332,226 @@ class STSUIFrame extends EventEmitter {
|
|
|
426
332
|
}
|
|
427
333
|
set gridDataPanels(gridDataPanels) {
|
|
428
334
|
this.uidata.panels = gridDataPanels;
|
|
429
|
-
|
|
335
|
+
this.#SetupPanels();
|
|
430
336
|
this.UpdateCursorInfo();
|
|
431
337
|
this.Render();
|
|
432
338
|
}
|
|
339
|
+
/*
|
|
340
|
+
ExitEx() {
|
|
341
|
+
//@@ override in sub-class
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
EscapeEx() {
|
|
345
|
+
//@@ override in sub-class
|
|
346
|
+
}
|
|
347
|
+
*/
|
|
348
|
+
// https://www.npmjs.com/package/blessed
|
|
349
|
+
// data:= { title: <str>,
|
|
350
|
+
// grid: { rows: <int>, cols: <int> },
|
|
351
|
+
// menu: [ { top: <bool>, menuitems: [ { text: <string>, key: <string>, cb: <func> } ] } ]
|
|
352
|
+
// panels: [ { id: <str>, pos: { row: <int>, col: <int>, rowSpan: <int>, colSpan: <int> }, template: <str> } ] }
|
|
353
|
+
/**
|
|
354
|
+
*
|
|
355
|
+
* @param {*} data UI Data
|
|
356
|
+
*/
|
|
357
|
+
SetupUI = () => {
|
|
358
|
+
this.DestroyUI();
|
|
359
|
+
if (this.screen === null) {
|
|
360
|
+
this.screen = blessed.screen({
|
|
361
|
+
smartCSR: true
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
if (!this.screen) {
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
const data = this.uidata;
|
|
368
|
+
this.screen.title = data.title;
|
|
369
|
+
this.screen.on("resize", () => {
|
|
370
|
+
this.#ReSize();
|
|
371
|
+
this.Render();
|
|
372
|
+
});
|
|
373
|
+
if (data.menu !== null) {
|
|
374
|
+
for (let i = 0; i < data.menu.length; i++) {
|
|
375
|
+
new MenuBar(this.screen, data.menu[i]);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
this.screen.key(["C-c"], () => {
|
|
379
|
+
this.DestroyUI();
|
|
380
|
+
this.emit("exit");
|
|
381
|
+
});
|
|
382
|
+
this.screen.key(["escape"], () => {
|
|
383
|
+
this.emit("escape");
|
|
384
|
+
});
|
|
385
|
+
this.#SetupPanels();
|
|
386
|
+
this.#cursorInfo = blessed.box({
|
|
387
|
+
parent: this.screen,
|
|
388
|
+
bottom: 0,
|
|
389
|
+
right: 0,
|
|
390
|
+
width: "shrink",
|
|
391
|
+
height: 1,
|
|
392
|
+
style: {
|
|
393
|
+
bg: "gray",
|
|
394
|
+
fg: "white"
|
|
395
|
+
},
|
|
396
|
+
keys: false,
|
|
397
|
+
// Do not allow default key handling for this box
|
|
398
|
+
mouse: false,
|
|
399
|
+
content: "",
|
|
400
|
+
tags: true
|
|
401
|
+
// Allow style in-line tags such as bolt, italics, etc.
|
|
402
|
+
});
|
|
403
|
+
this.sortInfo = blessed.box({
|
|
404
|
+
parent: this.screen,
|
|
405
|
+
top: 0,
|
|
406
|
+
right: 0,
|
|
407
|
+
width: "shrink",
|
|
408
|
+
height: 1,
|
|
409
|
+
style: {
|
|
410
|
+
bg: "gray",
|
|
411
|
+
fg: "white"
|
|
412
|
+
},
|
|
413
|
+
keys: false,
|
|
414
|
+
// Do not allow default key handling for this box
|
|
415
|
+
mouse: false,
|
|
416
|
+
content: "",
|
|
417
|
+
tags: true
|
|
418
|
+
// Allow style in-line tags such as bolt, italics, etc.
|
|
419
|
+
});
|
|
420
|
+
this.screenHeader = blessed.box({
|
|
421
|
+
parent: this.screen,
|
|
422
|
+
top: 0,
|
|
423
|
+
left: "center",
|
|
424
|
+
width: "shrink",
|
|
425
|
+
height: 1,
|
|
426
|
+
style: {
|
|
427
|
+
bg: "gray",
|
|
428
|
+
fg: "white"
|
|
429
|
+
},
|
|
430
|
+
keys: false,
|
|
431
|
+
// Do not allow default key handling for this box
|
|
432
|
+
mouse: false,
|
|
433
|
+
content: `[ ... ]`,
|
|
434
|
+
tags: true
|
|
435
|
+
// Allow style in-line tags such as bolt, italics, etc.
|
|
436
|
+
});
|
|
437
|
+
this.UpdateCursorInfo();
|
|
438
|
+
this.UpdateSortInfo("Default");
|
|
439
|
+
this.UpdateScreenHeader(this.screenHeaderText);
|
|
440
|
+
this.Render();
|
|
441
|
+
};
|
|
442
|
+
UpdateCursorInfo = () => {
|
|
443
|
+
if (this.#cursorInfo) {
|
|
444
|
+
this.#cursorInfo.setContent(`Cursor: ${this.#cursor} / ${this.TotalPanelNumber}`);
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
UpdateSortInfo = (sortMode) => {
|
|
448
|
+
if (this.sortInfo) {
|
|
449
|
+
this.sortInfo.setContent(`Sort: ${sortMode}`);
|
|
450
|
+
}
|
|
451
|
+
};
|
|
452
|
+
UpdateScreenHeader = (screenHeaderText) => {
|
|
453
|
+
this.screenHeaderText = screenHeaderText;
|
|
454
|
+
if (this.screenHeader) {
|
|
455
|
+
this.screenHeader.setContent(`[ ${screenHeaderText} ]`);
|
|
456
|
+
}
|
|
457
|
+
};
|
|
433
458
|
get rows() {
|
|
434
459
|
return this.uidata.grid.rows;
|
|
435
460
|
}
|
|
436
461
|
get cols() {
|
|
437
462
|
return this.uidata.grid.cols;
|
|
438
463
|
}
|
|
464
|
+
IncRows = () => {
|
|
465
|
+
if (this.screen && this.screen.height / (this.uidata.grid.rows + 1) > this.minHeight) {
|
|
466
|
+
this.uidata.grid.rows++;
|
|
467
|
+
this.CheckCursor();
|
|
468
|
+
this.#UpdateUI();
|
|
469
|
+
}
|
|
470
|
+
};
|
|
471
|
+
DecRows = () => {
|
|
472
|
+
if (this.uidata.grid.rows > this.minRows) {
|
|
473
|
+
this.uidata.grid.rows--;
|
|
474
|
+
this.CheckCursor();
|
|
475
|
+
this.#UpdateUI();
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
IncCols = () => {
|
|
479
|
+
if (this.screen && this.screen.width / (this.uidata.grid.cols + 1) > this.minWidth) {
|
|
480
|
+
this.uidata.grid.cols++;
|
|
481
|
+
this.CheckCursor();
|
|
482
|
+
this.#UpdateUI();
|
|
483
|
+
}
|
|
484
|
+
};
|
|
485
|
+
DecCols = () => {
|
|
486
|
+
if (this.uidata.grid.cols > this.minCols) {
|
|
487
|
+
this.uidata.grid.cols--;
|
|
488
|
+
this.CheckCursor();
|
|
489
|
+
this.#UpdateUI();
|
|
490
|
+
}
|
|
491
|
+
};
|
|
439
492
|
get ScreenCells() {
|
|
440
493
|
return this.uidata.grid.cols * this.uidata.grid.rows;
|
|
441
494
|
}
|
|
442
495
|
get TotalPanelNumber() {
|
|
443
496
|
return Object.keys(this.uidata.panels).length;
|
|
444
497
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
_renderPanelFn = new WeakMap();
|
|
451
|
-
_cursorInfo = new WeakMap();
|
|
452
|
-
_CalcBoxPos = new WeakMap();
|
|
453
|
-
_UpdateUIBoxPos = new WeakMap();
|
|
454
|
-
_ReSize = new WeakMap();
|
|
455
|
-
_UpdatePanelPosition = new WeakMap();
|
|
456
|
-
_STSUIFrame_instances = new WeakSet();
|
|
457
|
-
/**
|
|
458
|
-
*
|
|
459
|
-
* Setup all panels
|
|
460
|
-
*/
|
|
461
|
-
SetupPanels_fn = function() {
|
|
462
|
-
if (!this.screen) {
|
|
463
|
-
return;
|
|
464
|
-
}
|
|
465
|
-
const panelKeys = Object.keys(this.uidata.panels);
|
|
466
|
-
const uiBoxIds = Object.keys(this.uiBoxes);
|
|
467
|
-
for (let i = 0; i < uiBoxIds.length; i++) {
|
|
468
|
-
if (typeof this.uidata.panels[uiBoxIds[i]] === "undefined") {
|
|
469
|
-
let uiBox = this.uiBoxes[uiBoxIds[i]];
|
|
470
|
-
if (typeof uiBox !== "undefined") {
|
|
471
|
-
this.emit("preremovebox", uiBox.box, uiBox.box.get("panel"));
|
|
472
|
-
this.screen.remove(uiBox.boxHeader);
|
|
473
|
-
this.screen.remove(uiBox.box);
|
|
474
|
-
uiBox = null;
|
|
475
|
-
delete this.uiBoxes[uiBoxIds[i]];
|
|
498
|
+
CheckCursor = () => {
|
|
499
|
+
if (this.#cursor > this.TotalPanelNumber - this.ScreenCells) {
|
|
500
|
+
this.#cursor = this.TotalPanelNumber - this.ScreenCells;
|
|
501
|
+
if (this.#cursor < 0) {
|
|
502
|
+
this.#cursor = 0;
|
|
476
503
|
}
|
|
477
504
|
}
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
const
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
if (typeof this.uiBoxes[panel.id] === "undefined") {
|
|
487
|
-
panel.pos = { row, col, rowSpan: 1, colSpan: 1 };
|
|
488
|
-
const calculatedBoxPos = __privateGet(this, _CalcBoxPos).call(this, panel);
|
|
489
|
-
if (!calculatedBoxPos) {
|
|
490
|
-
return;
|
|
491
|
-
}
|
|
492
|
-
const { top, left, width, height } = __privateGet(this, _CalcBoxPos).call(this, panel);
|
|
493
|
-
const box = blessed.box({
|
|
494
|
-
parent: this.screen,
|
|
495
|
-
top,
|
|
496
|
-
left,
|
|
497
|
-
width,
|
|
498
|
-
height,
|
|
499
|
-
style: {
|
|
500
|
-
bg: "#101010",
|
|
501
|
-
fg: "white"
|
|
502
|
-
},
|
|
503
|
-
border: {
|
|
504
|
-
type: "line"
|
|
505
|
-
},
|
|
506
|
-
keys: false,
|
|
507
|
-
// Do not allow default key handling for this box
|
|
508
|
-
tags: true
|
|
509
|
-
// Allow style in-line tags such as bolt, italics, etc.
|
|
510
|
-
});
|
|
511
|
-
const boxHeader = blessed.box({
|
|
512
|
-
parent: this.screen,
|
|
513
|
-
top,
|
|
514
|
-
left: left + 2,
|
|
515
|
-
width: "shrink",
|
|
516
|
-
height: 1,
|
|
517
|
-
style: {
|
|
518
|
-
bg: "gray",
|
|
519
|
-
fg: "white"
|
|
520
|
-
},
|
|
521
|
-
keys: false,
|
|
522
|
-
// Do not allow default key handling for this box
|
|
523
|
-
mouse: false,
|
|
524
|
-
content: panel.panelHeader,
|
|
525
|
-
tags: true
|
|
526
|
-
// Allow style in-line tags such as bold, italics, etc.
|
|
527
|
-
});
|
|
528
|
-
this.uiBoxes[panel.id] = { box, boxHeader };
|
|
529
|
-
boxHeader.setIndex(-1);
|
|
530
|
-
box.on("click", () => {
|
|
531
|
-
this.emit("click", box.get("panel"));
|
|
532
|
-
});
|
|
533
|
-
box.on("destroy", () => {
|
|
534
|
-
this.emit("destroy", box, panel);
|
|
535
|
-
});
|
|
536
|
-
box.on("remove", () => {
|
|
537
|
-
this.emit("remove", box, panel);
|
|
538
|
-
});
|
|
539
|
-
box.on("detach", () => {
|
|
540
|
-
this.emit("detach", box, panel);
|
|
541
|
-
});
|
|
542
|
-
box.set("panel", panel);
|
|
543
|
-
this.uiBoxes[panel.id].box = box;
|
|
544
|
-
this.emit("boxsetup", box, panel);
|
|
545
|
-
if (typeof panel.widgets !== "undefined" && panel.widgets !== null) {
|
|
546
|
-
this.SetupWidgets(box, panel, box, panel.widgets);
|
|
547
|
-
this.emit("widgetsetupcomplete", box, panel, panel.widgets);
|
|
548
|
-
}
|
|
549
|
-
touched[panel.id] = true;
|
|
550
|
-
} else {
|
|
551
|
-
__privateGet(this, _UpdatePanelPosition).call(this, panel, row, col, this.uiBoxes[panel.id]);
|
|
552
|
-
touched[panel.id] = true;
|
|
505
|
+
this.UpdateCursorInfo();
|
|
506
|
+
};
|
|
507
|
+
NextPage = () => {
|
|
508
|
+
const endpos = this.TotalPanelNumber - this.ScreenCells;
|
|
509
|
+
if (this.#cursor < endpos) {
|
|
510
|
+
this.#cursor += this.ScreenCells;
|
|
511
|
+
if (this.#cursor > endpos) {
|
|
512
|
+
this.#cursor = endpos;
|
|
553
513
|
}
|
|
554
|
-
|
|
555
|
-
|
|
514
|
+
this.#UpdateUI();
|
|
515
|
+
}
|
|
516
|
+
};
|
|
517
|
+
PrevPage = () => {
|
|
518
|
+
if (this.#cursor > 0) {
|
|
519
|
+
this.#cursor -= this.ScreenCells;
|
|
520
|
+
if (this.#cursor < 0) {
|
|
521
|
+
this.#cursor = 0;
|
|
556
522
|
}
|
|
523
|
+
this.#UpdateUI();
|
|
557
524
|
}
|
|
525
|
+
};
|
|
526
|
+
#UpdateUI() {
|
|
527
|
+
this.SetupUI();
|
|
558
528
|
}
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
this.uiBoxes
|
|
569
|
-
this.
|
|
529
|
+
Exit = () => {
|
|
530
|
+
this.DestroyUI();
|
|
531
|
+
this.emit("exit");
|
|
532
|
+
};
|
|
533
|
+
/**
|
|
534
|
+
*
|
|
535
|
+
*/
|
|
536
|
+
DestroyUI = () => {
|
|
537
|
+
if (this.screen !== null) {
|
|
538
|
+
this.uiBoxes = {};
|
|
539
|
+
this.screen.destroy();
|
|
540
|
+
this.screen = null;
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
/**
|
|
544
|
+
* Render the screen.
|
|
545
|
+
*/
|
|
546
|
+
Render = () => {
|
|
547
|
+
if (this.screen) {
|
|
548
|
+
this.screen.render();
|
|
570
549
|
}
|
|
550
|
+
};
|
|
551
|
+
get mainScreen() {
|
|
552
|
+
return this.screen;
|
|
571
553
|
}
|
|
572
|
-
}
|
|
573
|
-
UpdateUI_fn = function() {
|
|
574
|
-
this.SetupUI();
|
|
575
|
-
};
|
|
554
|
+
}
|
|
576
555
|
export {
|
|
577
556
|
MenuBar,
|
|
578
557
|
STSUIFrame
|