@yuneta/gobj-ui 7.23.28 → 7.23.29
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/gobj-ui.cjs.js +330 -25
- package/dist/gobj-ui.es.js +330 -25
- package/package.json +1 -1
- package/src/c_g6_nodes_tree.js +40 -10
- package/src/c_yui_gobj_tree_js.js +197 -2
- package/src/c_yui_json_graph.js +245 -4
- package/src/lib_graph.css +38 -2
- package/src/yui_graph_camera.js +60 -0
package/dist/gobj-ui.es.js
CHANGED
|
@@ -9706,6 +9706,42 @@ function yui_graph_update_anchor($container, state) {
|
|
|
9706
9706
|
* nothing to centre right now".
|
|
9707
9707
|
************************************************************/
|
|
9708
9708
|
var __centring__ = /* @__PURE__ */ new WeakMap();
|
|
9709
|
+
/************************************************************
|
|
9710
|
+
* Put `node_id` at a GIVEN point of the viewport.
|
|
9711
|
+
*
|
|
9712
|
+
* What "the graph does not jump when I fold something" is
|
|
9713
|
+
* made of: read where the card is, rebuild the layout, put
|
|
9714
|
+
* that card back where it was. Everything that did not move
|
|
9715
|
+
* in the layout stays put with it.
|
|
9716
|
+
************************************************************/
|
|
9717
|
+
async function yui_graph_place_at(graph, node_id, viewport_xy) {
|
|
9718
|
+
if (!graph || !node_id || !viewport_xy) return false;
|
|
9719
|
+
try {
|
|
9720
|
+
if (typeof graph.getElementPosition !== "function" || typeof graph.getCanvasCenter !== "function" || typeof graph.translateTo !== "function") return false;
|
|
9721
|
+
let z = graph.getZoom() || 1;
|
|
9722
|
+
let c = graph.getCanvasCenter();
|
|
9723
|
+
let n = graph.getElementPosition(node_id);
|
|
9724
|
+
await graph.translateTo([(c[0] - n[0]) * z + (viewport_xy[0] - c[0]), (c[1] - n[1]) * z + (viewport_xy[1] - c[1])]);
|
|
9725
|
+
return true;
|
|
9726
|
+
} catch (e) {
|
|
9727
|
+
return false;
|
|
9728
|
+
}
|
|
9729
|
+
}
|
|
9730
|
+
/************************************************************
|
|
9731
|
+
* Where `node_id` is right now, in viewport pixels.
|
|
9732
|
+
*
|
|
9733
|
+
* The pair of the call above: read it before a rebuild, hand
|
|
9734
|
+
* it back after, and the node has not moved on screen even
|
|
9735
|
+
* though the layout under it changed.
|
|
9736
|
+
************************************************************/
|
|
9737
|
+
function yui_graph_viewport_of(graph, node_id) {
|
|
9738
|
+
if (!graph || !node_id) return null;
|
|
9739
|
+
try {
|
|
9740
|
+
return graph.getViewportByCanvas(graph.getElementPosition(node_id));
|
|
9741
|
+
} catch (e) {
|
|
9742
|
+
return null;
|
|
9743
|
+
}
|
|
9744
|
+
}
|
|
9709
9745
|
async function yui_graph_center_on(graph, node_id) {
|
|
9710
9746
|
if (!graph || !node_id) return false;
|
|
9711
9747
|
let st = __centring__.get(graph);
|
|
@@ -10576,6 +10612,7 @@ var PRIVATE_DATA$11 = {
|
|
|
10576
10612
|
_resize_raf: 0,
|
|
10577
10613
|
search: "",
|
|
10578
10614
|
collapsed: null,
|
|
10615
|
+
reserved: null,
|
|
10579
10616
|
match_count: 0,
|
|
10580
10617
|
find_timer: null,
|
|
10581
10618
|
fold_listener: null,
|
|
@@ -10587,7 +10624,8 @@ var PRIVATE_DATA$11 = {
|
|
|
10587
10624
|
anchor_path: "",
|
|
10588
10625
|
anchor_state: "off",
|
|
10589
10626
|
last_zoom: 1,
|
|
10590
|
-
center_posted: false
|
|
10627
|
+
center_posted: false,
|
|
10628
|
+
pending_keep: null
|
|
10591
10629
|
};
|
|
10592
10630
|
var __gclass__$11 = null;
|
|
10593
10631
|
var __layout_registered__$1 = false;
|
|
@@ -10697,6 +10735,7 @@ function type_color(type, dark) {
|
|
|
10697
10735
|
function mt_create$11(gobj) {
|
|
10698
10736
|
let priv = gobj.priv;
|
|
10699
10737
|
priv.collapsed = /* @__PURE__ */ new Set();
|
|
10738
|
+
priv.reserved = /* @__PURE__ */ new Map();
|
|
10700
10739
|
priv.search = "";
|
|
10701
10740
|
priv.canvas_id = "json-canvas-" + clean_name(gobj_name(gobj));
|
|
10702
10741
|
gobj_write_str_attr(gobj, "canvas_id", priv.canvas_id);
|
|
@@ -10796,7 +10835,11 @@ function build_ui$10(gobj) {
|
|
|
10796
10835
|
evt.stopPropagation();
|
|
10797
10836
|
evt.preventDefault();
|
|
10798
10837
|
if (evt.type !== "click") return;
|
|
10799
|
-
|
|
10838
|
+
let $card = $handle.closest ? $handle.closest(".JSON_CARD") : null;
|
|
10839
|
+
gobj_send_event(gobj, "EV_TOGGLE_FOLD", {
|
|
10840
|
+
path: $handle.getAttribute("data-fold-path"),
|
|
10841
|
+
keep: $card ? $card.getAttribute("data-json-path") : ""
|
|
10842
|
+
}, gobj);
|
|
10800
10843
|
};
|
|
10801
10844
|
for (let type of FOLD_SWALLOWED_EVENTS) $mount.addEventListener(type, priv.fold_listener, true);
|
|
10802
10845
|
} else log_error(`${gobj_short_name(gobj)}: no canvas mount, fold handles are dead`);
|
|
@@ -11077,6 +11120,8 @@ var BEHAVIORS_READING$1 = [
|
|
|
11077
11120
|
var BEHAVIORS_PICKING$1 = ["drag-canvas", ZOOM_CANVAS$1];
|
|
11078
11121
|
var CARD_HEADER_H$1 = 24;
|
|
11079
11122
|
var CARD_ROW_H$1 = 22;
|
|
11123
|
+
var H_GAP = 60;
|
|
11124
|
+
var V_GAP = 50;
|
|
11080
11125
|
function fold_toggle_html(path, foldable, folded, branches, colors) {
|
|
11081
11126
|
if (!foldable) return FOLD_SPACER;
|
|
11082
11127
|
let label = folded ? "+" + branches : "−";
|
|
@@ -11198,7 +11243,10 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id, parent_port)
|
|
|
11198
11243
|
lines.push(build_cell_html(key, value, type, dark, matched, fold));
|
|
11199
11244
|
}
|
|
11200
11245
|
if (parent_id && is_pure_collection(kw)) {
|
|
11201
|
-
if (priv.collapsed.has(path))
|
|
11246
|
+
if (priv.collapsed.has(path)) {
|
|
11247
|
+
push_fold_phantom(gobj, path, parent_id, parent_port, nodes, edges);
|
|
11248
|
+
return parent_id;
|
|
11249
|
+
}
|
|
11202
11250
|
for (let pending of pending_complex) build_json_nodes(gobj, add_segment(path, pending.key), pending.value, nodes, edges, parent_id, parent_port);
|
|
11203
11251
|
return parent_id;
|
|
11204
11252
|
}
|
|
@@ -11284,7 +11332,10 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id, parent_port)
|
|
|
11284
11332
|
if (parent_port) edge.style.sourcePort = parent_port;
|
|
11285
11333
|
edges.push(edge);
|
|
11286
11334
|
}
|
|
11287
|
-
if (folded)
|
|
11335
|
+
if (folded) {
|
|
11336
|
+
push_fold_phantom(gobj, path, group_id, "", nodes, edges);
|
|
11337
|
+
return group_id;
|
|
11338
|
+
}
|
|
11288
11339
|
for (let pending of pending_complex) build_json_nodes(gobj, add_segment(path, pending.key), pending.value, nodes, edges, group_id, pending.port);
|
|
11289
11340
|
return group_id;
|
|
11290
11341
|
}
|
|
@@ -11315,8 +11366,16 @@ function load_json(gobj) {
|
|
|
11315
11366
|
});
|
|
11316
11367
|
graph.render().then(() => {
|
|
11317
11368
|
reanchor$1(gobj);
|
|
11318
|
-
paint_anchor_mark(gobj);
|
|
11369
|
+
paint_anchor_mark$1(gobj);
|
|
11319
11370
|
if (preserve_view) {
|
|
11371
|
+
let keep = priv.pending_keep;
|
|
11372
|
+
priv.pending_keep = null;
|
|
11373
|
+
if (keep) {
|
|
11374
|
+
for (let n of nodes) if (n.data && n.data.path === keep.path) {
|
|
11375
|
+
yui_graph_place_at(graph, n.id, [keep.x, keep.y]);
|
|
11376
|
+
break;
|
|
11377
|
+
}
|
|
11378
|
+
}
|
|
11320
11379
|
yui_graph_update_zoom(gobj_read_attr(gobj, "$container"), priv.graph);
|
|
11321
11380
|
return;
|
|
11322
11381
|
}
|
|
@@ -11368,6 +11427,108 @@ function update_find_result(gobj) {
|
|
|
11368
11427
|
priv.$find_result.classList.remove("is-hidden");
|
|
11369
11428
|
}
|
|
11370
11429
|
/************************************************************
|
|
11430
|
+
* The invisible child a fold leaves behind.
|
|
11431
|
+
*
|
|
11432
|
+
* It is the whole of "nothing moves when I fold": the layout
|
|
11433
|
+
* is a plain tree that centres a parent over its children, so
|
|
11434
|
+
* the only way to keep the survivors still is to leave the
|
|
11435
|
+
* space where it was, in the order it was, as a CHILD. A width
|
|
11436
|
+
* reserved as a number would still have to be placed, and
|
|
11437
|
+
* appending it moves every sibling by half of it.
|
|
11438
|
+
*
|
|
11439
|
+
* A `rect` and not an `html` node: nothing is drawn, and a
|
|
11440
|
+
* DOM element per fold would be a card nobody can see but the
|
|
11441
|
+
* Inspector would show.
|
|
11442
|
+
************************************************************/
|
|
11443
|
+
function push_fold_phantom(gobj, path, parent_id, parent_port, nodes, edges) {
|
|
11444
|
+
let width = gobj.priv.reserved.get(path) || 0;
|
|
11445
|
+
if (!(width > 0) || !parent_id) return;
|
|
11446
|
+
let id = gen_node_id$1(gobj);
|
|
11447
|
+
nodes.push({
|
|
11448
|
+
id,
|
|
11449
|
+
type: "rect",
|
|
11450
|
+
data: {
|
|
11451
|
+
path,
|
|
11452
|
+
phantom: true
|
|
11453
|
+
},
|
|
11454
|
+
style: {
|
|
11455
|
+
size: [width, 1],
|
|
11456
|
+
fill: "transparent",
|
|
11457
|
+
stroke: "transparent",
|
|
11458
|
+
opacity: 0,
|
|
11459
|
+
pointerEvents: "none"
|
|
11460
|
+
}
|
|
11461
|
+
});
|
|
11462
|
+
edges.push({
|
|
11463
|
+
source: parent_id,
|
|
11464
|
+
target: id,
|
|
11465
|
+
style: {
|
|
11466
|
+
opacity: 0,
|
|
11467
|
+
endArrow: false,
|
|
11468
|
+
sourcePort: parent_port || void 0
|
|
11469
|
+
}
|
|
11470
|
+
});
|
|
11471
|
+
}
|
|
11472
|
+
/************************************************************
|
|
11473
|
+
* The width the children a fold is about to hide are taking
|
|
11474
|
+
* RIGHT NOW, measured with the layout's own numbers.
|
|
11475
|
+
*
|
|
11476
|
+
* `card_path` is the card that will lose them; `under` limits
|
|
11477
|
+
* it to the ones hanging from one key of that card, which is
|
|
11478
|
+
* the case of a container that has no card of its own -- its
|
|
11479
|
+
* children hang from the parent, so its fold is a hole in the
|
|
11480
|
+
* PARENT.
|
|
11481
|
+
************************************************************/
|
|
11482
|
+
function group_width_of(gobj, card_path, under) {
|
|
11483
|
+
let priv = gobj.priv;
|
|
11484
|
+
if (!priv.graph) return 0;
|
|
11485
|
+
try {
|
|
11486
|
+
let by_id = {};
|
|
11487
|
+
let card_id = "";
|
|
11488
|
+
for (let node of priv.graph.getNodeData()) {
|
|
11489
|
+
if (!node || !node.data) continue;
|
|
11490
|
+
by_id[node.id] = node;
|
|
11491
|
+
if (node.data.path === card_path) card_id = node.id;
|
|
11492
|
+
}
|
|
11493
|
+
if (!card_id) return 0;
|
|
11494
|
+
let prefix = under ? under + "`" : "";
|
|
11495
|
+
let sum = 0;
|
|
11496
|
+
let n = 0;
|
|
11497
|
+
for (let edge of priv.graph.getEdgeData()) {
|
|
11498
|
+
if (!edge || edge.source !== card_id) continue;
|
|
11499
|
+
let kid = by_id[edge.target];
|
|
11500
|
+
if (!kid) continue;
|
|
11501
|
+
if (prefix && String(kid.data.path).indexOf(prefix) !== 0) continue;
|
|
11502
|
+
sum += kid.data.subtree_width || 0;
|
|
11503
|
+
n++;
|
|
11504
|
+
}
|
|
11505
|
+
return n ? sum + H_GAP * (n - 1) : 0;
|
|
11506
|
+
} catch (e) {
|
|
11507
|
+
return 0;
|
|
11508
|
+
}
|
|
11509
|
+
}
|
|
11510
|
+
/************************************************************
|
|
11511
|
+
* The screen spot of the card at `path`, to be given back
|
|
11512
|
+
* after the rebuild. Null when it has no card of its own --
|
|
11513
|
+
* a pure collection -- and then nothing anchors and the
|
|
11514
|
+
* camera simply stays where it was.
|
|
11515
|
+
************************************************************/
|
|
11516
|
+
function keep_of(gobj, path) {
|
|
11517
|
+
let priv = gobj.priv;
|
|
11518
|
+
if (empty_string(path) || !priv.graph) return null;
|
|
11519
|
+
try {
|
|
11520
|
+
for (let node of priv.graph.getNodeData()) if (node && node.data && node.data.path === path) {
|
|
11521
|
+
let vp = yui_graph_viewport_of(priv.graph, node.id);
|
|
11522
|
+
return vp ? {
|
|
11523
|
+
path,
|
|
11524
|
+
x: vp[0],
|
|
11525
|
+
y: vp[1]
|
|
11526
|
+
} : null;
|
|
11527
|
+
}
|
|
11528
|
+
} catch (e) {}
|
|
11529
|
+
return null;
|
|
11530
|
+
}
|
|
11531
|
+
/************************************************************
|
|
11371
11532
|
* Clear and reload.
|
|
11372
11533
|
* {preserve_view: true}
|
|
11373
11534
|
* keep the current zoom and translate (no fitView) —
|
|
@@ -11409,8 +11570,6 @@ var JsonTreeLayout = class extends BaseLayout {
|
|
|
11409
11570
|
h
|
|
11410
11571
|
};
|
|
11411
11572
|
}
|
|
11412
|
-
const H_GAP = 60;
|
|
11413
|
-
const V_GAP = 50;
|
|
11414
11573
|
let subtree_widths = {};
|
|
11415
11574
|
function calc_subtree_width(node_id) {
|
|
11416
11575
|
let kids = children_map[node_id] || [];
|
|
@@ -11427,6 +11586,7 @@ var JsonTreeLayout = class extends BaseLayout {
|
|
|
11427
11586
|
return subtree_widths[node_id];
|
|
11428
11587
|
}
|
|
11429
11588
|
for (let root of roots) calc_subtree_width(root.id);
|
|
11589
|
+
for (let node of nodes) if (node.data) node.data.subtree_width = subtree_widths[node.id];
|
|
11430
11590
|
let positions = {};
|
|
11431
11591
|
function position_node(node_id, x, y) {
|
|
11432
11592
|
positions[node_id] = {
|
|
@@ -11474,9 +11634,16 @@ var JsonTreeLayout = class extends BaseLayout {
|
|
|
11474
11634
|
/************************************************************
|
|
11475
11635
|
*
|
|
11476
11636
|
************************************************************/
|
|
11637
|
+
function priv_reset_folds(gobj) {
|
|
11638
|
+
gobj.priv.collapsed.clear();
|
|
11639
|
+
gobj.priv.reserved.clear();
|
|
11640
|
+
}
|
|
11477
11641
|
function ac_load_data$1(gobj, event, kw, src) {
|
|
11478
11642
|
if (kw.path !== void 0) gobj_write_str_attr(gobj, "path", kw.path);
|
|
11479
|
-
if (kw.data !== void 0)
|
|
11643
|
+
if (kw.data !== void 0) {
|
|
11644
|
+
gobj_write_attr(gobj, "json_data", kw.data);
|
|
11645
|
+
priv_reset_folds(gobj);
|
|
11646
|
+
}
|
|
11480
11647
|
refresh_json(gobj);
|
|
11481
11648
|
return 0;
|
|
11482
11649
|
}
|
|
@@ -11531,8 +11698,16 @@ function ac_toggle_fold(gobj, event, kw, src) {
|
|
|
11531
11698
|
log_error(`${gobj_short_name(gobj)}: EV_TOGGLE_FOLD with no path`);
|
|
11532
11699
|
return -1;
|
|
11533
11700
|
}
|
|
11534
|
-
|
|
11535
|
-
|
|
11701
|
+
let card = kw && kw.keep || path;
|
|
11702
|
+
if (priv.collapsed.has(path)) {
|
|
11703
|
+
priv.collapsed.delete(path);
|
|
11704
|
+
priv.reserved.delete(path);
|
|
11705
|
+
} else {
|
|
11706
|
+
let w = group_width_of(gobj, card, card === path ? "" : path);
|
|
11707
|
+
priv.collapsed.add(path);
|
|
11708
|
+
if (w > 0) priv.reserved.set(path, w);
|
|
11709
|
+
}
|
|
11710
|
+
priv.pending_keep = keep_of(gobj, kw && kw.keep || path);
|
|
11536
11711
|
refresh_json(gobj, { preserve_view: true });
|
|
11537
11712
|
update_find_result(gobj);
|
|
11538
11713
|
return 0;
|
|
@@ -11559,6 +11734,7 @@ function ac_expand_all$2(gobj, event, kw, src) {
|
|
|
11559
11734
|
let priv = gobj.priv;
|
|
11560
11735
|
if (priv.collapsed.size === 0) return 0;
|
|
11561
11736
|
priv.collapsed.clear();
|
|
11737
|
+
priv.reserved.clear();
|
|
11562
11738
|
refresh_json(gobj);
|
|
11563
11739
|
update_find_result(gobj);
|
|
11564
11740
|
return 0;
|
|
@@ -11575,6 +11751,7 @@ function ac_collapse_all$2(gobj, event, kw, src) {
|
|
|
11575
11751
|
if (empty_string(path)) path = "`";
|
|
11576
11752
|
collect_foldable_paths(json_data, path, paths, true);
|
|
11577
11753
|
priv.collapsed = new Set(paths);
|
|
11754
|
+
priv.reserved.clear();
|
|
11578
11755
|
refresh_json(gobj);
|
|
11579
11756
|
update_find_result(gobj);
|
|
11580
11757
|
return 0;
|
|
@@ -11664,7 +11841,7 @@ function set_picking_mode$1(gobj, picking) {
|
|
|
11664
11841
|
* each time and the mark would otherwise survive only until the
|
|
11665
11842
|
* next fold.
|
|
11666
11843
|
************************************************************/
|
|
11667
|
-
function paint_anchor_mark(gobj) {
|
|
11844
|
+
function paint_anchor_mark$1(gobj) {
|
|
11668
11845
|
let priv = gobj.priv;
|
|
11669
11846
|
let $container = gobj_read_attr(gobj, "$container");
|
|
11670
11847
|
if (!$container) return;
|
|
@@ -11679,7 +11856,7 @@ function paint_anchor_mark(gobj) {
|
|
|
11679
11856
|
function ac_center_anchor$2(gobj, event, kw, src) {
|
|
11680
11857
|
let priv = gobj.priv;
|
|
11681
11858
|
priv.center_posted = false;
|
|
11682
|
-
paint_anchor_mark(gobj);
|
|
11859
|
+
paint_anchor_mark$1(gobj);
|
|
11683
11860
|
if (priv.anchor_state === "on" && priv.anchor_id) yui_graph_center_on(priv.graph, priv.anchor_id);
|
|
11684
11861
|
return 0;
|
|
11685
11862
|
}
|
|
@@ -11700,7 +11877,7 @@ function ac_toggle_anchor$2(gobj, event, kw, src) {
|
|
|
11700
11877
|
priv.anchor_path = "";
|
|
11701
11878
|
}
|
|
11702
11879
|
yui_graph_update_anchor(gobj_read_attr(gobj, "$container"), priv.anchor_state);
|
|
11703
|
-
paint_anchor_mark(gobj);
|
|
11880
|
+
paint_anchor_mark$1(gobj);
|
|
11704
11881
|
set_picking_mode$1(gobj, priv.anchor_state === "arming");
|
|
11705
11882
|
return 0;
|
|
11706
11883
|
}
|
|
@@ -13245,6 +13422,71 @@ var BEHAVIORS_READING = [
|
|
|
13245
13422
|
"drag-element"
|
|
13246
13423
|
];
|
|
13247
13424
|
var BEHAVIORS_PICKING = ["drag-canvas", ZOOM_CANVAS];
|
|
13425
|
+
var VIEW_STORE_PREFIX = "yui_gobj_tree_view:";
|
|
13426
|
+
function view_store_key(gobj) {
|
|
13427
|
+
return VIEW_STORE_PREFIX + gobj_name(gobj);
|
|
13428
|
+
}
|
|
13429
|
+
function restore_view_shape(gobj) {
|
|
13430
|
+
let priv = gobj.priv;
|
|
13431
|
+
let state = load_view_state(gobj);
|
|
13432
|
+
if (!state) return;
|
|
13433
|
+
if (state.layout && LAYOUTS[state.layout]) {
|
|
13434
|
+
gobj_write_str_attr(gobj, "layout", state.layout);
|
|
13435
|
+
if (priv.$layout_select) priv.$layout_select.value = state.layout;
|
|
13436
|
+
}
|
|
13437
|
+
if (state.collapsed && typeof state.collapsed === "object") priv.collapse_state = Object.assign({}, state.collapsed);
|
|
13438
|
+
}
|
|
13439
|
+
function restore_view_state(gobj) {
|
|
13440
|
+
let priv = gobj.priv;
|
|
13441
|
+
let graph = priv.graph;
|
|
13442
|
+
let state = load_view_state(gobj);
|
|
13443
|
+
if (!graph || !state) return false;
|
|
13444
|
+
let done = false;
|
|
13445
|
+
priv.restoring = true;
|
|
13446
|
+
try {
|
|
13447
|
+
if (typeof state.zoom === "number" && state.zoom > 0) {
|
|
13448
|
+
graph.zoomTo(state.zoom);
|
|
13449
|
+
priv.last_zoom = state.zoom;
|
|
13450
|
+
done = true;
|
|
13451
|
+
}
|
|
13452
|
+
if (Array.isArray(state.position) && state.position.length >= 2) {
|
|
13453
|
+
graph.translateTo([state.position[0], state.position[1]]);
|
|
13454
|
+
done = true;
|
|
13455
|
+
}
|
|
13456
|
+
if (state.anchor) {
|
|
13457
|
+
priv.anchor_name = state.anchor;
|
|
13458
|
+
priv.anchor_state = "on";
|
|
13459
|
+
reanchor(gobj);
|
|
13460
|
+
yui_graph_update_anchor(gobj_read_attr(gobj, "$container"), priv.anchor_state);
|
|
13461
|
+
paint_anchor_mark(gobj);
|
|
13462
|
+
}
|
|
13463
|
+
} catch (e) {
|
|
13464
|
+
log_error(`${gobj_short_name(gobj)}: cannot restore the saved view: ${e}`);
|
|
13465
|
+
} finally {
|
|
13466
|
+
priv.restoring = false;
|
|
13467
|
+
}
|
|
13468
|
+
yui_graph_update_zoom(gobj_read_attr(gobj, "$container"), priv.graph);
|
|
13469
|
+
return done;
|
|
13470
|
+
}
|
|
13471
|
+
function save_view_state(gobj) {
|
|
13472
|
+
let priv = gobj.priv;
|
|
13473
|
+
let graph = priv.graph;
|
|
13474
|
+
if (!graph || priv.restoring) return;
|
|
13475
|
+
let state = {
|
|
13476
|
+
layout: gobj_read_str_attr(gobj, "layout"),
|
|
13477
|
+
collapsed: priv.collapse_state || {},
|
|
13478
|
+
anchor: priv.anchor_state === "on" ? priv.anchor_name : ""
|
|
13479
|
+
};
|
|
13480
|
+
try {
|
|
13481
|
+
state.zoom = graph.getZoom();
|
|
13482
|
+
state.position = graph.getPosition();
|
|
13483
|
+
} catch (e) {}
|
|
13484
|
+
kw_set_local_storage_value(view_store_key(gobj), state);
|
|
13485
|
+
}
|
|
13486
|
+
function load_view_state(gobj) {
|
|
13487
|
+
let state = kw_get_local_storage_value(view_store_key(gobj), null, false);
|
|
13488
|
+
return state && typeof state === "object" ? state : null;
|
|
13489
|
+
}
|
|
13248
13490
|
var PRIVATE_DATA$9 = {
|
|
13249
13491
|
canvas_id: "",
|
|
13250
13492
|
graph: null,
|
|
@@ -13262,6 +13504,8 @@ var PRIVATE_DATA$9 = {
|
|
|
13262
13504
|
anchor_id: "",
|
|
13263
13505
|
anchor_name: "",
|
|
13264
13506
|
anchor_state: "off",
|
|
13507
|
+
restoring: false,
|
|
13508
|
+
restored: false,
|
|
13265
13509
|
last_zoom: 1
|
|
13266
13510
|
};
|
|
13267
13511
|
var __gclass__$9 = null;
|
|
@@ -13468,6 +13712,7 @@ function mt_create$9(gobj) {
|
|
|
13468
13712
|
* Framework Method: Start
|
|
13469
13713
|
***************************************************************/
|
|
13470
13714
|
function mt_start$9(gobj) {
|
|
13715
|
+
restore_view_shape(gobj);
|
|
13471
13716
|
build_graph$2(gobj);
|
|
13472
13717
|
load_tree(gobj);
|
|
13473
13718
|
}
|
|
@@ -13605,8 +13850,12 @@ function build_popover(gobj, $container) {
|
|
|
13605
13850
|
$header.appendChild($title);
|
|
13606
13851
|
let $close = document.createElement("button");
|
|
13607
13852
|
$close.type = "button";
|
|
13853
|
+
$close.className = "GOBJ_TREE_POPOVER_CLOSE";
|
|
13608
13854
|
$close.textContent = "×";
|
|
13609
13855
|
$close.title = t("close");
|
|
13856
|
+
$close.setAttribute("data-i18n-title", "close");
|
|
13857
|
+
$close.setAttribute("aria-label", t("close"));
|
|
13858
|
+
$close.setAttribute("data-i18n-aria-label", "close");
|
|
13610
13859
|
$close.style.cssText = `
|
|
13611
13860
|
background: transparent;
|
|
13612
13861
|
border: none;
|
|
@@ -13740,6 +13989,7 @@ function build_graph$2(gobj) {
|
|
|
13740
13989
|
if (z === priv.last_zoom) return;
|
|
13741
13990
|
priv.last_zoom = z;
|
|
13742
13991
|
if (priv.anchor_state === "on" && priv.anchor_id) yui_graph_center_on(priv.graph, priv.anchor_id);
|
|
13992
|
+
save_view_state(gobj);
|
|
13743
13993
|
});
|
|
13744
13994
|
graph.on(NodeEvent.CLICK, (evt) => {
|
|
13745
13995
|
gobj_send_event(gobj, "EV_NODE_CLICK", { evt }, gobj);
|
|
@@ -13889,7 +14139,7 @@ function build_gobj_nodes(gobj, target_gobj, nodes, edges, parent_id, is_root, c
|
|
|
13889
14139
|
if (compact) {
|
|
13890
14140
|
let compact_label = escapeHtml(instance_name ? gclass_name + "^" + instance_name : gclass_name);
|
|
13891
14141
|
node_html = `
|
|
13892
|
-
<div style="
|
|
14142
|
+
<div class="GOBJ_CARD" data-gobj-name="${escapeHtml(full_name)}" style="
|
|
13893
14143
|
width: ${width}px;
|
|
13894
14144
|
height: ${height}px;
|
|
13895
14145
|
background: ${cs.bg};
|
|
@@ -13926,7 +14176,7 @@ function build_gobj_nodes(gobj, target_gobj, nodes, edges, parent_id, is_root, c
|
|
|
13926
14176
|
}
|
|
13927
14177
|
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("");
|
|
13928
14178
|
node_html = `
|
|
13929
|
-
<div style="
|
|
14179
|
+
<div class="GOBJ_CARD" data-gobj-name="${escapeHtml(full_name)}" style="
|
|
13930
14180
|
width: ${width}px;
|
|
13931
14181
|
height: ${height}px;
|
|
13932
14182
|
background: ${cs.bg};
|
|
@@ -14034,11 +14284,16 @@ function load_tree(gobj) {
|
|
|
14034
14284
|
});
|
|
14035
14285
|
graph.render().then(() => {
|
|
14036
14286
|
reanchor(gobj);
|
|
14287
|
+
paint_anchor_mark(gobj);
|
|
14037
14288
|
if (anchor) {
|
|
14038
14289
|
restore_view_anchored(gobj, anchor);
|
|
14039
14290
|
return;
|
|
14040
14291
|
}
|
|
14041
14292
|
if (preserve_view) return;
|
|
14293
|
+
if (!priv.restored) {
|
|
14294
|
+
priv.restored = true;
|
|
14295
|
+
if (restore_view_state(gobj)) return;
|
|
14296
|
+
}
|
|
14042
14297
|
Promise.resolve(graph.zoomTo(1)).then(() => {
|
|
14043
14298
|
if (!yui_graph_center_on(graph, priv.anchor_id)) yui_graph_center_on(graph, root_id);
|
|
14044
14299
|
priv.last_zoom = 1;
|
|
@@ -14469,6 +14724,7 @@ var GobjLanesHLayout = class extends BaseLayout {
|
|
|
14469
14724
|
*
|
|
14470
14725
|
************************************************************/
|
|
14471
14726
|
function ac_refresh$3(gobj, event, kw, src) {
|
|
14727
|
+
save_view_state(gobj);
|
|
14472
14728
|
refresh_tree(gobj);
|
|
14473
14729
|
return 0;
|
|
14474
14730
|
}
|
|
@@ -14496,6 +14752,8 @@ function ac_change_layout(gobj, event, kw, src) {
|
|
|
14496
14752
|
gobj_write_str_attr(gobj, "layout", new_key);
|
|
14497
14753
|
if (priv.$layout_select && priv.$layout_select.value !== new_key) priv.$layout_select.value = new_key;
|
|
14498
14754
|
apply_layout(gobj);
|
|
14755
|
+
save_view_state(gobj);
|
|
14756
|
+
save_view_state(gobj);
|
|
14499
14757
|
refresh_tree(gobj);
|
|
14500
14758
|
return 0;
|
|
14501
14759
|
}
|
|
@@ -14515,6 +14773,7 @@ function ac_toggle_collapse(gobj, event, kw, src) {
|
|
|
14515
14773
|
priv.collapse_state[node_data.full_name] = "expanded";
|
|
14516
14774
|
for (let child_info of node_data.direct_children || []) if (child_info.has_grandchildren) priv.collapse_state[child_info.full_name] = "collapsed";
|
|
14517
14775
|
} else priv.collapse_state[node_data.full_name] = "collapsed";
|
|
14776
|
+
save_view_state(gobj);
|
|
14518
14777
|
refresh_tree(gobj, { anchor });
|
|
14519
14778
|
return 0;
|
|
14520
14779
|
}
|
|
@@ -14594,10 +14853,31 @@ function reanchor(gobj) {
|
|
|
14594
14853
|
************************************************************/
|
|
14595
14854
|
function ac_center_anchor$1(gobj, event, kw, src) {
|
|
14596
14855
|
let priv = gobj.priv;
|
|
14856
|
+
paint_anchor_mark(gobj);
|
|
14857
|
+
save_view_state(gobj);
|
|
14597
14858
|
if (priv.anchor_state === "on" && priv.anchor_id) yui_graph_center_on(priv.graph, priv.anchor_id);
|
|
14598
14859
|
return 0;
|
|
14599
14860
|
}
|
|
14600
14861
|
/************************************************************
|
|
14862
|
+
* Mark the card the camera is holding.
|
|
14863
|
+
*
|
|
14864
|
+
* A class on the card's own element and not a G6 node state:
|
|
14865
|
+
* G6 paints no state style on an html node.
|
|
14866
|
+
*
|
|
14867
|
+
* Re-applied after every rebuild, because the cards are new
|
|
14868
|
+
* DOM each time and the mark would otherwise last until the
|
|
14869
|
+
* next expand.
|
|
14870
|
+
************************************************************/
|
|
14871
|
+
function paint_anchor_mark(gobj) {
|
|
14872
|
+
let priv = gobj.priv;
|
|
14873
|
+
let $container = gobj_read_attr(gobj, "$container");
|
|
14874
|
+
if (!$container) return;
|
|
14875
|
+
for (let $card of $container.querySelectorAll(".GOBJ_CARD_ANCHORED")) $card.classList.remove("GOBJ_CARD_ANCHORED");
|
|
14876
|
+
if (priv.anchor_state !== "on" || !priv.anchor_name) return;
|
|
14877
|
+
let $it = $container.querySelector(".GOBJ_CARD[data-gobj-name=\"" + CSS.escape(priv.anchor_name) + "\"]");
|
|
14878
|
+
if ($it) $it.classList.add("GOBJ_CARD_ANCHORED");
|
|
14879
|
+
}
|
|
14880
|
+
/************************************************************
|
|
14601
14881
|
* Reading, or picking the node to anchor.
|
|
14602
14882
|
************************************************************/
|
|
14603
14883
|
function set_picking_mode(gobj, picking) {
|
|
@@ -14625,6 +14905,8 @@ function ac_toggle_anchor$1(gobj, event, kw, src) {
|
|
|
14625
14905
|
}
|
|
14626
14906
|
yui_graph_update_anchor(gobj_read_attr(gobj, "$container"), priv.anchor_state);
|
|
14627
14907
|
set_picking_mode(gobj, priv.anchor_state === "arming");
|
|
14908
|
+
paint_anchor_mark(gobj);
|
|
14909
|
+
save_view_state(gobj);
|
|
14628
14910
|
return 0;
|
|
14629
14911
|
}
|
|
14630
14912
|
/************************************************************
|
|
@@ -14708,6 +14990,7 @@ function ac_node_click$3(gobj, event, kw, src) {
|
|
|
14708
14990
|
function ac_show$6(gobj, event, kw, src) {
|
|
14709
14991
|
let priv = gobj.priv;
|
|
14710
14992
|
let graph = priv.graph;
|
|
14993
|
+
save_view_state(gobj);
|
|
14711
14994
|
refresh_tree(gobj);
|
|
14712
14995
|
if (graph) {
|
|
14713
14996
|
let $canvas = document.getElementById(priv.canvas_id);
|
|
@@ -49026,7 +49309,7 @@ function configure_toolbar(gobj) {
|
|
|
49026
49309
|
{
|
|
49027
49310
|
id: "g6-icon-anchor",
|
|
49028
49311
|
value: "anchor",
|
|
49029
|
-
className: "EV_TOGGLE_ANCHOR" + (priv.anchor_state
|
|
49312
|
+
className: "EV_TOGGLE_ANCHOR" + (priv.anchor_state === "on" ? " pressed_state" : "") + (priv.anchor_state === "arming" ? " color_pending_state" : ""),
|
|
49030
49313
|
title: anchor_title(priv.anchor_state)
|
|
49031
49314
|
}
|
|
49032
49315
|
];
|
|
@@ -51935,15 +52218,15 @@ function refresh_minimap(gobj) {
|
|
|
51935
52218
|
* same three-way choice — it lived inline in the theme refresh and is
|
|
51936
52219
|
* shared now. Returns null for a node that carries no desc.
|
|
51937
52220
|
************************************************************/
|
|
51938
|
-
function node_innerHTML_of(nd, theme, highlight, selected) {
|
|
52221
|
+
function node_innerHTML_of(nd, theme, highlight, selected, anchored) {
|
|
51939
52222
|
if (!nd || !nd.data || !nd.data.desc) return null;
|
|
51940
52223
|
let desc = nd.data.desc;
|
|
51941
52224
|
let record = nd.data.record || {};
|
|
51942
52225
|
let label = node_label(desc, record);
|
|
51943
52226
|
switch (desc.node_treedb_type) {
|
|
51944
|
-
case "child": return build_chip_innerHTML(desc.color, theme, record.icon, label, record.id, highlight, selected);
|
|
51945
|
-
case "extended": return build_node_innerHTML(desc.color, theme, record.icon, label, desc.topic_name, true, record.id, highlight, selected);
|
|
51946
|
-
case "hierarchical": return build_node_innerHTML(desc.color, theme, record.icon, label, desc.topic_name, false, record.id, highlight, selected);
|
|
52227
|
+
case "child": return build_chip_innerHTML(desc.color, theme, record.icon, label, record.id, highlight, selected, anchored);
|
|
52228
|
+
case "extended": return build_node_innerHTML(desc.color, theme, record.icon, label, desc.topic_name, true, record.id, highlight, selected, anchored);
|
|
52229
|
+
case "hierarchical": return build_node_innerHTML(desc.color, theme, record.icon, label, desc.topic_name, false, record.id, highlight, selected, anchored);
|
|
51947
52230
|
}
|
|
51948
52231
|
return null;
|
|
51949
52232
|
}
|
|
@@ -51964,7 +52247,7 @@ function repaint_cards(gobj, ids) {
|
|
|
51964
52247
|
let selected = new Set(priv._selected_paint_ids || []);
|
|
51965
52248
|
let updates = [];
|
|
51966
52249
|
for (let id of ids) {
|
|
51967
|
-
let html = node_innerHTML_of(graph.getNodeData(id), priv.theme, focus.has(id), selected.has(id));
|
|
52250
|
+
let html = node_innerHTML_of(graph.getNodeData(id), priv.theme, focus.has(id), selected.has(id), priv.anchor_state === "on" && id === priv.anchor_id);
|
|
51968
52251
|
if (html !== null) updates.push({
|
|
51969
52252
|
id,
|
|
51970
52253
|
style: { innerHTML: html }
|
|
@@ -52038,6 +52321,23 @@ function refresh_default_edges_theme(gobj, theme) {
|
|
|
52038
52321
|
* it, which is also the order that reads correctly when only one
|
|
52039
52322
|
* of them is on.
|
|
52040
52323
|
************************************************************/
|
|
52324
|
+
/************************************************************
|
|
52325
|
+
* The mark of the card the CAMERA is holding.
|
|
52326
|
+
*
|
|
52327
|
+
* An outline and not another ring, and DASHED: the two rings
|
|
52328
|
+
* already mean things here -- amber is a find match or a
|
|
52329
|
+
* focused topic, blue is the selection -- and a third solid
|
|
52330
|
+
* ring would be a third thing to learn in the same channel.
|
|
52331
|
+
* A dash is a different channel, so it reads beside either of
|
|
52332
|
+
* them, and it says "provisional" the way a camera state is.
|
|
52333
|
+
*
|
|
52334
|
+
* The same dash the other two viewers draw: this is one
|
|
52335
|
+
* feature with one control, and it should not be three
|
|
52336
|
+
* drawings.
|
|
52337
|
+
************************************************************/
|
|
52338
|
+
function anchor_outline(anchored) {
|
|
52339
|
+
return anchored ? "outline: 3px dashed #fa8c16; outline-offset: 2px;" : "";
|
|
52340
|
+
}
|
|
52041
52341
|
function ring_shadow(highlight, selected, base_shadow) {
|
|
52042
52342
|
let rings = [];
|
|
52043
52343
|
if (highlight) rings.push(`0 0 0 4px ${HIGHLIGHT_HALO}`);
|
|
@@ -52052,7 +52352,7 @@ function ring_shadow(highlight, selected, base_shadow) {
|
|
|
52052
52352
|
* but lighter (1px border, no shadow, single line). The name is
|
|
52053
52353
|
* always legible (ellipsis + native title tooltip on overflow).
|
|
52054
52354
|
************************************************************/
|
|
52055
|
-
function build_chip_innerHTML(color, theme, icon, label, key, highlight, selected) {
|
|
52355
|
+
function build_chip_innerHTML(color, theme, icon, label, key, highlight, selected, anchored) {
|
|
52056
52356
|
let title = key || label;
|
|
52057
52357
|
let dark = theme === "dark";
|
|
52058
52358
|
let bg = dark ? `color-mix(in srgb, ${color} 30%, #2c3542)` : `color-mix(in srgb, ${color} 10%, ${dark ? "#1b2230" : "#ffffff"})`;
|
|
@@ -52065,13 +52365,14 @@ function build_chip_innerHTML(color, theme, icon, label, key, highlight, selecte
|
|
|
52065
52365
|
margin-right: 6px; flex: 0 0 auto;
|
|
52066
52366
|
"/>`;
|
|
52067
52367
|
return `
|
|
52068
|
-
<div title="${escapeHtml(title)}" style="
|
|
52368
|
+
<div class="TREEDB_CARD" title="${escapeHtml(title)}" style="
|
|
52069
52369
|
box-sizing: border-box;
|
|
52070
52370
|
width: 100%;
|
|
52071
52371
|
height: 100%;
|
|
52072
52372
|
background: ${bg};
|
|
52073
52373
|
border: ${highlight ? "3px" : "1px"} solid ${border};
|
|
52074
52374
|
${ring_shadow(highlight, selected, "")}
|
|
52375
|
+
${anchor_outline(anchored)}
|
|
52075
52376
|
border-radius: 8px;
|
|
52076
52377
|
color: ${text_color};
|
|
52077
52378
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
@@ -52097,7 +52398,7 @@ function build_chip_innerHTML(color, theme, icon, label, key, highlight, selecte
|
|
|
52097
52398
|
* colour is kept (per-topic differentiation) but softened via
|
|
52098
52399
|
* color-mix instead of a harsh saturated fill. Theme-aware.
|
|
52099
52400
|
************************************************************/
|
|
52100
|
-
function build_node_innerHTML(color, theme, icon, label, topic_name, structural, key, highlight, selected) {
|
|
52401
|
+
function build_node_innerHTML(color, theme, icon, label, topic_name, structural, key, highlight, selected, anchored) {
|
|
52101
52402
|
let title = key || label;
|
|
52102
52403
|
let dark = theme === "dark";
|
|
52103
52404
|
let surface = dark ? "#1b2230" : "#ffffff";
|
|
@@ -52132,7 +52433,7 @@ function build_node_innerHTML(color, theme, icon, label, topic_name, structural,
|
|
|
52132
52433
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
52133
52434
|
">${escapeHtml(topic_name)}</div>`;
|
|
52134
52435
|
return `
|
|
52135
|
-
<div title="${escapeHtml(title)}" style="
|
|
52436
|
+
<div class="TREEDB_CARD" title="${escapeHtml(title)}" style="
|
|
52136
52437
|
box-sizing: border-box;
|
|
52137
52438
|
width: 100%;
|
|
52138
52439
|
height: 100%;
|
|
@@ -52140,6 +52441,7 @@ function build_node_innerHTML(color, theme, icon, label, topic_name, structural,
|
|
|
52140
52441
|
border: ${highlight ? "3px" : "1.5px"} ${border_style} ${border};
|
|
52141
52442
|
border-radius: 10px;
|
|
52142
52443
|
${ring_shadow(highlight, selected, shadow)}
|
|
52444
|
+
${anchor_outline(anchored)}
|
|
52143
52445
|
color: ${title_color};
|
|
52144
52446
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
52145
52447
|
display: flex;
|
|
@@ -53123,12 +53425,14 @@ function after_camera(gobj, moved) {
|
|
|
53123
53425
|
************************************************************/
|
|
53124
53426
|
function ac_toggle_anchor(gobj, event, kw, src) {
|
|
53125
53427
|
let priv = gobj.priv;
|
|
53428
|
+
let was = priv.anchor_id;
|
|
53126
53429
|
if (priv.anchor_state === "off") priv.anchor_state = "arming";
|
|
53127
53430
|
else {
|
|
53128
53431
|
priv.anchor_state = "off";
|
|
53129
53432
|
priv.anchor_id = "";
|
|
53130
53433
|
}
|
|
53131
53434
|
update_toolbar(gobj);
|
|
53435
|
+
if (was) repaint_cards(gobj, /* @__PURE__ */ new Set([was]));
|
|
53132
53436
|
return 0;
|
|
53133
53437
|
}
|
|
53134
53438
|
/************************************************************
|
|
@@ -53306,6 +53610,7 @@ function ac_node_click$2(gobj, event, kw, src) {
|
|
|
53306
53610
|
priv.anchor_id = node_id;
|
|
53307
53611
|
priv.anchor_state = "on";
|
|
53308
53612
|
update_toolbar(gobj);
|
|
53613
|
+
repaint_cards(gobj, /* @__PURE__ */ new Set([node_id]));
|
|
53309
53614
|
gobj_post_event(gobj, "EV_CENTER_ANCHOR", {}, gobj);
|
|
53310
53615
|
return 0;
|
|
53311
53616
|
}
|