@yuneta/gobj-ui 7.23.29 → 7.23.31
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/README.md +175 -2
- package/dist/gobj-ui.cjs.js +1008 -197
- package/dist/gobj-ui.es.js +1009 -198
- package/package.json +1 -1
- package/src/c_yui_gobj_tree_js.js +465 -249
- package/src/c_yui_json_graph.js +30 -4
- package/src/c_yui_treedb_graph.js +20 -6
- package/src/gclass_describe.js +234 -0
- package/src/gclass_describe.test.js +125 -0
- package/src/gobj_tree_model.js +436 -0
- package/src/gobj_tree_model.test.js +184 -0
- package/src/yui_gclass_view.js +290 -0
package/dist/gobj-ui.cjs.js
CHANGED
|
@@ -3518,7 +3518,7 @@ function composed_title(gobj) {
|
|
|
3518
3518
|
* Below the mobile breakpoint the window is a full-screen
|
|
3519
3519
|
* sheet (no float / drag / resize).
|
|
3520
3520
|
************************************************************/
|
|
3521
|
-
function is_mobile$
|
|
3521
|
+
function is_mobile$4() {
|
|
3522
3522
|
return (window.innerWidth || document.documentElement.offsetWidth) <= MOBILE_MAX;
|
|
3523
3523
|
}
|
|
3524
3524
|
/************************************************************
|
|
@@ -3551,7 +3551,7 @@ function do_minimize(gobj) {
|
|
|
3551
3551
|
************************************************************/
|
|
3552
3552
|
function build_ui$15(gobj) {
|
|
3553
3553
|
ensure_window_style();
|
|
3554
|
-
let mobile = is_mobile$
|
|
3554
|
+
let mobile = is_mobile$4();
|
|
3555
3555
|
let header = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "header");
|
|
3556
3556
|
if ((0, _yuneta_gobj_js.is_gobj)(header)) header = (0, _yuneta_gobj_js.gobj_read_attr)(header, "$container");
|
|
3557
3557
|
if (!header) header = build_default_header(gobj);
|
|
@@ -3889,7 +3889,7 @@ function min$1(gobj) {
|
|
|
3889
3889
|
* handlers moving
|
|
3890
3890
|
************************************************************/
|
|
3891
3891
|
function mvStart(gobj, evt) {
|
|
3892
|
-
if (is_mobile$
|
|
3892
|
+
if (is_mobile$4()) return;
|
|
3893
3893
|
let $container = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
|
|
3894
3894
|
let window_rect = $container.getBoundingClientRect();
|
|
3895
3895
|
let x = evt.screenX;
|
|
@@ -4048,7 +4048,7 @@ function do_center(gobj, x, y, width, height) {
|
|
|
4048
4048
|
function handleResize(gobj) {
|
|
4049
4049
|
let $container = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
|
|
4050
4050
|
if (!$container) return;
|
|
4051
|
-
if (is_mobile$
|
|
4051
|
+
if (is_mobile$4()) {
|
|
4052
4052
|
$container.classList.add("is-mobile-sheet");
|
|
4053
4053
|
let vw = window.innerWidth || document.documentElement.offsetWidth;
|
|
4054
4054
|
let vh = window.innerHeight || document.documentElement.offsetHeight;
|
|
@@ -10983,6 +10983,26 @@ function make_toolbar$3(gobj) {
|
|
|
10983
10983
|
return $toolbar;
|
|
10984
10984
|
}
|
|
10985
10985
|
/************************************************************
|
|
10986
|
+
* The element G6 mounts its canvas in.
|
|
10987
|
+
*
|
|
10988
|
+
* Read from THIS gclass's own $container, never with
|
|
10989
|
+
* `document.getElementById()`: a view is not always in the
|
|
10990
|
+
* document when it is started -- a host that builds the
|
|
10991
|
+
* viewer and mounts it into a window afterwards starts it
|
|
10992
|
+
* DETACHED -- and a global lookup answers null there. It cost
|
|
10993
|
+
* a resize that never worked: the ResizeObserver below was
|
|
10994
|
+
* simply never attached, silently, and the canvas kept the
|
|
10995
|
+
* size it was born with for the life of the window.
|
|
10996
|
+
*
|
|
10997
|
+
* Null only if the UI was never built; that is a bug, and it
|
|
10998
|
+
* is logged where it matters rather than skipped.
|
|
10999
|
+
************************************************************/
|
|
11000
|
+
function canvas_mount$1(gobj) {
|
|
11001
|
+
let $container = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
|
|
11002
|
+
if (!$container) return null;
|
|
11003
|
+
return $container.querySelector("#" + gobj.priv.canvas_id);
|
|
11004
|
+
}
|
|
11005
|
+
/************************************************************
|
|
10986
11006
|
* Build a G6 graph instance
|
|
10987
11007
|
************************************************************/
|
|
10988
11008
|
function build_graph$3(gobj) {
|
|
@@ -11026,8 +11046,9 @@ function build_graph$3(gobj) {
|
|
|
11026
11046
|
});
|
|
11027
11047
|
graph.on(_antv_g6.CanvasEvent.CLICK, (evt) => {});
|
|
11028
11048
|
if (typeof ResizeObserver !== "undefined") {
|
|
11029
|
-
let $canvas =
|
|
11030
|
-
if (
|
|
11049
|
+
let $canvas = canvas_mount$1(gobj);
|
|
11050
|
+
if (!$canvas) (0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: no canvas mount, the graph will never resize`);
|
|
11051
|
+
else {
|
|
11031
11052
|
let ro = new ResizeObserver(() => {
|
|
11032
11053
|
if (priv._resize_raf) cancelAnimationFrame(priv._resize_raf);
|
|
11033
11054
|
priv._resize_raf = requestAnimationFrame(() => {
|
|
@@ -11964,10 +11985,9 @@ function ac_node_click$4(gobj, event, kw, src) {
|
|
|
11964
11985
|
*
|
|
11965
11986
|
************************************************************/
|
|
11966
11987
|
function ac_show$8(gobj, event, kw, src) {
|
|
11967
|
-
let
|
|
11968
|
-
let graph = priv.graph;
|
|
11988
|
+
let graph = gobj.priv.graph;
|
|
11969
11989
|
if (graph) {
|
|
11970
|
-
let $canvas =
|
|
11990
|
+
let $canvas = canvas_mount$1(gobj);
|
|
11971
11991
|
if ($canvas) {
|
|
11972
11992
|
let cw = $canvas.clientWidth;
|
|
11973
11993
|
let ch = $canvas.clientHeight;
|
|
@@ -11986,10 +12006,9 @@ function ac_show$8(gobj, event, kw, src) {
|
|
|
11986
12006
|
* No fitView: preserve the user's current pan/zoom.
|
|
11987
12007
|
************************************************************/
|
|
11988
12008
|
function ac_resize$2(gobj, event, kw, src) {
|
|
11989
|
-
let
|
|
11990
|
-
let graph = priv.graph;
|
|
12009
|
+
let graph = gobj.priv.graph;
|
|
11991
12010
|
if (graph) {
|
|
11992
|
-
let $canvas =
|
|
12011
|
+
let $canvas = canvas_mount$1(gobj);
|
|
11993
12012
|
if ($canvas) {
|
|
11994
12013
|
let cw = $canvas.clientWidth;
|
|
11995
12014
|
let ch = $canvas.clientHeight;
|
|
@@ -13205,7 +13224,7 @@ function ac_json_item_clicked(gobj, event, kw, src) {
|
|
|
13205
13224
|
/************************************************************
|
|
13206
13225
|
* EV_LANGUAGE_CHANGED — re-translate chrome + re-render
|
|
13207
13226
|
************************************************************/
|
|
13208
|
-
function ac_language_changed$
|
|
13227
|
+
function ac_language_changed$4(gobj, event, kw, src) {
|
|
13209
13228
|
let priv = gobj.priv;
|
|
13210
13229
|
let $container = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
|
|
13211
13230
|
if ($container) {
|
|
@@ -13266,7 +13285,7 @@ function create_gclass$10(gclass_name) {
|
|
|
13266
13285
|
],
|
|
13267
13286
|
[
|
|
13268
13287
|
"EV_LANGUAGE_CHANGED",
|
|
13269
|
-
ac_language_changed$
|
|
13288
|
+
ac_language_changed$4,
|
|
13270
13289
|
null
|
|
13271
13290
|
],
|
|
13272
13291
|
[
|
|
@@ -13342,7 +13361,7 @@ function create_gclass$10(gclass_name) {
|
|
|
13342
13361
|
],
|
|
13343
13362
|
[
|
|
13344
13363
|
"EV_LANGUAGE_CHANGED",
|
|
13345
|
-
ac_language_changed$
|
|
13364
|
+
ac_language_changed$4,
|
|
13346
13365
|
null
|
|
13347
13366
|
],
|
|
13348
13367
|
[
|
|
@@ -13392,6 +13411,568 @@ function register_c_yui_json() {
|
|
|
13392
13411
|
return create_gclass$10(GCLASS_NAME$10);
|
|
13393
13412
|
}
|
|
13394
13413
|
//#endregion
|
|
13414
|
+
//#region src/gobj_tree_model.js
|
|
13415
|
+
/***********************************************************************
|
|
13416
|
+
* gobj_tree_model.js
|
|
13417
|
+
*
|
|
13418
|
+
* The gobj tree of a yuno, as plain data.
|
|
13419
|
+
*
|
|
13420
|
+
* The view (C_YUI_GOBJ_TREE_JS) draws NODE DESCRIPTORS, never
|
|
13421
|
+
* gobjs. There are two producers of a descriptor, because the
|
|
13422
|
+
* view has to show the gobjs of the BACKEND too:
|
|
13423
|
+
*
|
|
13424
|
+
* - describe_js_gobj() the gobj tree of THIS browser yuno
|
|
13425
|
+
* - describe_backend_tree() the answer of the backend command
|
|
13426
|
+
* `view-gobj-tree` of another yuno
|
|
13427
|
+
*
|
|
13428
|
+
* Both answer the SAME shape, and that shape is the backend's:
|
|
13429
|
+
* the field names are the ones `gobj2json()` writes in
|
|
13430
|
+
* `kernel/c/gobj-c/src/gobj.c` (fullname, shortname, gclass,
|
|
13431
|
+
* name, parent, state, running, playing, service, disabled,
|
|
13432
|
+
* volatil, bottom_gobj, gobj_flags, commands, gobj_trace_level).
|
|
13433
|
+
* Anything the browser runtime cannot answer is simply absent,
|
|
13434
|
+
* and every reader here treats absent as "not known", never as
|
|
13435
|
+
* false.
|
|
13436
|
+
*
|
|
13437
|
+
* Copyright (c) 2026, ArtGins.
|
|
13438
|
+
* All Rights Reserved.
|
|
13439
|
+
***********************************************************************/
|
|
13440
|
+
/************************************************************
|
|
13441
|
+
* The role of a node: "yuno" | "service" | "volatil" | "pure" | "child"
|
|
13442
|
+
************************************************************/
|
|
13443
|
+
function node_role(d) {
|
|
13444
|
+
if (!d) return "child";
|
|
13445
|
+
if (d.is_yuno) return "yuno";
|
|
13446
|
+
if (d.service) return "service";
|
|
13447
|
+
if (d.volatil) return "volatil";
|
|
13448
|
+
if (d.pure_child) return "pure";
|
|
13449
|
+
return "child";
|
|
13450
|
+
}
|
|
13451
|
+
/************************************************************
|
|
13452
|
+
* What the node is doing: "stopped" | "running" | "playing"
|
|
13453
|
+
************************************************************/
|
|
13454
|
+
function node_status(d) {
|
|
13455
|
+
if (!d || !d.running) return "stopped";
|
|
13456
|
+
return d.playing ? "playing" : "running";
|
|
13457
|
+
}
|
|
13458
|
+
/************************************************************
|
|
13459
|
+
* The i18n key of the status, which is NOT the status itself:
|
|
13460
|
+
* a gobj that runs and does not play is PAUSED to the reader,
|
|
13461
|
+
* and "running" alone never said which of the two it was.
|
|
13462
|
+
************************************************************/
|
|
13463
|
+
function node_status_key(d) {
|
|
13464
|
+
switch (node_status(d)) {
|
|
13465
|
+
case "playing": return "playing";
|
|
13466
|
+
case "running": return "running (paused)";
|
|
13467
|
+
default: return "stopped";
|
|
13468
|
+
}
|
|
13469
|
+
}
|
|
13470
|
+
/******************************
|
|
13471
|
+
* Producers
|
|
13472
|
+
******************************/
|
|
13473
|
+
/************************************************************
|
|
13474
|
+
* A descriptor of a LIVE gobj of this browser yuno, children
|
|
13475
|
+
* included (the whole subtree, depth-first).
|
|
13476
|
+
*
|
|
13477
|
+
* `is_root` marks the yuno itself: the JS runtime has no
|
|
13478
|
+
* gobj_flag_yuno test of its own.
|
|
13479
|
+
************************************************************/
|
|
13480
|
+
function describe_js_gobj(target_gobj, is_root) {
|
|
13481
|
+
if (!target_gobj) return null;
|
|
13482
|
+
let parent_gobj = (0, _yuneta_gobj_js.gobj_parent)(target_gobj);
|
|
13483
|
+
let bottom = (0, _yuneta_gobj_js.gobj_bottom_gobj)(target_gobj);
|
|
13484
|
+
let d = {
|
|
13485
|
+
gclass: (0, _yuneta_gobj_js.gobj_gclass_name)(target_gobj) || "",
|
|
13486
|
+
name: (0, _yuneta_gobj_js.gobj_name)(target_gobj) || "",
|
|
13487
|
+
shortname: (0, _yuneta_gobj_js.gobj_short_name)(target_gobj) || "",
|
|
13488
|
+
fullname: (0, _yuneta_gobj_js.gobj_full_name)(target_gobj) || "",
|
|
13489
|
+
parent: parent_gobj ? (0, _yuneta_gobj_js.gobj_short_name)(parent_gobj) || "" : "",
|
|
13490
|
+
state: (0, _yuneta_gobj_js.gobj_current_state)(target_gobj) || "",
|
|
13491
|
+
running: !!(0, _yuneta_gobj_js.gobj_is_running)(target_gobj),
|
|
13492
|
+
playing: !!(0, _yuneta_gobj_js.gobj_is_playing)(target_gobj),
|
|
13493
|
+
service: !!(0, _yuneta_gobj_js.gobj_is_service)(target_gobj),
|
|
13494
|
+
volatil: !!(0, _yuneta_gobj_js.gobj_is_volatil)(target_gobj),
|
|
13495
|
+
pure_child: !!(0, _yuneta_gobj_js.gobj_is_pure_child)(target_gobj),
|
|
13496
|
+
disabled: !!target_gobj.disabled,
|
|
13497
|
+
bottom_gobj: bottom ? (0, _yuneta_gobj_js.gobj_short_name)(bottom) || "" : "",
|
|
13498
|
+
commands: !!(target_gobj.gclass && target_gobj.gclass.command_table),
|
|
13499
|
+
is_yuno: !!is_root,
|
|
13500
|
+
children: []
|
|
13501
|
+
};
|
|
13502
|
+
let children = target_gobj.dl_children || [];
|
|
13503
|
+
for (let child of children) {
|
|
13504
|
+
let cd = describe_js_gobj(child, false);
|
|
13505
|
+
if (cd) d.children.push(cd);
|
|
13506
|
+
}
|
|
13507
|
+
return d;
|
|
13508
|
+
}
|
|
13509
|
+
/******************************
|
|
13510
|
+
* Readouts
|
|
13511
|
+
******************************/
|
|
13512
|
+
/************************************************************
|
|
13513
|
+
* The i18n key of a role. Two of the five roles are not the
|
|
13514
|
+
* word the reader wants ("pure" and "volatil" alone say
|
|
13515
|
+
* nothing), so the map is explicit.
|
|
13516
|
+
************************************************************/
|
|
13517
|
+
function role_i18n_key(role) {
|
|
13518
|
+
switch (role) {
|
|
13519
|
+
case "yuno": return "yuno";
|
|
13520
|
+
case "service": return "service";
|
|
13521
|
+
case "volatil": return "volatil child";
|
|
13522
|
+
case "pure": return "pure child";
|
|
13523
|
+
default: return "child";
|
|
13524
|
+
}
|
|
13525
|
+
}
|
|
13526
|
+
/************************************************************
|
|
13527
|
+
* The marks a node carries besides its role: what the reader
|
|
13528
|
+
* would otherwise have to open the popover to learn.
|
|
13529
|
+
*
|
|
13530
|
+
* Returns i18n KEYS, in a fixed order, so the card and the
|
|
13531
|
+
* popover cannot disagree about what a node is.
|
|
13532
|
+
************************************************************/
|
|
13533
|
+
function node_badge_keys(d) {
|
|
13534
|
+
let badges = [];
|
|
13535
|
+
if (!d) return badges;
|
|
13536
|
+
let role = node_role(d);
|
|
13537
|
+
if (role !== "child") badges.push(role_i18n_key(role));
|
|
13538
|
+
if (d.disabled) badges.push("disabled");
|
|
13539
|
+
if (d.bottom_gobj) badges.push("bottom");
|
|
13540
|
+
if (d.commands) badges.push("commands");
|
|
13541
|
+
return badges;
|
|
13542
|
+
}
|
|
13543
|
+
/************************************************************
|
|
13544
|
+
* The vocabulary of this view, translated.
|
|
13545
|
+
*
|
|
13546
|
+
* Written as literal t("...") calls and not as t(key): a key
|
|
13547
|
+
* reached through a variable is invisible to the locale
|
|
13548
|
+
* validator, which is how a fixed vocabulary ships in one
|
|
13549
|
+
* language and never changes it.
|
|
13550
|
+
************************************************************/
|
|
13551
|
+
function node_labels(t) {
|
|
13552
|
+
if (typeof t !== "function") t = (k) => k;
|
|
13553
|
+
return {
|
|
13554
|
+
role: {
|
|
13555
|
+
"yuno": t("yuno"),
|
|
13556
|
+
"service": t("service"),
|
|
13557
|
+
"volatil child": t("volatil child"),
|
|
13558
|
+
"pure child": t("pure child"),
|
|
13559
|
+
"child": t("child")
|
|
13560
|
+
},
|
|
13561
|
+
status: {
|
|
13562
|
+
"playing": t("playing"),
|
|
13563
|
+
"running (paused)": t("running (paused)"),
|
|
13564
|
+
"stopped": t("stopped")
|
|
13565
|
+
},
|
|
13566
|
+
status_short: {
|
|
13567
|
+
"playing": t("playing"),
|
|
13568
|
+
"running": t("running"),
|
|
13569
|
+
"stopped": t("stopped")
|
|
13570
|
+
},
|
|
13571
|
+
badge: {
|
|
13572
|
+
"yuno": t("yuno"),
|
|
13573
|
+
"service": t("service"),
|
|
13574
|
+
"volatil child": t("volatil child"),
|
|
13575
|
+
"pure child": t("pure child"),
|
|
13576
|
+
"disabled": t("disabled"),
|
|
13577
|
+
"bottom": t("bottom"),
|
|
13578
|
+
"commands": t("commands")
|
|
13579
|
+
},
|
|
13580
|
+
field: {
|
|
13581
|
+
gclass: t("gclass"),
|
|
13582
|
+
name: t("name"),
|
|
13583
|
+
full_name: t("full name"),
|
|
13584
|
+
role: t("role"),
|
|
13585
|
+
status: t("status"),
|
|
13586
|
+
state: t("state"),
|
|
13587
|
+
disabled: t("disabled"),
|
|
13588
|
+
parent: t("parent"),
|
|
13589
|
+
bottom_gobj: t("bottom gobj"),
|
|
13590
|
+
commands: t("commands"),
|
|
13591
|
+
traces: t("traces"),
|
|
13592
|
+
flags: t("flags"),
|
|
13593
|
+
children: t("children"),
|
|
13594
|
+
yes: t("yes"),
|
|
13595
|
+
collapsed: t("(collapsed)")
|
|
13596
|
+
}
|
|
13597
|
+
};
|
|
13598
|
+
}
|
|
13599
|
+
/************************************************************
|
|
13600
|
+
* The rows of the popover: [label, value], both translated.
|
|
13601
|
+
*
|
|
13602
|
+
* `t` is the app's translator -- the library has none of its
|
|
13603
|
+
* own. Values that are a fixed vocabulary (the role, the
|
|
13604
|
+
* status, yes) go through it too; free text does not.
|
|
13605
|
+
************************************************************/
|
|
13606
|
+
function node_info_rows(d, t) {
|
|
13607
|
+
let rows = [];
|
|
13608
|
+
if (!d) return rows;
|
|
13609
|
+
let L = node_labels(t);
|
|
13610
|
+
let f = L.field;
|
|
13611
|
+
rows.push([f.gclass, d.gclass || "—"]);
|
|
13612
|
+
rows.push([f.name, d.name || "—"]);
|
|
13613
|
+
if (d.fullname && d.fullname !== d.shortname) rows.push([f.full_name, d.fullname]);
|
|
13614
|
+
rows.push([f.role, L.role[role_i18n_key(node_role(d))]]);
|
|
13615
|
+
rows.push([f.status, L.status[node_status_key(d)]]);
|
|
13616
|
+
rows.push([f.state, d.state || "—"]);
|
|
13617
|
+
if (d.disabled) rows.push([f.disabled, f.yes]);
|
|
13618
|
+
if (d.parent) rows.push([f.parent, d.parent]);
|
|
13619
|
+
if (d.bottom_gobj) rows.push([f.bottom_gobj, d.bottom_gobj]);
|
|
13620
|
+
if (d.commands) rows.push([f.commands, f.yes]);
|
|
13621
|
+
if (Array.isArray(d.gobj_trace_level) && d.gobj_trace_level.length > 0) rows.push([f.traces, d.gobj_trace_level.join(", ")]);
|
|
13622
|
+
if (Array.isArray(d.gobj_flags) && d.gobj_flags.length > 0) rows.push([f.flags, d.gobj_flags.join(", ")]);
|
|
13623
|
+
let kids = Array.isArray(d.children) ? d.children.length : 0;
|
|
13624
|
+
if (kids > 0) rows.push([f.children, d.is_collapsed ? kids + " " + f.collapsed : String(kids)]);
|
|
13625
|
+
return rows;
|
|
13626
|
+
}
|
|
13627
|
+
//#endregion
|
|
13628
|
+
//#region src/gclass_describe.js
|
|
13629
|
+
/***********************************************************************
|
|
13630
|
+
* gclass_describe.js
|
|
13631
|
+
*
|
|
13632
|
+
* A gclass, as plain JSON, in the shape the BACKEND answers.
|
|
13633
|
+
*
|
|
13634
|
+
* There is no gclass viewer in the framework: the C kernel
|
|
13635
|
+
* answers `view-gclass` with `gclass2json()`
|
|
13636
|
+
* (`kernel/c/gobj-c/src/gobj.c`) and nothing draws it. This
|
|
13637
|
+
* module builds the same document for a gclass of the BROWSER
|
|
13638
|
+
* yuno, out of the gobj-js registry, so one viewer can show a
|
|
13639
|
+
* gclass of either side:
|
|
13640
|
+
*
|
|
13641
|
+
* {id, gcflag, attrs, commands, gclass_methods,
|
|
13642
|
+
* internal_methods, FSM: {events, states}}
|
|
13643
|
+
*
|
|
13644
|
+
* Two keys the backend does not carry are added at the end,
|
|
13645
|
+
* because the browser can answer them for free and the reader
|
|
13646
|
+
* asks them first: `instances` and `trace_levels`.
|
|
13647
|
+
*
|
|
13648
|
+
* Copyright (c) 2026, ArtGins.
|
|
13649
|
+
* All Rights Reserved.
|
|
13650
|
+
***********************************************************************/
|
|
13651
|
+
/***************************************************************
|
|
13652
|
+
* Bit tables
|
|
13653
|
+
***************************************************************/
|
|
13654
|
+
var DATA_TYPE_NAMES = {
|
|
13655
|
+
[_yuneta_gobj_js.data_type_t.DTP_STRING]: "DTP_STRING",
|
|
13656
|
+
[_yuneta_gobj_js.data_type_t.DTP_BOOLEAN]: "DTP_BOOLEAN",
|
|
13657
|
+
[_yuneta_gobj_js.data_type_t.DTP_INTEGER]: "DTP_INTEGER",
|
|
13658
|
+
[_yuneta_gobj_js.data_type_t.DTP_REAL]: "DTP_REAL",
|
|
13659
|
+
[_yuneta_gobj_js.data_type_t.DTP_LIST]: "DTP_LIST",
|
|
13660
|
+
[_yuneta_gobj_js.data_type_t.DTP_DICT]: "DTP_DICT",
|
|
13661
|
+
[_yuneta_gobj_js.data_type_t.DTP_JSON]: "DTP_JSON",
|
|
13662
|
+
[_yuneta_gobj_js.data_type_t.DTP_POINTER]: "DTP_POINTER"
|
|
13663
|
+
};
|
|
13664
|
+
/************************************************************
|
|
13665
|
+
* The names of the bits set in `bits`, in table order.
|
|
13666
|
+
************************************************************/
|
|
13667
|
+
function bits2names(table, bits) {
|
|
13668
|
+
let names = [];
|
|
13669
|
+
let value = Number(bits) || 0;
|
|
13670
|
+
for (let name of Object.keys(table)) if ((value & table[name]) !== 0) names.push(name);
|
|
13671
|
+
return names;
|
|
13672
|
+
}
|
|
13673
|
+
/************************************************************
|
|
13674
|
+
* The name of a data type. An unknown type is reported as
|
|
13675
|
+
* the number it is -- silently drawing "DTP_STRING" for a
|
|
13676
|
+
* type nobody registered would be worse than saying "17".
|
|
13677
|
+
************************************************************/
|
|
13678
|
+
function data_type_name(type) {
|
|
13679
|
+
return DATA_TYPE_NAMES[type] || String(type);
|
|
13680
|
+
}
|
|
13681
|
+
/************************************************************
|
|
13682
|
+
* One SDATA descriptor -> one row.
|
|
13683
|
+
*
|
|
13684
|
+
* A DTP_POINTER default is a live object (a DOM node, a
|
|
13685
|
+
* gobj): it is never printed, only named, because a viewer
|
|
13686
|
+
* that serializes it would either throw or dump the page.
|
|
13687
|
+
************************************************************/
|
|
13688
|
+
function sdatadesc2json(it) {
|
|
13689
|
+
let row = {
|
|
13690
|
+
id: it.name,
|
|
13691
|
+
type: data_type_name(it.type),
|
|
13692
|
+
flag: bits2names(_yuneta_gobj_js.sdata_flag_t, it.flag),
|
|
13693
|
+
description: it.description || ""
|
|
13694
|
+
};
|
|
13695
|
+
if (it.type === _yuneta_gobj_js.data_type_t.DTP_POINTER) row.default_value = it.default_value === null || it.default_value === void 0 ? null : "<pointer>";
|
|
13696
|
+
else row.default_value = it.default_value === void 0 ? null : it.default_value;
|
|
13697
|
+
return row;
|
|
13698
|
+
}
|
|
13699
|
+
/************************************************************
|
|
13700
|
+
* The attrs table of a gclass.
|
|
13701
|
+
************************************************************/
|
|
13702
|
+
function attrs2json(attrs_table) {
|
|
13703
|
+
let rows = [];
|
|
13704
|
+
if (!Array.isArray(attrs_table)) return rows;
|
|
13705
|
+
for (let it of attrs_table) {
|
|
13706
|
+
if (!it || !it.name) continue;
|
|
13707
|
+
rows.push(sdatadesc2json(it));
|
|
13708
|
+
}
|
|
13709
|
+
return rows;
|
|
13710
|
+
}
|
|
13711
|
+
/************************************************************
|
|
13712
|
+
* The command table of a gclass, with the parameters of
|
|
13713
|
+
* each command (the `schema` slot of SDATACM).
|
|
13714
|
+
************************************************************/
|
|
13715
|
+
function commands2json(command_table) {
|
|
13716
|
+
let rows = [];
|
|
13717
|
+
if (!Array.isArray(command_table)) return rows;
|
|
13718
|
+
for (let it of command_table) {
|
|
13719
|
+
if (!it || !it.name) continue;
|
|
13720
|
+
let row = {
|
|
13721
|
+
id: it.name,
|
|
13722
|
+
alias: it.alias || [],
|
|
13723
|
+
description: it.description || ""
|
|
13724
|
+
};
|
|
13725
|
+
if (Array.isArray(it.schema)) row.parameters = attrs2json(it.schema);
|
|
13726
|
+
rows.push(row);
|
|
13727
|
+
}
|
|
13728
|
+
return rows;
|
|
13729
|
+
}
|
|
13730
|
+
/************************************************************
|
|
13731
|
+
* The methods the gclass actually implements. A table of
|
|
13732
|
+
* every possible one, mostly empty, tells the reader nothing.
|
|
13733
|
+
************************************************************/
|
|
13734
|
+
function methods2json(mt) {
|
|
13735
|
+
let names = [];
|
|
13736
|
+
if (!mt || typeof mt !== "object") return names;
|
|
13737
|
+
for (let key of Object.keys(mt)) if (typeof mt[key] === "function") names.push(key);
|
|
13738
|
+
return names;
|
|
13739
|
+
}
|
|
13740
|
+
/************************************************************
|
|
13741
|
+
* The FSM: the events the gclass declares, and what each
|
|
13742
|
+
* state does with them.
|
|
13743
|
+
************************************************************/
|
|
13744
|
+
function fsm2json(gclass) {
|
|
13745
|
+
let events = [];
|
|
13746
|
+
for (let ev of gclass.dl_events || []) events.push({
|
|
13747
|
+
event_name: ev.event_name,
|
|
13748
|
+
event_flag: bits2names(_yuneta_gobj_js.event_flag_t, ev.event_flag)
|
|
13749
|
+
});
|
|
13750
|
+
let states = {};
|
|
13751
|
+
for (let st of gclass.dl_states || []) {
|
|
13752
|
+
let actions = [];
|
|
13753
|
+
for (let ac of st.dl_actions || []) actions.push({
|
|
13754
|
+
event_name: ac.event_name,
|
|
13755
|
+
action: ac.action ? ac.action.name || "action" : "",
|
|
13756
|
+
next_state: ac.next_state || ""
|
|
13757
|
+
});
|
|
13758
|
+
states[st.state_name] = actions;
|
|
13759
|
+
}
|
|
13760
|
+
return {
|
|
13761
|
+
events,
|
|
13762
|
+
states
|
|
13763
|
+
};
|
|
13764
|
+
}
|
|
13765
|
+
/************************************************************
|
|
13766
|
+
* The description of a gclass REGISTERED IN THIS BROWSER YUNO,
|
|
13767
|
+
* or null when the registry does not know that name.
|
|
13768
|
+
*
|
|
13769
|
+
* Null is the answer for a gclass of a BACKEND yuno too: the
|
|
13770
|
+
* browser registry carries the GUI gclasses and nothing else,
|
|
13771
|
+
* so the caller asks the backend `view-gclass` for those and
|
|
13772
|
+
* shows whatever it answers -- this same shape.
|
|
13773
|
+
************************************************************/
|
|
13774
|
+
function describe_local_gclass(gclass_name) {
|
|
13775
|
+
if (!gclass_name) return null;
|
|
13776
|
+
let gclass = (0, _yuneta_gobj_js.gclass_find_by_name)(gclass_name, false);
|
|
13777
|
+
if (!gclass) return null;
|
|
13778
|
+
return {
|
|
13779
|
+
id: gclass.gclass_name,
|
|
13780
|
+
gcflag: bits2names(_yuneta_gobj_js.gclass_flag_t, gclass.gclass_flag),
|
|
13781
|
+
attrs: attrs2json(gclass.attrs_table),
|
|
13782
|
+
commands: commands2json(gclass.command_table),
|
|
13783
|
+
gclass_methods: methods2json(gclass.gmt),
|
|
13784
|
+
internal_methods: methods2json(gclass.lmt),
|
|
13785
|
+
FSM: fsm2json(gclass),
|
|
13786
|
+
instances: Number(gclass.instances) || 0,
|
|
13787
|
+
trace_levels: Array.isArray(gclass.s_user_trace_level) ? gclass.s_user_trace_level : []
|
|
13788
|
+
};
|
|
13789
|
+
}
|
|
13790
|
+
//#endregion
|
|
13791
|
+
//#region src/yui_gclass_view.js
|
|
13792
|
+
/***********************************************************************
|
|
13793
|
+
* yui_gclass_view.js
|
|
13794
|
+
*
|
|
13795
|
+
* The gclass viewer: what a GClass IS, in a window.
|
|
13796
|
+
*
|
|
13797
|
+
* The framework had no such viewer. The C kernel answers
|
|
13798
|
+
* `view-gclass` with a full description (attrs, commands,
|
|
13799
|
+
* methods, FSM) and the only reader of it was a terminal.
|
|
13800
|
+
* This one draws that same document with C_YUI_JSON, so the
|
|
13801
|
+
* FSM of a gclass is a graph and its attrs table is a tree,
|
|
13802
|
+
* and it takes the document from either side:
|
|
13803
|
+
*
|
|
13804
|
+
* - a gclass of the browser yuno -> describe_local_gclass()
|
|
13805
|
+
* - a gclass of a backend yuno -> `opts.description`, the
|
|
13806
|
+
* answer of `view-gclass`
|
|
13807
|
+
*
|
|
13808
|
+
* One window at a time per host: the caller keeps the handle
|
|
13809
|
+
* and closes it, the way the treedb graph keeps its raw-JSON
|
|
13810
|
+
* viewer.
|
|
13811
|
+
*
|
|
13812
|
+
* Copyright (c) 2026, ArtGins.
|
|
13813
|
+
* All Rights Reserved.
|
|
13814
|
+
***********************************************************************/
|
|
13815
|
+
/************************************************************
|
|
13816
|
+
* Can this app show a gclass at all?
|
|
13817
|
+
*
|
|
13818
|
+
* The viewer is C_YUI_JSON, and an app registers only the
|
|
13819
|
+
* gclasses it mounts. The caller asks this BEFORE drawing a
|
|
13820
|
+
* button, so an app that does not carry the viewer shows no
|
|
13821
|
+
* control instead of a control that fails.
|
|
13822
|
+
************************************************************/
|
|
13823
|
+
function gclass_view_available() {
|
|
13824
|
+
return !!(0, _yuneta_gobj_js.gclass_find_by_name)("C_YUI_JSON", false);
|
|
13825
|
+
}
|
|
13826
|
+
/************************************************************
|
|
13827
|
+
* Open the viewer on `gclass_name`.
|
|
13828
|
+
*
|
|
13829
|
+
* opts:
|
|
13830
|
+
* description the document to draw. Omitted, it is
|
|
13831
|
+
* built from the browser registry.
|
|
13832
|
+
* title_prefix what the window says before the gclass
|
|
13833
|
+
* name (the yuno it belongs to).
|
|
13834
|
+
* on_close called when the reader dismisses it.
|
|
13835
|
+
*
|
|
13836
|
+
* Returns a handle for close_gclass_view(), or null (and a
|
|
13837
|
+
* logged reason) when there is nothing to show.
|
|
13838
|
+
************************************************************/
|
|
13839
|
+
function open_gclass_view(host, gclass_name, opts) {
|
|
13840
|
+
opts = opts || {};
|
|
13841
|
+
if (!host || !gclass_name) {
|
|
13842
|
+
(0, _yuneta_gobj_js.log_error)(`yui_gclass_view: open without a host or a gclass name`);
|
|
13843
|
+
return null;
|
|
13844
|
+
}
|
|
13845
|
+
let shell = yui_shell_of(host);
|
|
13846
|
+
if (!gclass_view_available()) {
|
|
13847
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(host)}: C_YUI_JSON not registered by the app`);
|
|
13848
|
+
yui_shell_show_error(shell, "gclass viewer unavailable", { t: i18next.t });
|
|
13849
|
+
return null;
|
|
13850
|
+
}
|
|
13851
|
+
let description = opts.description || describe_local_gclass(gclass_name);
|
|
13852
|
+
if (!description) {
|
|
13853
|
+
(0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(host)}: gclass not registered here: ${gclass_name}`);
|
|
13854
|
+
yui_shell_show_error(shell, "gclass not registered in this yuno", { t: i18next.t });
|
|
13855
|
+
return null;
|
|
13856
|
+
}
|
|
13857
|
+
let jv = (0, _yuneta_gobj_js.gobj_create_service)(`gclass-view-${(0, _yuneta_gobj_js.clean_name)((0, _yuneta_gobj_js.gobj_name)(host))}`, "C_YUI_JSON", {
|
|
13858
|
+
json_data: description,
|
|
13859
|
+
subscriber: null
|
|
13860
|
+
}, host);
|
|
13861
|
+
if (!jv) {
|
|
13862
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(host)}: cannot create the gclass viewer`);
|
|
13863
|
+
return null;
|
|
13864
|
+
}
|
|
13865
|
+
let handle = {
|
|
13866
|
+
json_gobj: jv,
|
|
13867
|
+
win: null,
|
|
13868
|
+
modal: null
|
|
13869
|
+
};
|
|
13870
|
+
let $box = (0, _yuneta_gobj_js.gobj_read_pointer_attr)(jv, "$container");
|
|
13871
|
+
let on_close = () => {
|
|
13872
|
+
if (typeof opts.on_close === "function") opts.on_close();
|
|
13873
|
+
};
|
|
13874
|
+
if (is_mobile$3()) {
|
|
13875
|
+
if (!shell) {
|
|
13876
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(host)}: no shell, cannot open the gclass sheet`);
|
|
13877
|
+
close_gclass_view(handle);
|
|
13878
|
+
return null;
|
|
13879
|
+
}
|
|
13880
|
+
handle.modal = yui_shell_show_modal(shell, $box, {
|
|
13881
|
+
dialog: true,
|
|
13882
|
+
logical_class: "GCLASS_VIEW_SHEET",
|
|
13883
|
+
title_prefix: opts.title_prefix || "",
|
|
13884
|
+
title: gclass_name,
|
|
13885
|
+
t: i18next.t,
|
|
13886
|
+
on_close
|
|
13887
|
+
});
|
|
13888
|
+
(0, _yuneta_gobj_js.gobj_start)(jv);
|
|
13889
|
+
return handle;
|
|
13890
|
+
}
|
|
13891
|
+
let $win_parent = window_layer_of(host, shell);
|
|
13892
|
+
handle.win = (0, _yuneta_gobj_js.gobj_create_service)(`gclass-win-${(0, _yuneta_gobj_js.clean_name)((0, _yuneta_gobj_js.gobj_name)(host))}`, "C_YUI_WINDOW", {
|
|
13893
|
+
$parent: $win_parent,
|
|
13894
|
+
subscriber: null,
|
|
13895
|
+
modal: false,
|
|
13896
|
+
showMax: true,
|
|
13897
|
+
showFooter: false,
|
|
13898
|
+
resizable: true,
|
|
13899
|
+
center: true,
|
|
13900
|
+
auto_save_size_and_position: true,
|
|
13901
|
+
width: 720,
|
|
13902
|
+
height: 640,
|
|
13903
|
+
logical_class: "GCLASS_VIEW_WINDOW",
|
|
13904
|
+
title_prefix: opts.title_prefix || "",
|
|
13905
|
+
title: gclass_name,
|
|
13906
|
+
icon: "yi-code",
|
|
13907
|
+
body: $box,
|
|
13908
|
+
manager: (0, _yuneta_gobj_js.gobj_find_service)("__window_manager__", false) || null,
|
|
13909
|
+
on_close
|
|
13910
|
+
}, host);
|
|
13911
|
+
if (!handle.win) {
|
|
13912
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(host)}: cannot create the gclass window`);
|
|
13913
|
+
close_gclass_view(handle);
|
|
13914
|
+
return null;
|
|
13915
|
+
}
|
|
13916
|
+
(0, _yuneta_gobj_js.gobj_start)(handle.win);
|
|
13917
|
+
(0, _yuneta_gobj_js.gobj_start)(jv);
|
|
13918
|
+
return handle;
|
|
13919
|
+
}
|
|
13920
|
+
/************************************************************
|
|
13921
|
+
* Close whatever open_gclass_view() opened. Safe on null and
|
|
13922
|
+
* on a handle whose window the reader already dismissed.
|
|
13923
|
+
************************************************************/
|
|
13924
|
+
function close_gclass_view(handle) {
|
|
13925
|
+
if (!handle) return;
|
|
13926
|
+
let jv = handle.json_gobj;
|
|
13927
|
+
let win = handle.win;
|
|
13928
|
+
let modal = handle.modal;
|
|
13929
|
+
handle.json_gobj = null;
|
|
13930
|
+
handle.win = null;
|
|
13931
|
+
handle.modal = null;
|
|
13932
|
+
if (win && (0, _yuneta_gobj_js.is_gobj)(win)) try {
|
|
13933
|
+
if ((0, _yuneta_gobj_js.gobj_is_running)(win)) (0, _yuneta_gobj_js.gobj_stop)(win);
|
|
13934
|
+
(0, _yuneta_gobj_js.gobj_destroy)(win);
|
|
13935
|
+
} catch (e) {
|
|
13936
|
+
(0, _yuneta_gobj_js.log_warning)(`yui_gclass_view: window already gone: ${e}`);
|
|
13937
|
+
}
|
|
13938
|
+
if (modal && typeof modal.close === "function") try {
|
|
13939
|
+
modal.close();
|
|
13940
|
+
} catch (e) {
|
|
13941
|
+
(0, _yuneta_gobj_js.log_warning)(`yui_gclass_view: modal already gone: ${e}`);
|
|
13942
|
+
}
|
|
13943
|
+
if (jv && (0, _yuneta_gobj_js.is_gobj)(jv)) try {
|
|
13944
|
+
if ((0, _yuneta_gobj_js.gobj_is_running)(jv)) (0, _yuneta_gobj_js.gobj_stop)(jv);
|
|
13945
|
+
(0, _yuneta_gobj_js.gobj_destroy)(jv);
|
|
13946
|
+
} catch (e) {
|
|
13947
|
+
(0, _yuneta_gobj_js.log_warning)(`yui_gclass_view: viewer already gone: ${e}`);
|
|
13948
|
+
}
|
|
13949
|
+
}
|
|
13950
|
+
/************************************************************
|
|
13951
|
+
* Where to mount the window: the SAME element the caller's
|
|
13952
|
+
* own window hangs from.
|
|
13953
|
+
*
|
|
13954
|
+
* Not a preference -- a requirement. z-index only orders
|
|
13955
|
+
* siblings of one stacking context, so a viewer opened from a
|
|
13956
|
+
* window on `body` and mounted in the shell's popup layer
|
|
13957
|
+
* lands BEHIND its opener whatever number it is given, and
|
|
13958
|
+
* the button reads as one that did nothing.
|
|
13959
|
+
************************************************************/
|
|
13960
|
+
function window_layer_of(host, shell) {
|
|
13961
|
+
let $c = (0, _yuneta_gobj_js.gobj_read_pointer_attr)(host, "$container");
|
|
13962
|
+
if ($c && typeof $c.closest === "function") {
|
|
13963
|
+
let $win = $c.closest(".C_YUI_WINDOW");
|
|
13964
|
+
if ($win && $win.parentNode) return $win.parentNode;
|
|
13965
|
+
}
|
|
13966
|
+
return typeof document !== "undefined" && document.getElementById("top-layer") || shell && yui_shell_popup_layer(shell) || null;
|
|
13967
|
+
}
|
|
13968
|
+
/************************************************************
|
|
13969
|
+
* A window is not a sheet: below this width there is no room
|
|
13970
|
+
* for a title bar the reader can drag.
|
|
13971
|
+
************************************************************/
|
|
13972
|
+
function is_mobile$3() {
|
|
13973
|
+
return typeof window !== "undefined" && window.innerWidth <= 768;
|
|
13974
|
+
}
|
|
13975
|
+
//#endregion
|
|
13395
13976
|
//#region src/c_yui_gobj_tree_js.js
|
|
13396
13977
|
/***********************************************************************
|
|
13397
13978
|
* c_yui_gobj_tree_js.js
|
|
@@ -13502,6 +14083,9 @@ var PRIVATE_DATA$9 = {
|
|
|
13502
14083
|
$popover: null,
|
|
13503
14084
|
$popover_title: null,
|
|
13504
14085
|
$popover_body: null,
|
|
14086
|
+
$popover_gclass: null,
|
|
14087
|
+
popover_node: null,
|
|
14088
|
+
gclass_view: null,
|
|
13505
14089
|
node_by_id: null,
|
|
13506
14090
|
collapse_state: null,
|
|
13507
14091
|
resize_observer: null,
|
|
@@ -13516,34 +14100,92 @@ var PRIVATE_DATA$9 = {
|
|
|
13516
14100
|
var __gclass__$9 = null;
|
|
13517
14101
|
var __layout_registered__ = false;
|
|
13518
14102
|
/***************************************************************
|
|
13519
|
-
* Node
|
|
14103
|
+
* Node colours by role.
|
|
14104
|
+
*
|
|
14105
|
+
* Saturated hues, one family apart from the next, and the same
|
|
14106
|
+
* five everywhere the reader meets a gobj. `stroke` draws the
|
|
14107
|
+
* border and the edge; `accent` is the brighter sibling used
|
|
14108
|
+
* for the bar down the left of the card and the toggle badge,
|
|
14109
|
+
* so a card carries its colour twice at two intensities and is
|
|
14110
|
+
* readable at the zoom where the text is not.
|
|
13520
14111
|
***************************************************************/
|
|
13521
14112
|
var ROLE_COLORS = {
|
|
13522
14113
|
yuno: {
|
|
13523
|
-
|
|
13524
|
-
|
|
14114
|
+
stroke: "#0284c7",
|
|
14115
|
+
accent: "#38bdf8"
|
|
13525
14116
|
},
|
|
13526
14117
|
service: {
|
|
13527
|
-
|
|
13528
|
-
|
|
14118
|
+
stroke: "#059669",
|
|
14119
|
+
accent: "#34d399"
|
|
13529
14120
|
},
|
|
13530
14121
|
pure: {
|
|
13531
|
-
|
|
13532
|
-
|
|
14122
|
+
stroke: "#d97706",
|
|
14123
|
+
accent: "#fbbf24"
|
|
13533
14124
|
},
|
|
13534
14125
|
volatil: {
|
|
13535
|
-
|
|
13536
|
-
|
|
14126
|
+
stroke: "#db2777",
|
|
14127
|
+
accent: "#f472b6"
|
|
13537
14128
|
},
|
|
13538
|
-
|
|
13539
|
-
|
|
13540
|
-
|
|
14129
|
+
child: {
|
|
14130
|
+
stroke: "#7c3aed",
|
|
14131
|
+
accent: "#a78bfa"
|
|
13541
14132
|
}
|
|
13542
14133
|
};
|
|
13543
|
-
|
|
13544
|
-
|
|
13545
|
-
|
|
13546
|
-
|
|
14134
|
+
/***************************************************************
|
|
14135
|
+
* Status colours: what the gobj is DOING.
|
|
14136
|
+
*
|
|
14137
|
+
* A pill and not a word: three states of one gobj are told
|
|
14138
|
+
* apart across a whole tree by colour long before anybody
|
|
14139
|
+
* reads them, and the dot alone never said which was which.
|
|
14140
|
+
* `disabled` is a fourth entry and not a status -- a disabled
|
|
14141
|
+
* gobj is still stopped or running -- but it takes the pill,
|
|
14142
|
+
* because it is the fact that explains the other one.
|
|
14143
|
+
***************************************************************/
|
|
14144
|
+
var STATUS_COLORS = {
|
|
14145
|
+
light: {
|
|
14146
|
+
playing: {
|
|
14147
|
+
fg: "#065f46",
|
|
14148
|
+
bg: "#a7f3d0",
|
|
14149
|
+
dot: "#10b981"
|
|
14150
|
+
},
|
|
14151
|
+
running: {
|
|
14152
|
+
fg: "#92400e",
|
|
14153
|
+
bg: "#fde68a",
|
|
14154
|
+
dot: "#f59e0b"
|
|
14155
|
+
},
|
|
14156
|
+
stopped: {
|
|
14157
|
+
fg: "#991b1b",
|
|
14158
|
+
bg: "#fecaca",
|
|
14159
|
+
dot: "#ef4444"
|
|
14160
|
+
},
|
|
14161
|
+
disabled: {
|
|
14162
|
+
fg: "#334155",
|
|
14163
|
+
bg: "#e2e8f0",
|
|
14164
|
+
dot: "#94a3b8"
|
|
14165
|
+
}
|
|
14166
|
+
},
|
|
14167
|
+
dark: {
|
|
14168
|
+
playing: {
|
|
14169
|
+
fg: "#6ee7b7",
|
|
14170
|
+
bg: "rgba(16,185,129,0.28)",
|
|
14171
|
+
dot: "#34d399"
|
|
14172
|
+
},
|
|
14173
|
+
running: {
|
|
14174
|
+
fg: "#fcd34d",
|
|
14175
|
+
bg: "rgba(245,158,11,0.28)",
|
|
14176
|
+
dot: "#fbbf24"
|
|
14177
|
+
},
|
|
14178
|
+
stopped: {
|
|
14179
|
+
fg: "#fca5a5",
|
|
14180
|
+
bg: "rgba(239,68,68,0.28)",
|
|
14181
|
+
dot: "#f87171"
|
|
14182
|
+
},
|
|
14183
|
+
disabled: {
|
|
14184
|
+
fg: "#cbd5e1",
|
|
14185
|
+
bg: "rgba(148,163,184,0.28)",
|
|
14186
|
+
dot: "#94a3b8"
|
|
14187
|
+
}
|
|
14188
|
+
}
|
|
13547
14189
|
};
|
|
13548
14190
|
/***************************************************************
|
|
13549
14191
|
* Fixed node sizes per role (px).
|
|
@@ -13553,16 +14195,16 @@ var STATE_COLORS = {
|
|
|
13553
14195
|
var NODE_SIZES = {
|
|
13554
14196
|
full: {
|
|
13555
14197
|
yuno: {
|
|
13556
|
-
w:
|
|
13557
|
-
h:
|
|
14198
|
+
w: 260,
|
|
14199
|
+
h: 96
|
|
13558
14200
|
},
|
|
13559
14201
|
service: {
|
|
13560
|
-
w:
|
|
13561
|
-
h:
|
|
14202
|
+
w: 232,
|
|
14203
|
+
h: 92
|
|
13562
14204
|
},
|
|
13563
14205
|
child: {
|
|
13564
|
-
w:
|
|
13565
|
-
h:
|
|
14206
|
+
w: 196,
|
|
14207
|
+
h: 86
|
|
13566
14208
|
}
|
|
13567
14209
|
},
|
|
13568
14210
|
compact: {
|
|
@@ -13585,27 +14227,47 @@ var NODE_SIZES = {
|
|
|
13585
14227
|
***************************************************************/
|
|
13586
14228
|
var GT_FONT = "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif";
|
|
13587
14229
|
/***************************************************************
|
|
13588
|
-
*
|
|
13589
|
-
*
|
|
13590
|
-
*
|
|
14230
|
+
* Theme-aware card palette derived from the role colour.
|
|
14231
|
+
*
|
|
14232
|
+
* Brighter than a tint: at 9% of the role colour every card
|
|
14233
|
+
* was the same near-white rectangle and the tree read as a
|
|
14234
|
+
* wireframe. The fill carries enough of the hue to be named
|
|
14235
|
+
* from across the canvas, and the border and the accent bar
|
|
14236
|
+
* carry the rest.
|
|
13591
14237
|
***************************************************************/
|
|
13592
|
-
function role_card_style(
|
|
14238
|
+
function role_card_style(colors, dark) {
|
|
14239
|
+
let stroke = colors.stroke;
|
|
14240
|
+
let accent = colors.accent;
|
|
13593
14241
|
return {
|
|
13594
|
-
bg: dark ? `color-mix(in srgb, ${stroke}
|
|
13595
|
-
border: dark ?
|
|
13596
|
-
|
|
13597
|
-
|
|
13598
|
-
|
|
13599
|
-
|
|
14242
|
+
bg: dark ? `color-mix(in srgb, ${stroke} 34%, #253044)` : `color-mix(in srgb, ${stroke} 13%, #ffffff)`,
|
|
14243
|
+
border: dark ? accent : stroke,
|
|
14244
|
+
accent: dark ? accent : stroke,
|
|
14245
|
+
title: dark ? "#f1f5f9" : "#0f172a",
|
|
14246
|
+
sub: dark ? "#a8b3c2" : "#475569",
|
|
14247
|
+
tagbg: dark ? `color-mix(in srgb, ${stroke} 48%, #253044)` : `color-mix(in srgb, ${stroke} 20%, #ffffff)`,
|
|
14248
|
+
tagfg: dark ? "#f1f5f9" : stroke,
|
|
14249
|
+
shadow: dark ? "0 2px 6px rgba(0,0,0,0.50)" : "0 2px 5px rgba(15,23,42,0.16)"
|
|
13600
14250
|
};
|
|
13601
14251
|
}
|
|
13602
14252
|
/***************************************************************
|
|
13603
|
-
*
|
|
14253
|
+
* The pill colours of a node, for the theme in force.
|
|
13604
14254
|
***************************************************************/
|
|
13605
|
-
function
|
|
13606
|
-
|
|
13607
|
-
if (
|
|
13608
|
-
return
|
|
14255
|
+
function status_card_style(d, dark) {
|
|
14256
|
+
let table = dark ? STATUS_COLORS.dark : STATUS_COLORS.light;
|
|
14257
|
+
if (d.disabled) return table.disabled;
|
|
14258
|
+
return table[node_status(d)] || table.stopped;
|
|
14259
|
+
}
|
|
14260
|
+
/***************************************************************
|
|
14261
|
+
* Map a node to its visual size class. Services are drawn
|
|
14262
|
+
* bigger than plain children so the service boundary of the
|
|
14263
|
+
* hierarchy is visible before anything is read.
|
|
14264
|
+
***************************************************************/
|
|
14265
|
+
function get_node_category(d) {
|
|
14266
|
+
switch (node_role(d)) {
|
|
14267
|
+
case "yuno": return "yuno";
|
|
14268
|
+
case "service": return "service";
|
|
14269
|
+
default: return "child";
|
|
14270
|
+
}
|
|
13609
14271
|
}
|
|
13610
14272
|
/***************************************************************
|
|
13611
14273
|
* Layouts registry.
|
|
@@ -13718,13 +14380,21 @@ function mt_create$9(gobj) {
|
|
|
13718
14380
|
***************************************************************/
|
|
13719
14381
|
function mt_start$9(gobj) {
|
|
13720
14382
|
restore_view_shape(gobj);
|
|
14383
|
+
let shell = yui_shell_of(gobj);
|
|
14384
|
+
if (shell) (0, _yuneta_gobj_js.gobj_subscribe_event)(shell, "EV_LANGUAGE_CHANGED", {}, gobj);
|
|
13721
14385
|
build_graph$2(gobj);
|
|
13722
14386
|
load_tree(gobj);
|
|
13723
14387
|
}
|
|
13724
14388
|
/***************************************************************
|
|
13725
14389
|
* Framework Method: Stop
|
|
13726
14390
|
***************************************************************/
|
|
13727
|
-
function mt_stop$9(gobj) {
|
|
14391
|
+
function mt_stop$9(gobj) {
|
|
14392
|
+
let priv = gobj.priv;
|
|
14393
|
+
let shell = yui_shell_of(gobj);
|
|
14394
|
+
if (shell) (0, _yuneta_gobj_js.gobj_unsubscribe_event)(shell, "EV_LANGUAGE_CHANGED", {}, gobj);
|
|
14395
|
+
close_gclass_view(priv.gclass_view);
|
|
14396
|
+
priv.gclass_view = null;
|
|
14397
|
+
}
|
|
13728
14398
|
/***************************************************************
|
|
13729
14399
|
* Framework Method: Destroy
|
|
13730
14400
|
***************************************************************/
|
|
@@ -13750,6 +14420,8 @@ function mt_destroy$9(gobj) {
|
|
|
13750
14420
|
priv.$popover = null;
|
|
13751
14421
|
priv.$popover_title = null;
|
|
13752
14422
|
priv.$popover_body = null;
|
|
14423
|
+
priv.$popover_gclass = null;
|
|
14424
|
+
priv.popover_node = null;
|
|
13753
14425
|
priv.$layout_select = null;
|
|
13754
14426
|
priv.node_by_id = null;
|
|
13755
14427
|
priv.collapse_state = null;
|
|
@@ -13853,6 +14525,30 @@ function build_popover(gobj, $container) {
|
|
|
13853
14525
|
text-overflow: ellipsis;
|
|
13854
14526
|
`;
|
|
13855
14527
|
$header.appendChild($title);
|
|
14528
|
+
if (gclass_view_available()) {
|
|
14529
|
+
let $gclass = document.createElement("button");
|
|
14530
|
+
$gclass.type = "button";
|
|
14531
|
+
$gclass.className = "GOBJ_TREE_POPOVER_GCLASS button is-small";
|
|
14532
|
+
$gclass.style.cssText = `
|
|
14533
|
+
margin-right: 6px;
|
|
14534
|
+
padding: 0 8px;
|
|
14535
|
+
height: 22px;
|
|
14536
|
+
font-size: 11px;
|
|
14537
|
+
white-space: nowrap;
|
|
14538
|
+
`;
|
|
14539
|
+
$gclass.textContent = (0, i18next.t)("gclass");
|
|
14540
|
+
$gclass.setAttribute("i18n", "gclass");
|
|
14541
|
+
$gclass.title = (0, i18next.t)("view gclass");
|
|
14542
|
+
$gclass.setAttribute("data-i18n-title", "view gclass");
|
|
14543
|
+
$gclass.setAttribute("aria-label", (0, i18next.t)("view gclass"));
|
|
14544
|
+
$gclass.setAttribute("data-i18n-aria-label", "view gclass");
|
|
14545
|
+
$gclass.addEventListener("click", (evt) => {
|
|
14546
|
+
evt.stopPropagation();
|
|
14547
|
+
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_OPEN_GCLASS", {}, gobj);
|
|
14548
|
+
});
|
|
14549
|
+
$header.appendChild($gclass);
|
|
14550
|
+
priv.$popover_gclass = $gclass;
|
|
14551
|
+
} else (0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: no C_YUI_JSON registered, the gclass viewer is not offered`);
|
|
13856
14552
|
let $close = document.createElement("button");
|
|
13857
14553
|
$close.type = "button";
|
|
13858
14554
|
$close.className = "GOBJ_TREE_POPOVER_CLOSE";
|
|
@@ -13960,6 +14656,26 @@ function make_toolbar$1(gobj) {
|
|
|
13960
14656
|
return $toolbar;
|
|
13961
14657
|
}
|
|
13962
14658
|
/************************************************************
|
|
14659
|
+
* The element G6 mounts its canvas in.
|
|
14660
|
+
*
|
|
14661
|
+
* Read from THIS gclass's own $container, never with
|
|
14662
|
+
* `document.getElementById()`: a view is not always in the
|
|
14663
|
+
* document when it is started -- a host that builds the
|
|
14664
|
+
* viewer and mounts it into a window afterwards starts it
|
|
14665
|
+
* DETACHED -- and a global lookup answers null there. It cost
|
|
14666
|
+
* a resize that never worked: the ResizeObserver below was
|
|
14667
|
+
* simply never attached, silently, and the canvas kept the
|
|
14668
|
+
* size it was born with for the life of the window.
|
|
14669
|
+
*
|
|
14670
|
+
* Null only if the UI was never built; that is a bug, and it
|
|
14671
|
+
* is logged where it matters rather than skipped.
|
|
14672
|
+
************************************************************/
|
|
14673
|
+
function canvas_mount(gobj) {
|
|
14674
|
+
let $container = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
|
|
14675
|
+
if (!$container) return null;
|
|
14676
|
+
return $container.querySelector("#" + gobj.priv.canvas_id);
|
|
14677
|
+
}
|
|
14678
|
+
/************************************************************
|
|
13963
14679
|
* Build a G6 graph instance
|
|
13964
14680
|
************************************************************/
|
|
13965
14681
|
function build_graph$2(gobj) {
|
|
@@ -14003,8 +14719,9 @@ function build_graph$2(gobj) {
|
|
|
14003
14719
|
hide_popover(gobj);
|
|
14004
14720
|
});
|
|
14005
14721
|
if (typeof ResizeObserver !== "undefined") {
|
|
14006
|
-
let $canvas =
|
|
14007
|
-
if (
|
|
14722
|
+
let $canvas = canvas_mount(gobj);
|
|
14723
|
+
if (!$canvas) (0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: no canvas mount, the graph will never resize`);
|
|
14724
|
+
else {
|
|
14008
14725
|
let ro = new ResizeObserver(() => {
|
|
14009
14726
|
if (priv._resize_raf) cancelAnimationFrame(priv._resize_raf);
|
|
14010
14727
|
priv._resize_raf = requestAnimationFrame(() => {
|
|
@@ -14037,22 +14754,20 @@ function apply_layout(gobj) {
|
|
|
14037
14754
|
});
|
|
14038
14755
|
}
|
|
14039
14756
|
/************************************************************
|
|
14040
|
-
*
|
|
14041
|
-
|
|
14042
|
-
|
|
14043
|
-
|
|
14044
|
-
|
|
14045
|
-
if ((0, _yuneta_gobj_js.gobj_is_service)(target_gobj)) return ROLE_COLORS.service;
|
|
14046
|
-
if ((0, _yuneta_gobj_js.gobj_is_pure_child)(target_gobj)) return ROLE_COLORS.pure;
|
|
14047
|
-
return ROLE_COLORS.default;
|
|
14048
|
-
}
|
|
14049
|
-
/************************************************************
|
|
14050
|
-
* Resolve state color
|
|
14757
|
+
* The role colours of a node.
|
|
14758
|
+
*
|
|
14759
|
+
* Note the ORDER: volatil before service. A volatil gobj that
|
|
14760
|
+
* is also a service is drawn volatil, because that is the fact
|
|
14761
|
+
* that decides how long it lives.
|
|
14051
14762
|
************************************************************/
|
|
14052
|
-
function
|
|
14053
|
-
|
|
14054
|
-
|
|
14055
|
-
|
|
14763
|
+
function get_role_colors(d) {
|
|
14764
|
+
switch (node_role(d)) {
|
|
14765
|
+
case "yuno": return ROLE_COLORS.yuno;
|
|
14766
|
+
case "volatil": return ROLE_COLORS.volatil;
|
|
14767
|
+
case "service": return ROLE_COLORS.service;
|
|
14768
|
+
case "pure": return ROLE_COLORS.pure;
|
|
14769
|
+
default: return ROLE_COLORS.child;
|
|
14770
|
+
}
|
|
14056
14771
|
}
|
|
14057
14772
|
/************************************************************
|
|
14058
14773
|
* Generate a unique node id
|
|
@@ -14084,72 +14799,135 @@ function is_node_collapsed(gobj, full_name, num_children) {
|
|
|
14084
14799
|
************************************************************/
|
|
14085
14800
|
function render_toggle_html(node_id, collapsed, num_children, cs) {
|
|
14086
14801
|
let label = collapsed ? "+" + num_children : "−";
|
|
14802
|
+
let title = collapsed ? (0, i18next.t)("expand children") : (0, i18next.t)("collapse children");
|
|
14087
14803
|
return `<span
|
|
14088
14804
|
data-gobj-toggle="true"
|
|
14089
14805
|
data-node-id="${node_id}"
|
|
14090
|
-
title="${
|
|
14806
|
+
title="${(0, _yuneta_gobj_js.escapeHtml)(title)}"
|
|
14091
14807
|
style="
|
|
14092
14808
|
flex: 0 0 auto;
|
|
14093
14809
|
display: inline-flex;
|
|
14094
14810
|
align-items: center;
|
|
14095
14811
|
justify-content: center;
|
|
14096
|
-
min-width:
|
|
14097
|
-
height:
|
|
14098
|
-
padding: 0
|
|
14812
|
+
min-width: 24px;
|
|
14813
|
+
height: 18px;
|
|
14814
|
+
padding: 0 6px;
|
|
14099
14815
|
margin-left: 4px;
|
|
14100
|
-
background: ${cs.
|
|
14101
|
-
color:
|
|
14102
|
-
border: 1px solid ${cs.
|
|
14103
|
-
border-radius:
|
|
14816
|
+
background: ${cs.accent};
|
|
14817
|
+
color: #ffffff;
|
|
14818
|
+
border: 1px solid ${cs.accent};
|
|
14819
|
+
border-radius: 9px;
|
|
14104
14820
|
font-size: 10px;
|
|
14105
|
-
font-weight:
|
|
14821
|
+
font-weight: 700;
|
|
14106
14822
|
line-height: 1;
|
|
14107
14823
|
cursor: pointer;
|
|
14108
14824
|
user-select: none;
|
|
14109
14825
|
">${label}</span>`;
|
|
14110
14826
|
}
|
|
14111
14827
|
/************************************************************
|
|
14112
|
-
*
|
|
14828
|
+
* HTML for the status pill: what the gobj is DOING.
|
|
14829
|
+
*
|
|
14830
|
+
* A dot plus a word, and the word is dropped in the compact
|
|
14831
|
+
* card where there is no room for it -- the colour still
|
|
14832
|
+
* carries it, and the `title` says it in full either way.
|
|
14113
14833
|
************************************************************/
|
|
14114
|
-
function
|
|
14834
|
+
function render_status_html(d, ss, labels, with_label) {
|
|
14835
|
+
let full = d.disabled ? labels.field.disabled : labels.status[node_status_key(d)] || node_status_key(d);
|
|
14836
|
+
let label = d.disabled ? labels.field.disabled : labels.status_short[node_status(d)] || node_status(d);
|
|
14837
|
+
if (!with_label) return `<span title="${(0, _yuneta_gobj_js.escapeHtml)(full)}" style="
|
|
14838
|
+
flex: 0 0 auto;
|
|
14839
|
+
width: 10px; height: 10px; border-radius: 50%;
|
|
14840
|
+
background: ${ss.dot};
|
|
14841
|
+
box-shadow: 0 0 0 2px ${ss.bg};
|
|
14842
|
+
margin-left: 6px;
|
|
14843
|
+
"></span>`;
|
|
14844
|
+
return `<span title="${(0, _yuneta_gobj_js.escapeHtml)(full)}" style="
|
|
14845
|
+
flex: 0 0 auto;
|
|
14846
|
+
display: inline-flex;
|
|
14847
|
+
align-items: center;
|
|
14848
|
+
gap: 4px;
|
|
14849
|
+
padding: 1px 7px 1px 5px;
|
|
14850
|
+
background: ${ss.bg};
|
|
14851
|
+
color: ${ss.fg};
|
|
14852
|
+
border-radius: 9px;
|
|
14853
|
+
font-size: 10px;
|
|
14854
|
+
font-weight: 700;
|
|
14855
|
+
line-height: 1.45;
|
|
14856
|
+
white-space: nowrap;
|
|
14857
|
+
"><span style="width:7px; height:7px; border-radius:50%; background:${ss.dot};"></span>${(0, _yuneta_gobj_js.escapeHtml)(label)}</span>`;
|
|
14858
|
+
}
|
|
14859
|
+
/************************************************************
|
|
14860
|
+
* HTML for the badges: what the gobj IS, besides its colour.
|
|
14861
|
+
************************************************************/
|
|
14862
|
+
function render_badges_html(d, cs, labels) {
|
|
14863
|
+
let html = "";
|
|
14864
|
+
for (let key of node_badge_keys(d)) {
|
|
14865
|
+
let label = labels.badge[key] || key;
|
|
14866
|
+
html += `<span style="
|
|
14867
|
+
font-size: 10px;
|
|
14868
|
+
font-weight: 600;
|
|
14869
|
+
padding: 0 6px;
|
|
14870
|
+
margin-right: 4px;
|
|
14871
|
+
background: ${cs.tagbg};
|
|
14872
|
+
color: ${cs.tagfg};
|
|
14873
|
+
border: 1px solid ${cs.accent};
|
|
14874
|
+
border-radius: 9px;
|
|
14875
|
+
white-space: nowrap;
|
|
14876
|
+
">${(0, _yuneta_gobj_js.escapeHtml)(label)}</span>`;
|
|
14877
|
+
}
|
|
14878
|
+
return html;
|
|
14879
|
+
}
|
|
14880
|
+
/************************************************************
|
|
14881
|
+
* Recursively build nodes and edges from a NODE DESCRIPTOR
|
|
14882
|
+
* tree (gobj_tree_model.js), never from gobjs: the same
|
|
14883
|
+
* builder draws the browser yuno and a backend one.
|
|
14884
|
+
*
|
|
14885
|
+
* The descriptor is also what the popover reads, so the view
|
|
14886
|
+
* fields it needs are written onto it here (`full_name`,
|
|
14887
|
+
* `short_name`, `num_children`, `is_collapsed`,
|
|
14888
|
+
* `direct_children`) instead of copied into a second object
|
|
14889
|
+
* that can then disagree with the first.
|
|
14890
|
+
************************************************************/
|
|
14891
|
+
function build_gobj_nodes(gobj, d, nodes, edges, parent_id, compact, labels) {
|
|
14115
14892
|
let priv = gobj.priv;
|
|
14116
14893
|
let node_id = gen_node_id(gobj);
|
|
14117
|
-
let gclass_name = (0, _yuneta_gobj_js.gobj_gclass_name)(target_gobj) || "";
|
|
14118
|
-
let instance_name = (0, _yuneta_gobj_js.gobj_name)(target_gobj) || "";
|
|
14119
|
-
let state = (0, _yuneta_gobj_js.gobj_current_state)(target_gobj) || "";
|
|
14120
|
-
let full_name = (0, _yuneta_gobj_js.gobj_full_name)(target_gobj);
|
|
14121
|
-
let colors = get_role_colors(target_gobj, is_root);
|
|
14122
14894
|
let dark = yui_is_dark();
|
|
14123
|
-
let
|
|
14124
|
-
let
|
|
14125
|
-
let
|
|
14126
|
-
let
|
|
14127
|
-
let status_text = !running ? "stopped" : playing ? "playing" : "running";
|
|
14128
|
-
let category = get_node_category(target_gobj, is_root);
|
|
14895
|
+
let colors = get_role_colors(d);
|
|
14896
|
+
let cs = role_card_style(colors, dark);
|
|
14897
|
+
let ss = status_card_style(d, dark);
|
|
14898
|
+
let category = get_node_category(d);
|
|
14129
14899
|
let size = NODE_SIZES[compact ? "compact" : "full"][category];
|
|
14130
14900
|
let width = size.w;
|
|
14131
14901
|
let height = size.h;
|
|
14132
14902
|
let border_width = category === "yuno" || category === "service" ? 2 : 1;
|
|
14133
|
-
let
|
|
14903
|
+
let border_style = d.disabled ? "dashed" : "solid";
|
|
14904
|
+
let children = d.children || [];
|
|
14134
14905
|
let num_children = children.length;
|
|
14135
14906
|
let has_children = num_children > 0;
|
|
14136
|
-
let collapsed = has_children && is_node_collapsed(gobj,
|
|
14907
|
+
let collapsed = has_children && is_node_collapsed(gobj, d.fullname, num_children);
|
|
14137
14908
|
let direct_children = [];
|
|
14138
14909
|
for (let child of children) direct_children.push({
|
|
14139
|
-
full_name:
|
|
14140
|
-
has_grandchildren: (child.
|
|
14910
|
+
full_name: child.fullname,
|
|
14911
|
+
has_grandchildren: (child.children || []).length > 0
|
|
14141
14912
|
});
|
|
14913
|
+
d.full_name = d.fullname;
|
|
14914
|
+
d.short_name = d.shortname;
|
|
14915
|
+
d.num_children = num_children;
|
|
14916
|
+
d.is_collapsed = collapsed;
|
|
14917
|
+
d.direct_children = direct_children;
|
|
14918
|
+
d.node_id = node_id;
|
|
14142
14919
|
let toggle_html = has_children ? render_toggle_html(node_id, collapsed, num_children, cs) : "";
|
|
14920
|
+
let card_title = d.gclass + (d.name ? "^" + d.name : "");
|
|
14143
14921
|
let node_html;
|
|
14144
14922
|
if (compact) {
|
|
14145
|
-
let compact_label = (0, _yuneta_gobj_js.escapeHtml)(
|
|
14923
|
+
let compact_label = (0, _yuneta_gobj_js.escapeHtml)(card_title);
|
|
14146
14924
|
node_html = `
|
|
14147
|
-
<div class="GOBJ_CARD" data-gobj-name="${(0, _yuneta_gobj_js.escapeHtml)(
|
|
14925
|
+
<div class="GOBJ_CARD" data-gobj-name="${(0, _yuneta_gobj_js.escapeHtml)(d.fullname)}" style="
|
|
14148
14926
|
width: ${width}px;
|
|
14149
14927
|
height: ${height}px;
|
|
14150
14928
|
background: ${cs.bg};
|
|
14151
|
-
border: ${border_width}px
|
|
14152
|
-
border-left:
|
|
14929
|
+
border: ${border_width}px ${border_style} ${cs.border};
|
|
14930
|
+
border-left: 6px solid ${cs.accent};
|
|
14153
14931
|
border-radius: 7px;
|
|
14154
14932
|
box-shadow: ${cs.shadow};
|
|
14155
14933
|
font-family: ${GT_FONT};
|
|
@@ -14158,34 +14936,24 @@ function build_gobj_nodes(gobj, target_gobj, nodes, edges, parent_id, is_root, c
|
|
|
14158
14936
|
padding: 0 8px;
|
|
14159
14937
|
box-sizing: border-box;
|
|
14160
14938
|
overflow: hidden;
|
|
14939
|
+
opacity: ${d.disabled ? "0.72" : "1"};
|
|
14161
14940
|
cursor: pointer;
|
|
14162
14941
|
" title="${compact_label}">
|
|
14163
14942
|
<span style="flex:1 1 auto; min-width:0; font-size:11px; font-weight:600; color:${cs.title}; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">${compact_label}</span>
|
|
14164
|
-
|
|
14165
|
-
flex: 0 0 auto;
|
|
14166
|
-
width: 8px; height: 8px; border-radius: 50%;
|
|
14167
|
-
background: ${state_color}; margin-left: 6px;
|
|
14168
|
-
"></span>
|
|
14943
|
+
${render_status_html(d, ss, labels, false)}
|
|
14169
14944
|
${toggle_html}
|
|
14170
14945
|
</div>`;
|
|
14171
14946
|
} else {
|
|
14172
|
-
let header_label = (0, _yuneta_gobj_js.escapeHtml)(
|
|
14173
|
-
let name_label = (0, _yuneta_gobj_js.escapeHtml)(
|
|
14174
|
-
let state_label = (0, _yuneta_gobj_js.escapeHtml)(state);
|
|
14175
|
-
let badges = [];
|
|
14176
|
-
if (is_root) badges.push("yuno");
|
|
14177
|
-
else {
|
|
14178
|
-
if ((0, _yuneta_gobj_js.gobj_is_service)(target_gobj)) badges.push("service");
|
|
14179
|
-
if ((0, _yuneta_gobj_js.gobj_is_pure_child)(target_gobj)) badges.push("pure");
|
|
14180
|
-
if ((0, _yuneta_gobj_js.gobj_is_volatil)(target_gobj)) badges.push("volatil");
|
|
14181
|
-
}
|
|
14182
|
-
let badges_html = badges.map((b) => `<span style="font-size:10px; padding:0 5px; margin-right:4px; background:${cs.tagbg}; color:${cs.border}; border:1px solid ${cs.border}; border-radius:6px; white-space:nowrap;">${b}</span>`).join("");
|
|
14947
|
+
let header_label = (0, _yuneta_gobj_js.escapeHtml)(d.gclass);
|
|
14948
|
+
let name_label = (0, _yuneta_gobj_js.escapeHtml)(d.name);
|
|
14949
|
+
let state_label = (0, _yuneta_gobj_js.escapeHtml)(d.state);
|
|
14183
14950
|
node_html = `
|
|
14184
|
-
<div class="GOBJ_CARD" data-gobj-name="${(0, _yuneta_gobj_js.escapeHtml)(
|
|
14951
|
+
<div class="GOBJ_CARD" data-gobj-name="${(0, _yuneta_gobj_js.escapeHtml)(d.fullname)}" style="
|
|
14185
14952
|
width: ${width}px;
|
|
14186
14953
|
height: ${height}px;
|
|
14187
14954
|
background: ${cs.bg};
|
|
14188
|
-
border: ${border_width}px
|
|
14955
|
+
border: ${border_width}px ${border_style} ${cs.border};
|
|
14956
|
+
border-left: 6px solid ${cs.accent};
|
|
14189
14957
|
border-radius: 9px;
|
|
14190
14958
|
box-shadow: ${cs.shadow};
|
|
14191
14959
|
overflow: hidden;
|
|
@@ -14194,48 +14962,29 @@ function build_gobj_nodes(gobj, target_gobj, nodes, edges, parent_id, is_root, c
|
|
|
14194
14962
|
display: flex;
|
|
14195
14963
|
flex-direction: column;
|
|
14196
14964
|
justify-content: center;
|
|
14197
|
-
padding:
|
|
14198
|
-
gap:
|
|
14965
|
+
padding: 6px 9px;
|
|
14966
|
+
gap: 2px;
|
|
14967
|
+
opacity: ${d.disabled ? "0.72" : "1"};
|
|
14199
14968
|
cursor: pointer;
|
|
14200
|
-
" title="${(0, _yuneta_gobj_js.escapeHtml)(
|
|
14969
|
+
" title="${(0, _yuneta_gobj_js.escapeHtml)(card_title)}">
|
|
14201
14970
|
<div style="flex:0 0 auto; display:flex; align-items:center; gap:6px; overflow:hidden;">
|
|
14202
|
-
<span style="flex:1 1 auto; min-width:0; font-size:12px; line-height:1.25; font-weight:
|
|
14971
|
+
<span style="flex:1 1 auto; min-width:0; font-size:12px; line-height:1.25; font-weight:700; color:${cs.title}; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">${header_label}</span>
|
|
14203
14972
|
${toggle_html}
|
|
14204
14973
|
</div>
|
|
14205
14974
|
<div style="flex:0 0 auto; font-size:12px; line-height:1.25; color:${cs.sub}; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">${name_label || " "}</div>
|
|
14206
14975
|
<div style="flex:0 0 auto; display:flex; justify-content:space-between; align-items:center; gap:6px; overflow:hidden;">
|
|
14207
|
-
<span style="flex:1 1 auto; min-width:0;
|
|
14208
|
-
|
|
14209
|
-
<span style="width:7px; height:7px; border-radius:50%; background:${state_color};"></span>${state_label || status_text}
|
|
14210
|
-
</span>
|
|
14976
|
+
<span style="flex:1 1 auto; min-width:0; font-size:10px; line-height:1.25; color:${cs.sub}; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">${state_label || " "}</span>
|
|
14977
|
+
${render_status_html(d, ss, labels, true)}
|
|
14211
14978
|
</div>
|
|
14979
|
+
<div style="flex:0 0 auto; overflow:hidden; white-space:nowrap; text-overflow:ellipsis;">${render_badges_html(d, cs, labels)}</div>
|
|
14212
14980
|
</div>`;
|
|
14213
14981
|
}
|
|
14214
|
-
let parent_gobj = (0, _yuneta_gobj_js.gobj_parent)(target_gobj);
|
|
14215
|
-
let node_data = {
|
|
14216
|
-
gclass: gclass_name,
|
|
14217
|
-
name: instance_name,
|
|
14218
|
-
short_name: (0, _yuneta_gobj_js.gobj_short_name)(target_gobj),
|
|
14219
|
-
full_name,
|
|
14220
|
-
parent_short_name: parent_gobj ? (0, _yuneta_gobj_js.gobj_short_name)(parent_gobj) : "",
|
|
14221
|
-
state,
|
|
14222
|
-
category,
|
|
14223
|
-
is_yuno: is_root,
|
|
14224
|
-
is_service: (0, _yuneta_gobj_js.gobj_is_service)(target_gobj),
|
|
14225
|
-
is_pure_child: (0, _yuneta_gobj_js.gobj_is_pure_child)(target_gobj),
|
|
14226
|
-
is_volatil: (0, _yuneta_gobj_js.gobj_is_volatil)(target_gobj),
|
|
14227
|
-
is_running: running,
|
|
14228
|
-
is_playing: playing,
|
|
14229
|
-
num_children,
|
|
14230
|
-
is_collapsed: collapsed,
|
|
14231
|
-
direct_children
|
|
14232
|
-
};
|
|
14233
14982
|
if (!priv.node_by_id) priv.node_by_id = {};
|
|
14234
|
-
priv.node_by_id[node_id] =
|
|
14983
|
+
priv.node_by_id[node_id] = d;
|
|
14235
14984
|
let node = {
|
|
14236
14985
|
id: node_id,
|
|
14237
14986
|
type: "html",
|
|
14238
|
-
data:
|
|
14987
|
+
data: d,
|
|
14239
14988
|
style: {
|
|
14240
14989
|
innerHTML: node_html,
|
|
14241
14990
|
size: [width, height],
|
|
@@ -14248,11 +14997,11 @@ function build_gobj_nodes(gobj, target_gobj, nodes, edges, parent_id, is_root, c
|
|
|
14248
14997
|
source: parent_id,
|
|
14249
14998
|
target: node_id,
|
|
14250
14999
|
style: {
|
|
14251
|
-
stroke: colors.
|
|
14252
|
-
lineWidth: 1
|
|
15000
|
+
stroke: colors.accent,
|
|
15001
|
+
lineWidth: 1.4
|
|
14253
15002
|
}
|
|
14254
15003
|
});
|
|
14255
|
-
if (!collapsed) for (let child of children) build_gobj_nodes(gobj, child, nodes, edges, node_id,
|
|
15004
|
+
if (!collapsed) for (let child of children) build_gobj_nodes(gobj, child, nodes, edges, node_id, compact, labels);
|
|
14256
15005
|
return node_id;
|
|
14257
15006
|
}
|
|
14258
15007
|
/************************************************************
|
|
@@ -14269,9 +15018,13 @@ function load_tree(gobj) {
|
|
|
14269
15018
|
let priv = gobj.priv;
|
|
14270
15019
|
let graph = priv.graph;
|
|
14271
15020
|
if (!graph) return;
|
|
14272
|
-
let
|
|
14273
|
-
if (!
|
|
15021
|
+
let root = describe_js_gobj((0, _yuneta_gobj_js.gobj_yuno)(), true);
|
|
15022
|
+
if (!root) {
|
|
15023
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: no yuno to draw`);
|
|
15024
|
+
return;
|
|
15025
|
+
}
|
|
14274
15026
|
let layout_cfg = get_layout_cfg((0, _yuneta_gobj_js.gobj_read_str_attr)(gobj, "layout"));
|
|
15027
|
+
let labels = node_labels(i18next.t);
|
|
14275
15028
|
let anchor = priv.pending_anchor || null;
|
|
14276
15029
|
let preserve_view = !!priv.pending_preserve_view;
|
|
14277
15030
|
priv.pending_anchor = null;
|
|
@@ -14280,7 +15033,7 @@ function load_tree(gobj) {
|
|
|
14280
15033
|
priv.node_by_id = {};
|
|
14281
15034
|
let nodes = [];
|
|
14282
15035
|
let edges = [];
|
|
14283
|
-
build_gobj_nodes(gobj,
|
|
15036
|
+
build_gobj_nodes(gobj, root, nodes, edges, null, layout_cfg.compact, labels);
|
|
14284
15037
|
if (nodes.length > 0) {
|
|
14285
15038
|
let root_id = nodes[0].id;
|
|
14286
15039
|
graph.setData({
|
|
@@ -14381,46 +15134,17 @@ function refresh_tree(gobj, opts) {
|
|
|
14381
15134
|
}
|
|
14382
15135
|
}
|
|
14383
15136
|
/************************************************************
|
|
14384
|
-
* Rows to show in the popover for a given node data.
|
|
14385
|
-
*
|
|
14386
|
-
* This is the extension point: to surface a new attribute,
|
|
14387
|
-
* collect it into `node_data` in build_gobj_nodes(), then
|
|
14388
|
-
* append a `[label, value]` pair here.
|
|
14389
|
-
************************************************************/
|
|
14390
|
-
function get_node_info_rows(node_data) {
|
|
14391
|
-
let rows = [];
|
|
14392
|
-
rows.push([(0, i18next.t)("gclass"), node_data.gclass || "—"]);
|
|
14393
|
-
rows.push([(0, i18next.t)("name"), node_data.name || "—"]);
|
|
14394
|
-
if (node_data.full_name && node_data.full_name !== node_data.short_name) rows.push([(0, i18next.t)("full name"), node_data.full_name]);
|
|
14395
|
-
let role;
|
|
14396
|
-
if (node_data.is_yuno) role = "yuno";
|
|
14397
|
-
else if (node_data.is_service) role = "service";
|
|
14398
|
-
else if (node_data.is_volatil) role = "volatil child";
|
|
14399
|
-
else if (node_data.is_pure_child) role = "pure child";
|
|
14400
|
-
else role = "child";
|
|
14401
|
-
rows.push([(0, i18next.t)("role"), role]);
|
|
14402
|
-
let status;
|
|
14403
|
-
if (!node_data.is_running) status = "stopped";
|
|
14404
|
-
else if (node_data.is_playing) status = "running + playing";
|
|
14405
|
-
else status = "running";
|
|
14406
|
-
rows.push([(0, i18next.t)("status"), status]);
|
|
14407
|
-
rows.push([(0, i18next.t)("state"), node_data.state || "—"]);
|
|
14408
|
-
if (node_data.parent_short_name) rows.push([(0, i18next.t)("parent"), node_data.parent_short_name]);
|
|
14409
|
-
if (typeof node_data.num_children === "number") {
|
|
14410
|
-
let kids = node_data.num_children;
|
|
14411
|
-
if (kids > 0 && node_data.is_collapsed) rows.push([(0, i18next.t)("children"), kids + " " + (0, i18next.t)("(collapsed)")]);
|
|
14412
|
-
else if (kids > 0) rows.push([(0, i18next.t)("children"), String(kids)]);
|
|
14413
|
-
}
|
|
14414
|
-
return rows;
|
|
14415
|
-
}
|
|
14416
|
-
/************************************************************
|
|
14417
15137
|
* Render popover body from the info rows of a node.
|
|
15138
|
+
*
|
|
15139
|
+
* The rows come from gobj_tree_model.js, so a node of the
|
|
15140
|
+
* browser yuno and a node of a backend one are read out with
|
|
15141
|
+
* the same words in the same order.
|
|
14418
15142
|
************************************************************/
|
|
14419
15143
|
function render_popover_body(gobj, node_data) {
|
|
14420
15144
|
let $body = gobj.priv.$popover_body;
|
|
14421
15145
|
if (!$body) return;
|
|
14422
|
-
$body.innerHTML =
|
|
14423
|
-
<div style="display:grid; grid-template-columns:
|
|
15146
|
+
$body.innerHTML = node_info_rows(node_data, i18next.t).map(([label, value]) => `
|
|
15147
|
+
<div style="display:grid; grid-template-columns: 96px 1fr; column-gap:10px; padding: 2px 0;">
|
|
14424
15148
|
<span style="color:var(--bulma-text-weak, #6B7280); font-weight:500;">${(0, _yuneta_gobj_js.escapeHtml)(String(label))}</span>
|
|
14425
15149
|
<span style="color:var(--bulma-text-strong, #1A1A1A); word-break:break-all;">${(0, _yuneta_gobj_js.escapeHtml)(String(value))}</span>
|
|
14426
15150
|
</div>
|
|
@@ -14437,6 +15161,7 @@ function show_popover(gobj, node_data, client_x, client_y) {
|
|
|
14437
15161
|
let $title = priv.$popover_title;
|
|
14438
15162
|
let $container = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
|
|
14439
15163
|
if (!$popover || !$title || !$container) return;
|
|
15164
|
+
priv.popover_node = node_data;
|
|
14440
15165
|
$title.textContent = node_data.short_name || node_data.gclass + (node_data.name ? "^" + node_data.name : "");
|
|
14441
15166
|
$title.title = $title.textContent;
|
|
14442
15167
|
render_popover_body(gobj, node_data);
|
|
@@ -14467,6 +15192,7 @@ function hide_popover(gobj) {
|
|
|
14467
15192
|
if (priv.$popover) priv.$popover.style.display = "none";
|
|
14468
15193
|
if (priv.$popover_body) priv.$popover_body.innerHTML = "";
|
|
14469
15194
|
if (priv.$popover_title) priv.$popover_title.textContent = "";
|
|
15195
|
+
priv.popover_node = null;
|
|
14470
15196
|
}
|
|
14471
15197
|
/************************************************************
|
|
14472
15198
|
* Generic tree layout engine.
|
|
@@ -14993,12 +15719,11 @@ function ac_node_click$3(gobj, event, kw, src) {
|
|
|
14993
15719
|
*
|
|
14994
15720
|
************************************************************/
|
|
14995
15721
|
function ac_show$6(gobj, event, kw, src) {
|
|
14996
|
-
let
|
|
14997
|
-
let graph = priv.graph;
|
|
15722
|
+
let graph = gobj.priv.graph;
|
|
14998
15723
|
save_view_state(gobj);
|
|
14999
15724
|
refresh_tree(gobj);
|
|
15000
15725
|
if (graph) {
|
|
15001
|
-
let $canvas =
|
|
15726
|
+
let $canvas = canvas_mount(gobj);
|
|
15002
15727
|
if ($canvas) {
|
|
15003
15728
|
let cw = $canvas.clientWidth;
|
|
15004
15729
|
let ch = $canvas.clientHeight;
|
|
@@ -15017,10 +15742,9 @@ function ac_show$6(gobj, event, kw, src) {
|
|
|
15017
15742
|
* No fitView: preserve the user's current pan/zoom.
|
|
15018
15743
|
************************************************************/
|
|
15019
15744
|
function ac_resize$1(gobj, event, kw, src) {
|
|
15020
|
-
let
|
|
15021
|
-
let graph = priv.graph;
|
|
15745
|
+
let graph = gobj.priv.graph;
|
|
15022
15746
|
if (graph) {
|
|
15023
|
-
let $canvas =
|
|
15747
|
+
let $canvas = canvas_mount(gobj);
|
|
15024
15748
|
if ($canvas) {
|
|
15025
15749
|
let cw = $canvas.clientWidth;
|
|
15026
15750
|
let ch = $canvas.clientHeight;
|
|
@@ -15036,6 +15760,68 @@ function ac_hide$5(gobj, event, kw, src) {
|
|
|
15036
15760
|
hide_popover(gobj);
|
|
15037
15761
|
return 0;
|
|
15038
15762
|
}
|
|
15763
|
+
/************************************************************
|
|
15764
|
+
* Open the gclass of the node the popover is showing.
|
|
15765
|
+
*
|
|
15766
|
+
* One window at a time: opening a second gclass replaces the
|
|
15767
|
+
* first rather than stacking windows nobody closes.
|
|
15768
|
+
************************************************************/
|
|
15769
|
+
function ac_open_gclass(gobj, event, kw, src) {
|
|
15770
|
+
let priv = gobj.priv;
|
|
15771
|
+
let node_data = priv.popover_node;
|
|
15772
|
+
if (!node_data || !node_data.gclass) {
|
|
15773
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: EV_OPEN_GCLASS with no node`);
|
|
15774
|
+
return -1;
|
|
15775
|
+
}
|
|
15776
|
+
close_gclass_view(priv.gclass_view);
|
|
15777
|
+
priv.gclass_view = null;
|
|
15778
|
+
priv.gclass_view = open_gclass_view(gobj, node_data.gclass, {
|
|
15779
|
+
title_prefix: (0, _yuneta_gobj_js.gobj_yuno_name)() || "",
|
|
15780
|
+
on_close: () => {
|
|
15781
|
+
if ((0, _yuneta_gobj_js.gobj_is_destroying)(gobj)) return;
|
|
15782
|
+
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_GCLASS_CLOSED", {}, gobj);
|
|
15783
|
+
}
|
|
15784
|
+
});
|
|
15785
|
+
return 0;
|
|
15786
|
+
}
|
|
15787
|
+
/************************************************************
|
|
15788
|
+
* The reader dismissed the gclass window (its own ✕).
|
|
15789
|
+
*
|
|
15790
|
+
* C_YUI_WINDOW.close_window() calls on_close and THEN destroys
|
|
15791
|
+
* itself, so here we only drop our reference -- destroying it
|
|
15792
|
+
* again would destroy it twice.
|
|
15793
|
+
************************************************************/
|
|
15794
|
+
function ac_gclass_closed(gobj, event, kw, src) {
|
|
15795
|
+
gobj.priv.gclass_view = null;
|
|
15796
|
+
return 0;
|
|
15797
|
+
}
|
|
15798
|
+
/************************************************************
|
|
15799
|
+
* The gclass viewer asked for a subtree.
|
|
15800
|
+
*
|
|
15801
|
+
* It cannot: the gclass description is a COMPLETE document,
|
|
15802
|
+
* it carries no `__collapsed__` stub, so nothing in it is
|
|
15803
|
+
* fetchable. The event is declared because the viewer is
|
|
15804
|
+
* hosted as a child and subscribes its host to everything it
|
|
15805
|
+
* publishes -- and it is logged, because arriving here means
|
|
15806
|
+
* the document was not the one we built.
|
|
15807
|
+
************************************************************/
|
|
15808
|
+
function ac_gclass_expand_path(gobj, event, kw, src) {
|
|
15809
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: EV_EXPAND_PATH on a complete document: ${kw && kw.path}`);
|
|
15810
|
+
return -1;
|
|
15811
|
+
}
|
|
15812
|
+
/************************************************************
|
|
15813
|
+
* The app switched language.
|
|
15814
|
+
*
|
|
15815
|
+
* A rebuild, not a re-translation: the words live inside the
|
|
15816
|
+
* innerHTML of G6 nodes, where refresh_language() cannot go.
|
|
15817
|
+
************************************************************/
|
|
15818
|
+
function ac_language_changed$3(gobj, event, kw, src) {
|
|
15819
|
+
let $container = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
|
|
15820
|
+
if ($container) (0, _yuneta_gobj_js.refresh_language)($container, i18next.t);
|
|
15821
|
+
hide_popover(gobj);
|
|
15822
|
+
refresh_tree(gobj);
|
|
15823
|
+
return 0;
|
|
15824
|
+
}
|
|
15039
15825
|
/***************************
|
|
15040
15826
|
* FSM
|
|
15041
15827
|
***************************/
|
|
@@ -15069,7 +15855,11 @@ function create_gclass$9(gclass_name) {
|
|
|
15069
15855
|
["EV_CENTER_ANCHOR", 0],
|
|
15070
15856
|
["EV_RESIZE", 0],
|
|
15071
15857
|
["EV_SHOW", 0],
|
|
15072
|
-
["EV_HIDE", 0]
|
|
15858
|
+
["EV_HIDE", 0],
|
|
15859
|
+
["EV_OPEN_GCLASS", 0],
|
|
15860
|
+
["EV_GCLASS_CLOSED", 0],
|
|
15861
|
+
["EV_EXPAND_PATH", 0],
|
|
15862
|
+
["EV_LANGUAGE_CHANGED", 0]
|
|
15073
15863
|
], [["ST_IDLE", [
|
|
15074
15864
|
[
|
|
15075
15865
|
"EV_REFRESH",
|
|
@@ -15150,6 +15940,26 @@ function create_gclass$9(gclass_name) {
|
|
|
15150
15940
|
"EV_HIDE",
|
|
15151
15941
|
ac_hide$5,
|
|
15152
15942
|
null
|
|
15943
|
+
],
|
|
15944
|
+
[
|
|
15945
|
+
"EV_OPEN_GCLASS",
|
|
15946
|
+
ac_open_gclass,
|
|
15947
|
+
null
|
|
15948
|
+
],
|
|
15949
|
+
[
|
|
15950
|
+
"EV_GCLASS_CLOSED",
|
|
15951
|
+
ac_gclass_closed,
|
|
15952
|
+
null
|
|
15953
|
+
],
|
|
15954
|
+
[
|
|
15955
|
+
"EV_EXPAND_PATH",
|
|
15956
|
+
ac_gclass_expand_path,
|
|
15957
|
+
null
|
|
15958
|
+
],
|
|
15959
|
+
[
|
|
15960
|
+
"EV_LANGUAGE_CHANGED",
|
|
15961
|
+
ac_language_changed$3,
|
|
15962
|
+
null
|
|
15153
15963
|
]
|
|
15154
15964
|
]]], gmt$9, 0, attrs_table$9, PRIVATE_DATA$9, 0, 0, 0, 0);
|
|
15155
15965
|
if (!__gclass__$9) return -1;
|
|
@@ -54595,7 +55405,6 @@ function open_json_viewer(gobj) {
|
|
|
54595
55405
|
return;
|
|
54596
55406
|
}
|
|
54597
55407
|
priv.json_gobj = jv;
|
|
54598
|
-
(0, _yuneta_gobj_js.gobj_start)(jv);
|
|
54599
55408
|
let $box = (0, _yuneta_gobj_js.gobj_read_pointer_attr)(jv, "$container");
|
|
54600
55409
|
if (mobile) {
|
|
54601
55410
|
if (!shell) {
|
|
@@ -54614,6 +55423,7 @@ function open_json_viewer(gobj) {
|
|
|
54614
55423
|
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_JSON_CLOSED", {}, gobj);
|
|
54615
55424
|
}
|
|
54616
55425
|
});
|
|
55426
|
+
(0, _yuneta_gobj_js.gobj_start)(jv);
|
|
54617
55427
|
} else {
|
|
54618
55428
|
let $win_parent = shell && yui_shell_popup_layer(shell) || typeof document !== "undefined" && document.getElementById("top-layer") || null;
|
|
54619
55429
|
priv.json_win = (0, _yuneta_gobj_js.gobj_create_service)(`treedb-jsonwin-${(0, _yuneta_gobj_js.clean_name)((0, _yuneta_gobj_js.gobj_name)(gobj))}`, "C_YUI_WINDOW", {
|
|
@@ -54644,6 +55454,7 @@ function open_json_viewer(gobj) {
|
|
|
54644
55454
|
return;
|
|
54645
55455
|
}
|
|
54646
55456
|
(0, _yuneta_gobj_js.gobj_start)(priv.json_win);
|
|
55457
|
+
(0, _yuneta_gobj_js.gobj_start)(jv);
|
|
54647
55458
|
}
|
|
54648
55459
|
request_print_tranger(gobj, "");
|
|
54649
55460
|
}
|
|
@@ -54671,7 +55482,7 @@ function close_json_viewer(gobj) {
|
|
|
54671
55482
|
(0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: already gone: ${e}`);
|
|
54672
55483
|
}
|
|
54673
55484
|
if (jv && (0, _yuneta_gobj_js.is_gobj)(jv)) try {
|
|
54674
|
-
(0, _yuneta_gobj_js.gobj_stop)(jv);
|
|
55485
|
+
if ((0, _yuneta_gobj_js.gobj_is_running)(jv)) (0, _yuneta_gobj_js.gobj_stop)(jv);
|
|
54675
55486
|
(0, _yuneta_gobj_js.gobj_destroy)(jv);
|
|
54676
55487
|
} catch (e) {
|
|
54677
55488
|
(0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: already gone: ${e}`);
|