@yuneta/gobj-ui 7.23.74 → 7.23.76
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 +66 -12
- package/dist/gobj-ui.cjs.js +493 -136
- package/dist/gobj-ui.es.js +493 -136
- package/package.json +1 -1
- package/src/c_g6_nodes_tree.js +433 -94
- package/src/c_yui_treedb_graph.js +104 -2
- package/src/treedb_layout.js +40 -56
- package/src/treedb_layout.test.js +45 -24
- package/src/yui_icons.css +6 -0
package/dist/gobj-ui.es.js
CHANGED
|
@@ -27365,10 +27365,10 @@ function fold_reveal(model, state, node_key) {
|
|
|
27365
27365
|
/***********************************************************************
|
|
27366
27366
|
* treedb_layout.js
|
|
27367
27367
|
*
|
|
27368
|
-
*
|
|
27368
|
+
* Two layouts made for a treedb, and nothing else.
|
|
27369
27369
|
*
|
|
27370
27370
|
* What a treedb graph IS, once it is folded (treedb_fold_model.js):
|
|
27371
|
-
* a forest read
|
|
27371
|
+
* a forest read top to bottom. A main topic is a tree (places:
|
|
27372
27372
|
* country, region, site, hall), the other topics hang from its
|
|
27373
27373
|
* nodes through hooks (devices, users, controllers), a record may
|
|
27374
27374
|
* hang from two parents (a device from its place AND its
|
|
@@ -27389,9 +27389,8 @@ function fold_reveal(model, state, node_key) {
|
|
|
27389
27389
|
* - the force family scatters a tree, which is the pile with
|
|
27390
27390
|
* physics.
|
|
27391
27391
|
*
|
|
27392
|
-
* So: a tidy tree (`tree`)
|
|
27393
|
-
*
|
|
27394
|
-
* deterministically:
|
|
27392
|
+
* So: a tidy tree (`tree`) and a radial tree (`radial`), both fed
|
|
27393
|
+
* by the SAME spanning tree, chosen deterministically:
|
|
27395
27394
|
*
|
|
27396
27395
|
* - roots are the nodes with no incoming edge, in node order;
|
|
27397
27396
|
* - a node belongs to the FIRST parent that reaches it in a
|
|
@@ -27403,16 +27402,16 @@ function fold_reveal(model, state, node_key) {
|
|
|
27403
27402
|
* and then by node order (record order, the pages' order);
|
|
27404
27403
|
* - a node nothing reaches (a cycle) is a root too.
|
|
27405
27404
|
*
|
|
27406
|
-
* `tree`: the classic tidy tree,
|
|
27407
|
-
*
|
|
27408
|
-
* block of its children; siblings
|
|
27409
|
-
* them. O(n), and opening a hook moves NOTHING that is
|
|
27410
|
-
* or beside it -- the cards keep their order, the eye
|
|
27411
|
-
* place.
|
|
27412
|
-
*
|
|
27413
|
-
*
|
|
27414
|
-
*
|
|
27415
|
-
*
|
|
27405
|
+
* `tree`: the classic tidy tree, top to bottom. Each depth is a
|
|
27406
|
+
* row as tall as its tallest card; a node is centred over the
|
|
27407
|
+
* block of its children; siblings sit side by side with `nodesep`
|
|
27408
|
+
* between them. O(n), and opening a hook moves NOTHING that is
|
|
27409
|
+
* not below or beside it -- the cards keep their order, the eye
|
|
27410
|
+
* keeps its place. It reads DOWN because that is the direction a
|
|
27411
|
+
* tree with many children has room in: a hall with a hundred
|
|
27412
|
+
* devices is a wide row, not a tall column beside a card. (The
|
|
27413
|
+
* left-to-right reading is `direction: "LR"`, kept for a host
|
|
27414
|
+
* that wants it; `dagre` reads that way in the graph.)
|
|
27416
27415
|
*
|
|
27417
27416
|
* `radial`: the root in the middle and a ring per depth, each
|
|
27418
27417
|
* subtree owning a sector proportional to its leaves; the radius
|
|
@@ -27420,15 +27419,15 @@ function fold_reveal(model, state, node_key) {
|
|
|
27420
27419
|
* nothing overlaps by construction (see `layout_radial`).
|
|
27421
27420
|
*
|
|
27422
27421
|
* Pure: takes plain nodes and edges, returns positions. The G6
|
|
27423
|
-
* classes in c_g6_nodes_tree.js are
|
|
27422
|
+
* classes in c_g6_nodes_tree.js are two thin adapters over it.
|
|
27424
27423
|
*
|
|
27425
27424
|
* Copyright (c) 2026, ArtGins.
|
|
27426
27425
|
* All Rights Reserved.
|
|
27427
27426
|
***********************************************************************/
|
|
27428
27427
|
var DEFAULTS = {
|
|
27429
27428
|
nodesep: 18,
|
|
27430
|
-
ranksep:
|
|
27431
|
-
|
|
27429
|
+
ranksep: 90,
|
|
27430
|
+
direction: "TB"
|
|
27432
27431
|
};
|
|
27433
27432
|
/************************************************************
|
|
27434
27433
|
* The spanning tree of a graph, deterministic.
|
|
@@ -27515,13 +27514,33 @@ function walk_order(t) {
|
|
|
27515
27514
|
return order;
|
|
27516
27515
|
}
|
|
27517
27516
|
/************************************************************
|
|
27518
|
-
* The tidy tree
|
|
27517
|
+
* The tidy tree.
|
|
27519
27518
|
*
|
|
27520
27519
|
* Returns Map<id, {x, y}> with the CENTRE of each node, the way G6
|
|
27521
27520
|
* positions a node.
|
|
27521
|
+
*
|
|
27522
|
+
* The algorithm is written ONCE, reading left to right (depths are
|
|
27523
|
+
* columns, siblings stack down). Top to bottom -- the default -- is
|
|
27524
|
+
* the same tree with the axes swapped: every card is fed in
|
|
27525
|
+
* transposed (its height as its width), and every position comes
|
|
27526
|
+
* back transposed. That is the whole difference, and it is the
|
|
27527
|
+
* reason the code is not duplicated for a second direction.
|
|
27522
27528
|
************************************************************/
|
|
27523
27529
|
function layout_tree(nodes, edges, opts) {
|
|
27524
27530
|
let o = Object.assign({}, DEFAULTS, opts || {});
|
|
27531
|
+
if (o.direction === "LR") return tidy_tree_lr(nodes, edges, o);
|
|
27532
|
+
let lr = tidy_tree_lr(nodes.map((n) => Object.assign({}, n, {
|
|
27533
|
+
w: n.h,
|
|
27534
|
+
h: n.w
|
|
27535
|
+
})), edges, o);
|
|
27536
|
+
let pos = /* @__PURE__ */ new Map();
|
|
27537
|
+
for (let [id, p] of lr) pos.set(id, {
|
|
27538
|
+
x: p.y,
|
|
27539
|
+
y: p.x
|
|
27540
|
+
});
|
|
27541
|
+
return pos;
|
|
27542
|
+
}
|
|
27543
|
+
function tidy_tree_lr(nodes, edges, o) {
|
|
27525
27544
|
let t = spanning_tree(nodes, edges);
|
|
27526
27545
|
let pos = /* @__PURE__ */ new Map();
|
|
27527
27546
|
let col_w = [];
|
|
@@ -27687,37 +27706,6 @@ function layout_radial(nodes, edges, opts) {
|
|
|
27687
27706
|
}
|
|
27688
27707
|
return pos;
|
|
27689
27708
|
}
|
|
27690
|
-
/************************************************************
|
|
27691
|
-
* The outline: one node per row, indented by depth, in the
|
|
27692
|
-
* pre-order of the spanning tree. Rows are left-aligned on
|
|
27693
|
-
* their indent, so a column of chips reads as a list.
|
|
27694
|
-
************************************************************/
|
|
27695
|
-
function layout_outline(nodes, edges, opts) {
|
|
27696
|
-
let o = Object.assign({}, DEFAULTS, opts || {});
|
|
27697
|
-
let t = spanning_tree(nodes, edges);
|
|
27698
|
-
let pos = /* @__PURE__ */ new Map();
|
|
27699
|
-
let y = 0;
|
|
27700
|
-
let visit = (root_id) => {
|
|
27701
|
-
let stack = [root_id];
|
|
27702
|
-
while (stack.length) {
|
|
27703
|
-
let id = stack.pop();
|
|
27704
|
-
let n = t.by_id.get(id);
|
|
27705
|
-
let d = t.depth.get(id);
|
|
27706
|
-
pos.set(id, {
|
|
27707
|
-
x: d * o.indent + n.w / 2,
|
|
27708
|
-
y: y + n.h / 2
|
|
27709
|
-
});
|
|
27710
|
-
y += n.h + o.nodesep;
|
|
27711
|
-
let kids = t.children.get(id) || [];
|
|
27712
|
-
for (let i = kids.length - 1; i >= 0; i--) stack.push(kids[i]);
|
|
27713
|
-
}
|
|
27714
|
-
};
|
|
27715
|
-
for (let root of t.roots) {
|
|
27716
|
-
visit(root);
|
|
27717
|
-
y += o.nodesep;
|
|
27718
|
-
}
|
|
27719
|
-
return pos;
|
|
27720
|
-
}
|
|
27721
27709
|
//#endregion
|
|
27722
27710
|
//#region node_modules/@babel/runtime/helpers/esm/typeof.js
|
|
27723
27711
|
function _typeof(o) {
|
|
@@ -54534,6 +54522,14 @@ var GCLASS_NAME$4 = "C_G6_NODES_TREE";
|
|
|
54534
54522
|
var HIGHLIGHT_COLOR = "#f0a020";
|
|
54535
54523
|
var HIGHLIGHT_HALO = "rgba(240,160,32,0.35)";
|
|
54536
54524
|
var SELECT_RING = "rgba(59,130,246,0.95)";
|
|
54525
|
+
var PORT_R_ENTITY = 10;
|
|
54526
|
+
var PORT_R_CHILD = 5;
|
|
54527
|
+
var PORT_LINE_WIDTH = 2;
|
|
54528
|
+
var COMPACT_SIZE = {
|
|
54529
|
+
hierarchical: 32,
|
|
54530
|
+
extended: 28,
|
|
54531
|
+
child: 22
|
|
54532
|
+
};
|
|
54537
54533
|
/***************************************************************
|
|
54538
54534
|
* Internal layout and operation mode definitions
|
|
54539
54535
|
***************************************************************/
|
|
@@ -54541,13 +54537,9 @@ var _layouts = {
|
|
|
54541
54537
|
"manual": { type: "manual" },
|
|
54542
54538
|
"treedb-tree": {
|
|
54543
54539
|
type: "treedb-tree",
|
|
54540
|
+
direction: "TB",
|
|
54544
54541
|
nodesep: 18,
|
|
54545
|
-
ranksep:
|
|
54546
|
-
},
|
|
54547
|
-
"treedb-outline": {
|
|
54548
|
-
type: "treedb-outline",
|
|
54549
|
-
nodesep: 12,
|
|
54550
|
-
indent: 48
|
|
54542
|
+
ranksep: 90
|
|
54551
54543
|
},
|
|
54552
54544
|
"dagre": {
|
|
54553
54545
|
type: "dagre",
|
|
@@ -54618,6 +54610,8 @@ var attrs_table$4 = [
|
|
|
54618
54610
|
SDATA(data_type_t.DTP_LIST, "hidden_topics", 0, "[]", "Topics left out of the tree: no card, no pill counts them, no edge reaches them"),
|
|
54619
54611
|
SDATA(data_type_t.DTP_STRING, "main_topic", 0, "", "The topic the tree hangs from; empty = deduced (the one whose hooks reach the most others). Its parentless records are the roots; a parentless record of a topic linked to it is LOOSE and shown only on request"),
|
|
54620
54612
|
SDATA(data_type_t.DTP_LIST, "loose_topics", 0, "[]", "Topics whose loose records (no parent, in a topic the schema hangs from the main one) are shown as roots"),
|
|
54613
|
+
SDATA(data_type_t.DTP_STRING, "node_mode", 0, "expanded", "How a record is drawn: `expanded` = the card with its ports (the only shape a link can be edited on); `compact` = a rounded square of the topic's colour, no ports, no text -- the topology alone. One node can be toggled against it (EV_TOGGLE_NODE_MODE)"),
|
|
54614
|
+
SDATA(data_type_t.DTP_BOOLEAN, "node_labels", 0, true, "A compact node says its name under the square. Off, it is a coloured square and nothing else"),
|
|
54621
54615
|
SDATA(data_type_t.DTP_BOOLEAN, "confirm_delete_node", 0, true, "Ask confirmation before deleting a node"),
|
|
54622
54616
|
SDATA(data_type_t.DTP_BOOLEAN, "confirm_unlink_edge", 0, true, "Ask confirmation before unlinking an edge"),
|
|
54623
54617
|
SDATA(data_type_t.DTP_STRING, "wide", 0, "40px", "Height of header"),
|
|
@@ -54701,6 +54695,7 @@ var PRIVATE_DATA$4 = {
|
|
|
54701
54695
|
_fold_state: null,
|
|
54702
54696
|
_fold_listener: null,
|
|
54703
54697
|
_pill_sig: null,
|
|
54698
|
+
_open_nodes: null,
|
|
54704
54699
|
_fold_busy: false
|
|
54705
54700
|
};
|
|
54706
54701
|
var __gclass__$4 = null;
|
|
@@ -54846,7 +54841,6 @@ function register_layouts(gobj) {
|
|
|
54846
54841
|
_g6_extensions_registered = true;
|
|
54847
54842
|
register(ExtensionCategory.LAYOUT, "manual", ManualLayout);
|
|
54848
54843
|
register(ExtensionCategory.LAYOUT, "treedb-tree", TreedbTreeLayout);
|
|
54849
|
-
register(ExtensionCategory.LAYOUT, "treedb-outline", TreedbOutlineLayout);
|
|
54850
54844
|
register(ExtensionCategory.LAYOUT, "treedb-radial", TreedbRadialLayout);
|
|
54851
54845
|
register(ExtensionCategory.NODE, "light", LightNode);
|
|
54852
54846
|
}
|
|
@@ -54929,6 +54923,9 @@ function configure_events(gobj) {
|
|
|
54929
54923
|
graph.on(NodeEvent.CONTEXT_MENU, (evt) => {
|
|
54930
54924
|
gobj_send_event(gobj, "EV_NODE_CONTEXT_MENU", { evt }, gobj);
|
|
54931
54925
|
});
|
|
54926
|
+
graph.on(NodeEvent.DBLCLICK, (evt) => {
|
|
54927
|
+
gobj_send_event(gobj, "EV_NODE_DBLCLICK", { evt }, gobj);
|
|
54928
|
+
});
|
|
54932
54929
|
graph.on(EdgeEvent.CLICK, (evt) => {
|
|
54933
54930
|
if (consume_long_press_click(graph)) return;
|
|
54934
54931
|
gobj_send_event(gobj, "EV_EDGE_CLICK", { evt }, gobj);
|
|
@@ -55353,7 +55350,7 @@ function configure_behaviour(gobj) {
|
|
|
55353
55350
|
case "writing":
|
|
55354
55351
|
case "reading":
|
|
55355
55352
|
priv.edit_mode = false;
|
|
55356
|
-
behaviors = ["drag-canvas",
|
|
55353
|
+
behaviors = ["drag-canvas", ...camera_behaviors()];
|
|
55357
55354
|
break;
|
|
55358
55355
|
case "edition":
|
|
55359
55356
|
priv.edit_mode = true;
|
|
@@ -55367,7 +55364,7 @@ function configure_behaviour(gobj) {
|
|
|
55367
55364
|
return true;
|
|
55368
55365
|
}
|
|
55369
55366
|
},
|
|
55370
|
-
|
|
55367
|
+
...camera_behaviors(),
|
|
55371
55368
|
"drag-element",
|
|
55372
55369
|
{
|
|
55373
55370
|
type: BRUSH_SELECT_OWNED,
|
|
@@ -55385,7 +55382,7 @@ function configure_behaviour(gobj) {
|
|
|
55385
55382
|
break;
|
|
55386
55383
|
case "operation":
|
|
55387
55384
|
priv.edit_mode = false;
|
|
55388
|
-
behaviors = ["drag-canvas",
|
|
55385
|
+
behaviors = ["drag-canvas", ...camera_behaviors()];
|
|
55389
55386
|
break;
|
|
55390
55387
|
default: log_error(`operation mode unknown: ${operation_mode}`);
|
|
55391
55388
|
}
|
|
@@ -55457,13 +55454,33 @@ function build_ports(gobj, desc) {
|
|
|
55457
55454
|
* Which way the graph reads. `dagre` is the left-to-right
|
|
55458
55455
|
* layout; everything else keeps the top-down reading, `manual`
|
|
55459
55456
|
* included, because the saved arrangements were made with the
|
|
55460
|
-
* ports on the top and bottom edges.
|
|
55461
|
-
|
|
55462
|
-
|
|
55463
|
-
|
|
55464
|
-
|
|
55465
|
-
|
|
55466
|
-
|
|
55457
|
+
* ports on the top and bottom edges. The treedb tree reads down
|
|
55458
|
+
* too, since 7.23.75: read right it was dagre's twin.
|
|
55459
|
+
************************************************************/
|
|
55460
|
+
var LR_LAYOUTS = ["dagre"];
|
|
55461
|
+
/************************************************************
|
|
55462
|
+
* The camera behaviors every operation mode shares.
|
|
55463
|
+
*
|
|
55464
|
+
* The wheel SCROLLS, as it does on a map and on every page: a
|
|
55465
|
+
* graph of many nodes is taller than the screen, and a wheel
|
|
55466
|
+
* that zoomed instead made it a thing to be looked at from afar
|
|
55467
|
+
* or read through a keyhole -- never scrolled. Zoom is Ctrl +
|
|
55468
|
+
* wheel (which is also what a trackpad pinch arrives as), the
|
|
55469
|
+
* toolbar's +/-, and the two-finger pinch of g6_touch_gestures.
|
|
55470
|
+
* `enable` on the scroll keeps the two apart: a Ctrl wheel is
|
|
55471
|
+
* the zoom's, so the scroll stands aside for it.
|
|
55472
|
+
************************************************************/
|
|
55473
|
+
function camera_behaviors() {
|
|
55474
|
+
return [{
|
|
55475
|
+
type: "scroll-canvas",
|
|
55476
|
+
key: "scroll-canvas",
|
|
55477
|
+
enable: (event) => !(event && (event.ctrlKey || event.metaKey))
|
|
55478
|
+
}, {
|
|
55479
|
+
type: "zoom-canvas",
|
|
55480
|
+
key: "zoom-canvas",
|
|
55481
|
+
trigger: ["Control"]
|
|
55482
|
+
}];
|
|
55483
|
+
}
|
|
55467
55484
|
function layout_direction(gobj) {
|
|
55468
55485
|
return str_in_list(LR_LAYOUTS, gobj.priv.layout) ? "LR" : "TB";
|
|
55469
55486
|
}
|
|
@@ -55531,83 +55548,101 @@ function apply_layout_direction(gobj) {
|
|
|
55531
55548
|
* Create a topic node in the G6 graph
|
|
55532
55549
|
************************************************************/
|
|
55533
55550
|
function create_topic_node(gobj, desc, record) {
|
|
55534
|
-
|
|
55535
|
-
const graph = priv.graph;
|
|
55551
|
+
const graph = gobj.priv.graph;
|
|
55536
55552
|
let node_name = build_node_name(gobj, desc.topic_name, record.id);
|
|
55537
55553
|
let xy = get_default_ne_xy(gobj);
|
|
55538
55554
|
let geometry = get_node_graph_props(gobj, desc.topic_name, record.id, record);
|
|
55539
55555
|
let x = kw_get_int(gobj, geometry, "x", xy, kw_flag_t.KW_CREATE);
|
|
55540
55556
|
let y = kw_get_int(gobj, geometry, "y", xy, kw_flag_t.KW_CREATE);
|
|
55541
|
-
let
|
|
55542
|
-
let
|
|
55557
|
+
let shape = node_shape_of(gobj, node_name, desc, record, geometry, pills_html_of_key(gobj, fold_node_key(desc.topic_name, String(record.id))));
|
|
55558
|
+
let node_def = {
|
|
55559
|
+
id: node_name,
|
|
55560
|
+
type: shape.type,
|
|
55561
|
+
style: Object.assign({
|
|
55562
|
+
x,
|
|
55563
|
+
y
|
|
55564
|
+
}, shape.style),
|
|
55565
|
+
data: {
|
|
55566
|
+
topic_name: desc.topic_name,
|
|
55567
|
+
desc,
|
|
55568
|
+
record,
|
|
55569
|
+
graph_props: geometry,
|
|
55570
|
+
port_keys: build_ports(gobj, desc).map((p) => p.key)
|
|
55571
|
+
}
|
|
55572
|
+
};
|
|
55573
|
+
graph.addNodeData([node_def]);
|
|
55574
|
+
}
|
|
55575
|
+
/************************************************************
|
|
55576
|
+
* The shape of a record node: OPEN (the card, with its ports)
|
|
55577
|
+
* or CLOSED (a coloured square), by `node_mode` and the nodes
|
|
55578
|
+
* toggled against it.
|
|
55579
|
+
*
|
|
55580
|
+
* Both answer {type, style} WITHOUT x/y, which belong to the node
|
|
55581
|
+
* and not to its shape, and a node moves between the two on the
|
|
55582
|
+
* fly: G6 rebuilds the element when `type` changes, and the
|
|
55583
|
+
* style is MERGED, which is why each shape also writes the keys
|
|
55584
|
+
* the other one would leave behind (`labelText`, `ports`).
|
|
55585
|
+
************************************************************/
|
|
55586
|
+
function node_shape_of(gobj, node_id, desc, record, geometry, pills_html) {
|
|
55587
|
+
if (node_is_compact(gobj, node_id)) return compact_shape_of(gobj, desc, record, {});
|
|
55588
|
+
return card_shape_of(gobj, desc, record, geometry, pills_html);
|
|
55589
|
+
}
|
|
55590
|
+
function node_is_compact(gobj, node_id) {
|
|
55591
|
+
let priv = gobj.priv;
|
|
55592
|
+
if (!priv._open_nodes) priv._open_nodes = /* @__PURE__ */ new Set();
|
|
55593
|
+
let compact = gobj_read_str_attr(gobj, "node_mode") === "compact";
|
|
55594
|
+
return priv._open_nodes.has(node_id) ? !compact : compact;
|
|
55595
|
+
}
|
|
55596
|
+
/************************************************************
|
|
55597
|
+
* The CARD: an html node, the tier's size, the ports, the
|
|
55598
|
+
* saved geometry on top. The flags (focus, selection, anchor)
|
|
55599
|
+
* are not painted here: repaint_cards() reads them where they
|
|
55600
|
+
* live and rebuilds the html.
|
|
55601
|
+
************************************************************/
|
|
55602
|
+
function card_shape_of(gobj, desc, record, geometry, pills_html) {
|
|
55603
|
+
let priv = gobj.priv;
|
|
55543
55604
|
let node_treedb_type = desc.node_treedb_type;
|
|
55605
|
+
let label = node_label(desc, record);
|
|
55606
|
+
let ports = build_ports(gobj, desc);
|
|
55544
55607
|
let style = {
|
|
55545
|
-
x,
|
|
55546
|
-
y,
|
|
55547
55608
|
fill: desc.color,
|
|
55548
55609
|
stroke: getStrokeColor(desc.color),
|
|
55549
|
-
lineWidth: 1
|
|
55610
|
+
lineWidth: 1,
|
|
55611
|
+
lineDash: [],
|
|
55612
|
+
halo: false,
|
|
55613
|
+
labelText: ""
|
|
55550
55614
|
};
|
|
55551
|
-
let pills_html = pills_html_of_key(gobj, fold_node_key(desc.topic_name, String(record.id)));
|
|
55552
55615
|
let size = card_size_for(node_treedb_type, !!pills_html);
|
|
55553
|
-
|
|
55554
|
-
|
|
55555
|
-
|
|
55556
|
-
|
|
55557
|
-
|
|
55558
|
-
|
|
55559
|
-
} else if (node_treedb_type === "extended") {
|
|
55560
|
-
node_graph_type = "html";
|
|
55561
|
-
style.size = size;
|
|
55562
|
-
style.dx = -size[0] / 2;
|
|
55563
|
-
style.dy = -size[1] / 2;
|
|
55564
|
-
style.innerHTML = build_node_innerHTML(desc.color, priv.theme, record.icon, node_label(desc, record), desc.topic_name, true, record.id, false, false, false, pills_html);
|
|
55565
|
-
} else {
|
|
55566
|
-
node_graph_type = "html";
|
|
55567
|
-
style.size = size;
|
|
55568
|
-
style.dx = -size[0] / 2;
|
|
55569
|
-
style.dy = -size[1] / 2;
|
|
55570
|
-
style.innerHTML = build_node_innerHTML(desc.color, priv.theme, record.icon, node_label(desc, record), desc.topic_name, false, record.id, false, false, false, pills_html);
|
|
55571
|
-
}
|
|
55616
|
+
style.size = size;
|
|
55617
|
+
style.dx = -size[0] / 2;
|
|
55618
|
+
style.dy = -size[1] / 2;
|
|
55619
|
+
if (node_treedb_type === "child") style.innerHTML = build_chip_innerHTML(desc.color, priv.theme, record.icon, label, record.id);
|
|
55620
|
+
else if (node_treedb_type === "extended") style.innerHTML = build_node_innerHTML(desc.color, priv.theme, record.icon, label, desc.topic_name, true, record.id, false, false, false, pills_html);
|
|
55621
|
+
else style.innerHTML = build_node_innerHTML(desc.color, priv.theme, record.icon, label, desc.topic_name, false, record.id, false, false, false, pills_html);
|
|
55572
55622
|
let topic_props = priv._graph_properties[desc.topic_name];
|
|
55573
55623
|
let topic_defaults = is_object(topic_props) && is_object(topic_props.defaults) ? topic_props.defaults : null;
|
|
55574
55624
|
if (topic_defaults) {
|
|
55575
55625
|
let def_size = topic_defaults.size;
|
|
55576
55626
|
if (!geometry.size && Array.isArray(def_size) && def_size.length > 0) {
|
|
55577
55627
|
style.size = [...def_size];
|
|
55578
|
-
|
|
55579
|
-
|
|
55580
|
-
style.dy = -(def_size.length > 1 ? def_size[1] : def_size[0]) / 2;
|
|
55581
|
-
}
|
|
55628
|
+
style.dx = -def_size[0] / 2;
|
|
55629
|
+
style.dy = -(def_size.length > 1 ? def_size[1] : def_size[0]) / 2;
|
|
55582
55630
|
}
|
|
55583
55631
|
if (!geometry.portR && topic_defaults.portR > 0) style.portR = topic_defaults.portR;
|
|
55584
55632
|
}
|
|
55585
55633
|
let saved_size = geometry.size;
|
|
55586
55634
|
if (Array.isArray(saved_size) && saved_size.length > 0) {
|
|
55587
55635
|
style.size = saved_size;
|
|
55588
|
-
|
|
55589
|
-
|
|
55590
|
-
style.dy = -(saved_size.length > 1 ? saved_size[1] : saved_size[0]) / 2;
|
|
55591
|
-
}
|
|
55636
|
+
style.dx = -saved_size[0] / 2;
|
|
55637
|
+
style.dy = -(saved_size.length > 1 ? saved_size[1] : saved_size[0]) / 2;
|
|
55592
55638
|
}
|
|
55593
55639
|
if (geometry.portR > 0) style.portR = geometry.portR;
|
|
55594
|
-
let node_def = {
|
|
55595
|
-
id: node_name,
|
|
55596
|
-
type: node_graph_type,
|
|
55597
|
-
style,
|
|
55598
|
-
data: {
|
|
55599
|
-
topic_name: desc.topic_name,
|
|
55600
|
-
desc,
|
|
55601
|
-
record,
|
|
55602
|
-
graph_props: geometry
|
|
55603
|
-
}
|
|
55604
|
-
};
|
|
55605
55640
|
if (json_size(ports)) {
|
|
55606
55641
|
json_object_update_missing(style, {
|
|
55607
55642
|
port: true,
|
|
55608
55643
|
ports,
|
|
55609
|
-
portR: node_treedb_type === "child" ?
|
|
55610
|
-
portLineWidth:
|
|
55644
|
+
portR: node_treedb_type === "child" ? PORT_R_CHILD : PORT_R_ENTITY,
|
|
55645
|
+
portLineWidth: PORT_LINE_WIDTH
|
|
55611
55646
|
});
|
|
55612
55647
|
let port_sizes = geometry.port_sizes;
|
|
55613
55648
|
let default_port_sizes = topic_defaults ? topic_defaults.port_sizes : null;
|
|
@@ -55617,8 +55652,117 @@ function create_topic_node(gobj, desc, record) {
|
|
|
55617
55652
|
if (r == null && is_object(default_port_sizes)) r = default_port_sizes[key];
|
|
55618
55653
|
if (r != null) style.ports[i].r = r;
|
|
55619
55654
|
}
|
|
55655
|
+
} else {
|
|
55656
|
+
style.port = false;
|
|
55657
|
+
style.ports = [];
|
|
55658
|
+
}
|
|
55659
|
+
return {
|
|
55660
|
+
type: "html",
|
|
55661
|
+
style
|
|
55662
|
+
};
|
|
55663
|
+
}
|
|
55664
|
+
/************************************************************
|
|
55665
|
+
* The SQUARE: a G6 `rect` of the topic's colour, no ports, the
|
|
55666
|
+
* name as a label under it when `node_labels` says so. A native
|
|
55667
|
+
* shape and not html on purpose: G6's own stroke and halo paint
|
|
55668
|
+
* on it, so the focus, the selection and the anchor are three
|
|
55669
|
+
* keys of the style instead of a rebuilt innerHTML.
|
|
55670
|
+
*
|
|
55671
|
+
* flags {highlight, selected, anchored}
|
|
55672
|
+
************************************************************/
|
|
55673
|
+
function compact_shape_of(gobj, desc, record, flags) {
|
|
55674
|
+
let dark = gobj.priv.theme === "dark";
|
|
55675
|
+
let f = flags || {};
|
|
55676
|
+
let tier = desc.node_treedb_type;
|
|
55677
|
+
let side = COMPACT_SIZE[tier] || COMPACT_SIZE.hierarchical;
|
|
55678
|
+
let labels = gobj_read_bool_attr(gobj, "node_labels");
|
|
55679
|
+
let stroke = getStrokeColor(desc.color);
|
|
55680
|
+
let line_width = 1.5;
|
|
55681
|
+
if (f.selected) {
|
|
55682
|
+
stroke = SELECT_RING;
|
|
55683
|
+
line_width = 3;
|
|
55684
|
+
}
|
|
55685
|
+
if (f.highlight) {
|
|
55686
|
+
stroke = HIGHLIGHT_COLOR;
|
|
55687
|
+
line_width = 3;
|
|
55688
|
+
}
|
|
55689
|
+
let dash = [];
|
|
55690
|
+
if (tier === "extended") dash = [4, 3];
|
|
55691
|
+
if (f.anchored) {
|
|
55692
|
+
dash = [2, 2];
|
|
55693
|
+
line_width = Math.max(line_width, 2.5);
|
|
55694
|
+
}
|
|
55695
|
+
return {
|
|
55696
|
+
type: "rect",
|
|
55697
|
+
style: {
|
|
55698
|
+
size: [side, side],
|
|
55699
|
+
radius: Math.round(side / 5),
|
|
55700
|
+
fill: desc.color,
|
|
55701
|
+
stroke,
|
|
55702
|
+
lineWidth: line_width,
|
|
55703
|
+
lineDash: dash,
|
|
55704
|
+
halo: !!f.highlight,
|
|
55705
|
+
haloStroke: HIGHLIGHT_HALO,
|
|
55706
|
+
haloLineWidth: 8,
|
|
55707
|
+
port: false,
|
|
55708
|
+
ports: [],
|
|
55709
|
+
labelText: labels ? node_label(desc, record) : "",
|
|
55710
|
+
labelPlacement: "bottom",
|
|
55711
|
+
labelFontSize: 11,
|
|
55712
|
+
labelFill: dark ? "#e6e9ef" : "#2e333d",
|
|
55713
|
+
labelMaxWidth: 150,
|
|
55714
|
+
labelWordWrap: true,
|
|
55715
|
+
labelMaxLines: 1,
|
|
55716
|
+
labelTextOverflow: "ellipsis",
|
|
55717
|
+
labelBackground: true,
|
|
55718
|
+
labelBackgroundFill: dark ? "#1b2230" : "#ffffff",
|
|
55719
|
+
labelBackgroundOpacity: .85,
|
|
55720
|
+
labelBackgroundRadius: 3,
|
|
55721
|
+
labelPadding: [1, 3]
|
|
55722
|
+
}
|
|
55723
|
+
};
|
|
55724
|
+
}
|
|
55725
|
+
/************************************************************
|
|
55726
|
+
* Give these record nodes the shape their mode says, then
|
|
55727
|
+
* repaint them with the flags they carry. A `+N` chip is not a
|
|
55728
|
+
* record and keeps its own shape.
|
|
55729
|
+
************************************************************/
|
|
55730
|
+
function reshape_nodes(gobj, ids) {
|
|
55731
|
+
let graph = gobj.priv.graph;
|
|
55732
|
+
if (!graph) return;
|
|
55733
|
+
let updates = [];
|
|
55734
|
+
let touched = /* @__PURE__ */ new Set();
|
|
55735
|
+
for (let id of ids) {
|
|
55736
|
+
let nd;
|
|
55737
|
+
try {
|
|
55738
|
+
nd = graph.getNodeData(id);
|
|
55739
|
+
} catch (e) {
|
|
55740
|
+
continue;
|
|
55741
|
+
}
|
|
55742
|
+
if (!nd || !nd.data || !nd.data.desc || is_more_node(nd)) continue;
|
|
55743
|
+
let geometry = nd.data.graph_props || {};
|
|
55744
|
+
let shape = node_shape_of(gobj, id, nd.data.desc, nd.data.record || {}, geometry, pills_html_of(gobj, nd));
|
|
55745
|
+
updates.push({
|
|
55746
|
+
id,
|
|
55747
|
+
type: shape.type,
|
|
55748
|
+
style: shape.style
|
|
55749
|
+
});
|
|
55750
|
+
touched.add(id);
|
|
55751
|
+
}
|
|
55752
|
+
if (!updates.length) return;
|
|
55753
|
+
try {
|
|
55754
|
+
graph.updateNodeData(updates);
|
|
55755
|
+
} catch (e) {
|
|
55756
|
+
log_error(`${gobj_short_name(gobj)}: cannot reshape the nodes: ${e}`);
|
|
55757
|
+
return;
|
|
55620
55758
|
}
|
|
55621
|
-
|
|
55759
|
+
repaint_cards(gobj, touched);
|
|
55760
|
+
}
|
|
55761
|
+
function all_record_node_ids(gobj) {
|
|
55762
|
+
let graph = gobj.priv.graph;
|
|
55763
|
+
let ids = [];
|
|
55764
|
+
for (let nd of graph && graph.getNodeData() || []) if (nd && nd.data && nd.data.desc && !is_more_node(nd)) ids.push(nd.id);
|
|
55765
|
+
return ids;
|
|
55622
55766
|
}
|
|
55623
55767
|
/************************************************************
|
|
55624
55768
|
* Update topic node data
|
|
@@ -56465,7 +56609,7 @@ var ManualLayout = class extends BaseLayout {
|
|
|
56465
56609
|
}
|
|
56466
56610
|
};
|
|
56467
56611
|
/************************************************************
|
|
56468
|
-
* Custom G6 layouts: TreedbTreeLayout /
|
|
56612
|
+
* Custom G6 layouts: TreedbTreeLayout / TreedbRadialLayout.
|
|
56469
56613
|
*
|
|
56470
56614
|
* Thin adapters over treedb_layout.js: the nodes with their sizes,
|
|
56471
56615
|
* the edges with the RANK of the hook they leave by (the position
|
|
@@ -56483,7 +56627,8 @@ function treedb_layout_input(data) {
|
|
|
56483
56627
|
let w = is_array(size) ? size[0] : size;
|
|
56484
56628
|
let h = is_array(size) ? size.length > 1 ? size[1] : size[0] : size;
|
|
56485
56629
|
let ports = node.style && is_array(node.style.ports) ? node.style.ports : [];
|
|
56486
|
-
|
|
56630
|
+
let keys = node.data && is_array(node.data.port_keys) ? node.data.port_keys : ports.map((p) => p.key);
|
|
56631
|
+
ports_of.set(node.id, keys);
|
|
56487
56632
|
return {
|
|
56488
56633
|
id: node.id,
|
|
56489
56634
|
w,
|
|
@@ -56519,12 +56664,6 @@ var TreedbTreeLayout = class extends BaseLayout {
|
|
|
56519
56664
|
return treedb_layout_output(layout_tree(input.nodes, input.edges, options));
|
|
56520
56665
|
}
|
|
56521
56666
|
};
|
|
56522
|
-
var TreedbOutlineLayout = class extends BaseLayout {
|
|
56523
|
-
async execute(data, options) {
|
|
56524
|
-
let input = treedb_layout_input(data);
|
|
56525
|
-
return treedb_layout_output(layout_outline(input.nodes, input.edges, options));
|
|
56526
|
-
}
|
|
56527
|
-
};
|
|
56528
56667
|
var TreedbRadialLayout = class extends BaseLayout {
|
|
56529
56668
|
async execute(data, options) {
|
|
56530
56669
|
let input = treedb_layout_input(data);
|
|
@@ -57216,7 +57355,7 @@ function get_port_radius(gobj, node_id, port_key) {
|
|
|
57216
57355
|
if (ports[i].r != null) return ports[i].r;
|
|
57217
57356
|
break;
|
|
57218
57357
|
}
|
|
57219
|
-
return style.portR ||
|
|
57358
|
+
return style.portR || PORT_R_ENTITY;
|
|
57220
57359
|
}
|
|
57221
57360
|
/************************************************************
|
|
57222
57361
|
* How much wider than the port itself its hit area is,
|
|
@@ -57248,7 +57387,7 @@ function detect_port_click(gobj, node_id, canvasX, canvasY) {
|
|
|
57248
57387
|
const style = graph.getNodeData(node_id).style || {};
|
|
57249
57388
|
const { w, h } = extract_size(style);
|
|
57250
57389
|
const ports = style.ports || [];
|
|
57251
|
-
const defaultR = style.portR ||
|
|
57390
|
+
const defaultR = style.portR || PORT_R_ENTITY;
|
|
57252
57391
|
let best_key = null;
|
|
57253
57392
|
let best_dist = Infinity;
|
|
57254
57393
|
let slop = port_hit_slop_world(graph);
|
|
@@ -57405,7 +57544,7 @@ function enter_linking_mode(gobj) {
|
|
|
57405
57544
|
p.stroke = "#52c41a";
|
|
57406
57545
|
p.lineWidth = 3;
|
|
57407
57546
|
if (p.r != null) p.r = p.r + 4;
|
|
57408
|
-
else p.r = (style.portR ||
|
|
57547
|
+
else p.r = (style.portR || PORT_R_ENTITY) + 4;
|
|
57409
57548
|
}
|
|
57410
57549
|
graph.updateNodeData([{
|
|
57411
57550
|
id: vh.node_id,
|
|
@@ -57557,7 +57696,7 @@ function find_hook_at_point(gobj, canvasX, canvasY) {
|
|
|
57557
57696
|
let pl = p.placement || [.5, .5];
|
|
57558
57697
|
let px = pos[0] + (pl[0] - .5) * w;
|
|
57559
57698
|
let py = pos[1] + (pl[1] - .5) * h;
|
|
57560
|
-
let r = p.r != null ? p.r : style.portR ||
|
|
57699
|
+
let r = p.r != null ? p.r : style.portR || PORT_R_ENTITY;
|
|
57561
57700
|
let dx = canvasX - px;
|
|
57562
57701
|
let dy = canvasY - py;
|
|
57563
57702
|
if (Math.sqrt(dx * dx + dy * dy) <= r + 6) return {
|
|
@@ -58315,7 +58454,19 @@ function repaint_cards(gobj, ids) {
|
|
|
58315
58454
|
} catch (e) {
|
|
58316
58455
|
continue;
|
|
58317
58456
|
}
|
|
58318
|
-
let
|
|
58457
|
+
let anchored = priv.anchor_state === "on" && id === priv.anchor_id;
|
|
58458
|
+
if (nd && nd.data && nd.data.desc && node_is_compact(gobj, id)) {
|
|
58459
|
+
updates.push({
|
|
58460
|
+
id,
|
|
58461
|
+
style: compact_shape_of(gobj, nd.data.desc, nd.data.record || {}, {
|
|
58462
|
+
highlight: focus.has(id),
|
|
58463
|
+
selected: selected.has(id),
|
|
58464
|
+
anchored
|
|
58465
|
+
}).style
|
|
58466
|
+
});
|
|
58467
|
+
continue;
|
|
58468
|
+
}
|
|
58469
|
+
let html = node_innerHTML_of(nd, priv.theme, focus.has(id), selected.has(id), anchored, pills_html_of(gobj, nd));
|
|
58319
58470
|
if (html !== null) updates.push({
|
|
58320
58471
|
id,
|
|
58321
58472
|
style: { innerHTML: html }
|
|
@@ -58352,7 +58503,19 @@ function refresh_html_nodes_theme(gobj, theme) {
|
|
|
58352
58503
|
for (let i = 0; i < nodes.length; i++) {
|
|
58353
58504
|
let id = nodes[i].id;
|
|
58354
58505
|
let nd = graph.getNodeData(id);
|
|
58355
|
-
let
|
|
58506
|
+
let anchored = priv.anchor_state === "on" && id === priv.anchor_id;
|
|
58507
|
+
if (nd && nd.data && nd.data.desc && node_is_compact(gobj, id)) {
|
|
58508
|
+
updates.push({
|
|
58509
|
+
id,
|
|
58510
|
+
style: compact_shape_of(gobj, nd.data.desc, nd.data.record || {}, {
|
|
58511
|
+
highlight: highlighted.has(id),
|
|
58512
|
+
selected: selected.has(id),
|
|
58513
|
+
anchored
|
|
58514
|
+
}).style
|
|
58515
|
+
});
|
|
58516
|
+
continue;
|
|
58517
|
+
}
|
|
58518
|
+
let html = node_innerHTML_of(nd, theme, highlighted.has(id), selected.has(id), anchored, pills_html_of(gobj, nd));
|
|
58356
58519
|
if (html === null) html = more_innerHTML_of(gobj, nd, theme);
|
|
58357
58520
|
if (html !== null) updates.push({
|
|
58358
58521
|
id,
|
|
@@ -58972,8 +59135,10 @@ function ctx_item(icon_id, label, value) {
|
|
|
58972
59135
|
************************************************************/
|
|
58973
59136
|
function build_node_context_menu(gobj, node_id) {
|
|
58974
59137
|
let items = [];
|
|
58975
|
-
|
|
58976
|
-
|
|
59138
|
+
inject_svg_icons();
|
|
59139
|
+
if (node_is_compact(gobj, node_id)) items.push(ctx_item("g6-icon-fullscreen", t("open node"), "toggle_node_mode"));
|
|
59140
|
+
else items.push(ctx_item("g6-icon-fullscreen-exit", t("close node"), "toggle_node_mode"));
|
|
59141
|
+
if (gobj.priv.edit_mode && !node_is_compact(gobj, node_id)) {
|
|
58977
59142
|
items.push(ctx_item("g6-icon-resize", t("resize all"), "resize_all_nodes"));
|
|
58978
59143
|
items.push(ctx_item("g6-icon-resize", t("resize topic nodes"), "resize_topic_nodes"));
|
|
58979
59144
|
}
|
|
@@ -59001,8 +59166,11 @@ function build_edge_context_menu(gobj) {
|
|
|
59001
59166
|
* Handle context menu click: dispatch by value.
|
|
59002
59167
|
************************************************************/
|
|
59003
59168
|
function handle_context_menu_click(gobj, value) {
|
|
59004
|
-
gobj.priv;
|
|
59169
|
+
let priv = gobj.priv;
|
|
59005
59170
|
switch (value) {
|
|
59171
|
+
case "toggle_node_mode":
|
|
59172
|
+
if (priv._context_node_id) gobj_send_event(gobj, "EV_TOGGLE_NODE_MODE", { id: priv._context_node_id }, gobj);
|
|
59173
|
+
break;
|
|
59006
59174
|
case "resize_all_nodes":
|
|
59007
59175
|
copy_size_to_nodes(gobj, false);
|
|
59008
59176
|
break;
|
|
@@ -59533,7 +59701,7 @@ async function reconcile_fold_apply(gobj, opts, visible) {
|
|
|
59533
59701
|
let nd = graph.getNodeData(id);
|
|
59534
59702
|
let desc = nd && nd.data && nd.data.desc;
|
|
59535
59703
|
let geometry = nd && nd.data && nd.data.graph_props || {};
|
|
59536
|
-
if (desc && !is_array(geometry.size)) {
|
|
59704
|
+
if (desc && !is_array(geometry.size) && !node_is_compact(gobj, id)) {
|
|
59537
59705
|
let size = card_size_for(desc.node_treedb_type, !!sig);
|
|
59538
59706
|
resize.push({
|
|
59539
59707
|
id,
|
|
@@ -59618,6 +59786,7 @@ function ac_clear_data(gobj, event, kw, src) {
|
|
|
59618
59786
|
priv._fold_model = null;
|
|
59619
59787
|
priv._fold_state = null;
|
|
59620
59788
|
priv._pill_sig = null;
|
|
59789
|
+
priv._open_nodes = null;
|
|
59621
59790
|
graph_remove_plugin(gobj, "history");
|
|
59622
59791
|
update_history_buttons(gobj);
|
|
59623
59792
|
graph_clear(gobj);
|
|
@@ -60116,6 +60285,79 @@ function ac_set_loose_topics(gobj, event, kw, src) {
|
|
|
60116
60285
|
return 0;
|
|
60117
60286
|
}
|
|
60118
60287
|
/************************************************************
|
|
60288
|
+
* The shape of every record: open cards or closed squares.
|
|
60289
|
+
* A change of mode forgets the nodes toggled against the old
|
|
60290
|
+
* one -- they were exceptions to a rule that no longer holds --
|
|
60291
|
+
* and lays the graph out again, because a square and a card
|
|
60292
|
+
* do not occupy the same room.
|
|
60293
|
+
************************************************************/
|
|
60294
|
+
function ac_set_node_mode(gobj, event, kw, src) {
|
|
60295
|
+
let priv = gobj.priv;
|
|
60296
|
+
let mode = kw && kw.node_mode === "compact" ? "compact" : "expanded";
|
|
60297
|
+
gobj_write_str_attr(gobj, "node_mode", mode);
|
|
60298
|
+
priv._open_nodes = /* @__PURE__ */ new Set();
|
|
60299
|
+
if (!priv.graph || !priv._fold_model) return 0;
|
|
60300
|
+
reshape_nodes(gobj, all_record_node_ids(gobj));
|
|
60301
|
+
reconcile_fold(gobj, {
|
|
60302
|
+
relayout: true,
|
|
60303
|
+
fit: true
|
|
60304
|
+
});
|
|
60305
|
+
return 0;
|
|
60306
|
+
}
|
|
60307
|
+
/************************************************************
|
|
60308
|
+
* The name under a closed square, on or off. Only the closed
|
|
60309
|
+
* nodes change, and nothing moves: the label hangs outside the
|
|
60310
|
+
* square and the layout measures the square.
|
|
60311
|
+
************************************************************/
|
|
60312
|
+
function ac_set_node_labels(gobj, event, kw, src) {
|
|
60313
|
+
let priv = gobj.priv;
|
|
60314
|
+
gobj_write_bool_attr(gobj, "node_labels", !!(kw && kw.node_labels));
|
|
60315
|
+
if (!priv.graph) return 0;
|
|
60316
|
+
reshape_nodes(gobj, all_record_node_ids(gobj).filter((id) => node_is_compact(gobj, id)));
|
|
60317
|
+
return 0;
|
|
60318
|
+
}
|
|
60319
|
+
/************************************************************
|
|
60320
|
+
* ONE node opened or closed against the mode (a double click,
|
|
60321
|
+
* or the context menu). It holds still on screen while the
|
|
60322
|
+
* rest of the graph makes room, as a fold does.
|
|
60323
|
+
************************************************************/
|
|
60324
|
+
function ac_toggle_node_mode$1(gobj, event, kw, src) {
|
|
60325
|
+
let priv = gobj.priv;
|
|
60326
|
+
let node_id = kw && kw.id || "";
|
|
60327
|
+
if (!priv.graph || !node_id) {
|
|
60328
|
+
log_error(`${gobj_short_name(gobj)}: toggle node mode without a node`);
|
|
60329
|
+
return -1;
|
|
60330
|
+
}
|
|
60331
|
+
if (!priv._open_nodes) priv._open_nodes = /* @__PURE__ */ new Set();
|
|
60332
|
+
if (priv._open_nodes.has(node_id)) priv._open_nodes.delete(node_id);
|
|
60333
|
+
else priv._open_nodes.add(node_id);
|
|
60334
|
+
let vp = yui_graph_viewport_of(priv.graph, node_id);
|
|
60335
|
+
reshape_nodes(gobj, [node_id]);
|
|
60336
|
+
if (priv._fold_model) reconcile_fold(gobj, {
|
|
60337
|
+
relayout: true,
|
|
60338
|
+
keep: node_id,
|
|
60339
|
+
keep_vp: vp
|
|
60340
|
+
});
|
|
60341
|
+
return 0;
|
|
60342
|
+
}
|
|
60343
|
+
/************************************************************
|
|
60344
|
+
* A double click on a node: open it if closed, close it if open.
|
|
60345
|
+
* A `+N` chip is not a record and has no shape to toggle.
|
|
60346
|
+
************************************************************/
|
|
60347
|
+
function ac_node_dblclick(gobj, event, kw, src) {
|
|
60348
|
+
let priv = gobj.priv;
|
|
60349
|
+
let node_id = kw && kw.evt && kw.evt.target ? kw.evt.target.id : "";
|
|
60350
|
+
let nd = null;
|
|
60351
|
+
try {
|
|
60352
|
+
nd = priv.graph.getNodeData(node_id);
|
|
60353
|
+
} catch (e) {
|
|
60354
|
+
nd = null;
|
|
60355
|
+
}
|
|
60356
|
+
if (!nd || !nd.data || !nd.data.desc || is_more_node(nd)) return 0;
|
|
60357
|
+
gobj_send_event(gobj, "EV_TOGGLE_NODE_MODE", { id: node_id }, gobj);
|
|
60358
|
+
return 0;
|
|
60359
|
+
}
|
|
60360
|
+
/************************************************************
|
|
60119
60361
|
* Tell whoever asked how many nodes the term matched. The count is
|
|
60120
60362
|
* the answer to the question the box asks; without it "nothing moved"
|
|
60121
60363
|
* and "nothing matched" look the same.
|
|
@@ -60605,6 +60847,26 @@ function create_gclass$4(gclass_name) {
|
|
|
60605
60847
|
ac_set_loose_topics,
|
|
60606
60848
|
null
|
|
60607
60849
|
],
|
|
60850
|
+
[
|
|
60851
|
+
"EV_SET_NODE_MODE",
|
|
60852
|
+
ac_set_node_mode,
|
|
60853
|
+
null
|
|
60854
|
+
],
|
|
60855
|
+
[
|
|
60856
|
+
"EV_SET_NODE_LABELS",
|
|
60857
|
+
ac_set_node_labels,
|
|
60858
|
+
null
|
|
60859
|
+
],
|
|
60860
|
+
[
|
|
60861
|
+
"EV_TOGGLE_NODE_MODE",
|
|
60862
|
+
ac_toggle_node_mode$1,
|
|
60863
|
+
null
|
|
60864
|
+
],
|
|
60865
|
+
[
|
|
60866
|
+
"EV_NODE_DBLCLICK",
|
|
60867
|
+
ac_node_dblclick,
|
|
60868
|
+
null
|
|
60869
|
+
],
|
|
60608
60870
|
[
|
|
60609
60871
|
"EV_CENTER",
|
|
60610
60872
|
ac_center,
|
|
@@ -60709,6 +60971,10 @@ function create_gclass$4(gclass_name) {
|
|
|
60709
60971
|
["EV_SET_HIDDEN_TOPICS", 0],
|
|
60710
60972
|
["EV_SET_MAIN_TOPIC", 0],
|
|
60711
60973
|
["EV_SET_LOOSE_TOPICS", 0],
|
|
60974
|
+
["EV_SET_NODE_MODE", 0],
|
|
60975
|
+
["EV_SET_NODE_LABELS", 0],
|
|
60976
|
+
["EV_TOGGLE_NODE_MODE", 0],
|
|
60977
|
+
["EV_NODE_DBLCLICK", 0],
|
|
60712
60978
|
["EV_LEGEND_STATE", event_flag_t.EVF_OUTPUT_EVENT],
|
|
60713
60979
|
["EV_CENTER", 0],
|
|
60714
60980
|
["EV_FULLSCREEN", 0],
|
|
@@ -60774,6 +61040,8 @@ var attrs_table$3 = [
|
|
|
60774
61040
|
SDATA(data_type_t.DTP_LIST, "hidden_topics", sdata_flag_t.SDF_PERSIST, "[]", "Topics hidden from the graph (legend). User preference, per treedb"),
|
|
60775
61041
|
SDATA(data_type_t.DTP_STRING, "main_topic", sdata_flag_t.SDF_PERSIST, "", "The topic the tree hangs from; empty = deduced by the graph. User preference, per treedb"),
|
|
60776
61042
|
SDATA(data_type_t.DTP_LIST, "loose_topics", sdata_flag_t.SDF_PERSIST, "[]", "Topics whose LOOSE records (no parent) are shown. User preference, per treedb"),
|
|
61043
|
+
SDATA(data_type_t.DTP_STRING, "node_mode", sdata_flag_t.SDF_PERSIST, "expanded", "How the records are drawn: `expanded` = the cards with their ports, `compact` = coloured squares, the topology alone. User preference"),
|
|
61044
|
+
SDATA(data_type_t.DTP_BOOLEAN, "node_labels", sdata_flag_t.SDF_PERSIST, true, "A compact node says its name under its square. User preference"),
|
|
60777
61045
|
SDATA(data_type_t.DTP_POINTER, "gobj_remote_yuno", 0, null, "Remote Yuno to request data"),
|
|
60778
61046
|
SDATA(data_type_t.DTP_STRING, "treedb_name", 0, null, "Remote service treedb name"),
|
|
60779
61047
|
SDATA(data_type_t.DTP_DICT, "descs", 0, null, "Descriptions of topics obtained"),
|
|
@@ -60851,7 +61119,9 @@ function mt_create$3(gobj) {
|
|
|
60851
61119
|
fold_page_size: gobj_read_integer_attr(gobj, "fold_page_size"),
|
|
60852
61120
|
hidden_topics: gobj_read_attr(gobj, "hidden_topics") || [],
|
|
60853
61121
|
main_topic: gobj_read_str_attr(gobj, "main_topic") || "",
|
|
60854
|
-
loose_topics: gobj_read_attr(gobj, "loose_topics") || []
|
|
61122
|
+
loose_topics: gobj_read_attr(gobj, "loose_topics") || [],
|
|
61123
|
+
node_mode: gobj_read_str_attr(gobj, "node_mode") || "expanded",
|
|
61124
|
+
node_labels: gobj_read_bool_attr(gobj, "node_labels")
|
|
60855
61125
|
}, gobj);
|
|
60856
61126
|
populate_nodes_tree_options(gobj);
|
|
60857
61127
|
if (priv.with_treedb_tables) {}
|
|
@@ -60902,6 +61172,7 @@ function build_ui$3(gobj) {
|
|
|
60902
61172
|
let priv = gobj.priv;
|
|
60903
61173
|
let padding = gobj_read_attr(gobj, "padding");
|
|
60904
61174
|
let $toolbar = make_toolbar(gobj);
|
|
61175
|
+
refresh_node_shape_buttons(gobj, $toolbar);
|
|
60905
61176
|
let $back = make_back_to_topics(gobj);
|
|
60906
61177
|
let $container = createElement2([
|
|
60907
61178
|
"div",
|
|
@@ -61031,7 +61302,6 @@ function option_label(name) {
|
|
|
61031
61302
|
case "edition": return t("edition");
|
|
61032
61303
|
case "manual": return t("manual");
|
|
61033
61304
|
case "treedb-tree": return t("treedb-tree");
|
|
61034
|
-
case "treedb-outline": return t("treedb-outline");
|
|
61035
61305
|
case "radial": return t("radial");
|
|
61036
61306
|
case "dagre": return t("dagre");
|
|
61037
61307
|
case "antv-dagre": return t("antv-dagre");
|
|
@@ -61043,6 +61313,57 @@ function option_label(name) {
|
|
|
61043
61313
|
/************************************************************
|
|
61044
61314
|
*
|
|
61045
61315
|
************************************************************/
|
|
61316
|
+
/************************************************************
|
|
61317
|
+
* The two toggles of the nodes' shape.
|
|
61318
|
+
*
|
|
61319
|
+
* Closed nodes: every record a rounded square of its topic's
|
|
61320
|
+
* colour, no ports, no text -- the topology of a graph of many
|
|
61321
|
+
* nodes, which the cards hide behind their own size. Labels:
|
|
61322
|
+
* the name under each square, when the squares alone do not say
|
|
61323
|
+
* enough. Both persist, both are forwarded to the G6 child, and
|
|
61324
|
+
* one node can be opened against the rule with a double click or
|
|
61325
|
+
* its context menu (the child's business).
|
|
61326
|
+
************************************************************/
|
|
61327
|
+
function node_shape_items(gobj, wide) {
|
|
61328
|
+
let toggle = (cls, icon, event_name, label_key) => {
|
|
61329
|
+
return [
|
|
61330
|
+
"button",
|
|
61331
|
+
{
|
|
61332
|
+
class: `${cls} button`,
|
|
61333
|
+
type: "button",
|
|
61334
|
+
style: {
|
|
61335
|
+
height: wide,
|
|
61336
|
+
width: "2.5em"
|
|
61337
|
+
},
|
|
61338
|
+
title: t(label_key),
|
|
61339
|
+
"data-i18n-title": label_key,
|
|
61340
|
+
"aria-label": t(label_key),
|
|
61341
|
+
"data-i18n-aria-label": label_key,
|
|
61342
|
+
"aria-pressed": "false"
|
|
61343
|
+
},
|
|
61344
|
+
["i", {
|
|
61345
|
+
style: "font-size:1.5em; color:inherit;",
|
|
61346
|
+
class: icon
|
|
61347
|
+
}],
|
|
61348
|
+
{ click: (evt) => {
|
|
61349
|
+
evt.stopPropagation();
|
|
61350
|
+
gobj_send_event(gobj, event_name, {}, gobj);
|
|
61351
|
+
} }
|
|
61352
|
+
];
|
|
61353
|
+
};
|
|
61354
|
+
return [toggle("GRAPH_NODE_MODE", "yi-hexagon-nodes", "EV_TOGGLE_NODE_MODE", "closed nodes"), toggle("GRAPH_NODE_LABELS", "yi-font", "EV_TOGGLE_NODE_LABELS", "node labels")];
|
|
61355
|
+
}
|
|
61356
|
+
function refresh_node_shape_buttons(gobj, $root) {
|
|
61357
|
+
if (!$root) return;
|
|
61358
|
+
let compact = gobj_read_str_attr(gobj, "node_mode") === "compact";
|
|
61359
|
+
let labels = gobj_read_bool_attr(gobj, "node_labels");
|
|
61360
|
+
set_pressed_state($root, ".GRAPH_NODE_MODE", compact);
|
|
61361
|
+
set_pressed_state($root, ".GRAPH_NODE_LABELS", labels);
|
|
61362
|
+
let $mode = $root.querySelector(".GRAPH_NODE_MODE");
|
|
61363
|
+
if ($mode) $mode.setAttribute("aria-pressed", compact ? "true" : "false");
|
|
61364
|
+
let $labels = $root.querySelector(".GRAPH_NODE_LABELS");
|
|
61365
|
+
if ($labels) $labels.setAttribute("aria-pressed", labels ? "true" : "false");
|
|
61366
|
+
}
|
|
61046
61367
|
function make_toolbar(gobj) {
|
|
61047
61368
|
let priv = gobj.priv;
|
|
61048
61369
|
let modes = gobj_read_attr(gobj, "operation_modes");
|
|
@@ -61113,6 +61434,7 @@ function make_toolbar(gobj) {
|
|
|
61113
61434
|
} }
|
|
61114
61435
|
],
|
|
61115
61436
|
...yui_graph_fold_items(gobj, gobj_read_str_attr(gobj, "wide")),
|
|
61437
|
+
...node_shape_items(gobj, gobj_read_str_attr(gobj, "wide")),
|
|
61116
61438
|
[
|
|
61117
61439
|
"button",
|
|
61118
61440
|
{
|
|
@@ -62427,6 +62749,29 @@ function ac_collapse_all(gobj, event, kw, src) {
|
|
|
62427
62749
|
return 0;
|
|
62428
62750
|
}
|
|
62429
62751
|
/************************************************************
|
|
62752
|
+
* The shape pair of the toolbar: the attr flips, persists,
|
|
62753
|
+
* shows on the button, and reaches the G6 child, which owns
|
|
62754
|
+
* the nodes.
|
|
62755
|
+
************************************************************/
|
|
62756
|
+
function ac_toggle_node_mode(gobj, event, kw, src) {
|
|
62757
|
+
let priv = gobj.priv;
|
|
62758
|
+
let mode = gobj_read_str_attr(gobj, "node_mode") === "compact" ? "expanded" : "compact";
|
|
62759
|
+
gobj_write_str_attr(gobj, "node_mode", mode);
|
|
62760
|
+
gobj_save_persistent_attrs(gobj, "node_mode");
|
|
62761
|
+
refresh_node_shape_buttons(gobj, priv.$container);
|
|
62762
|
+
if (priv.gobj_nodes_tree) gobj_send_event(priv.gobj_nodes_tree, "EV_SET_NODE_MODE", { node_mode: mode }, gobj);
|
|
62763
|
+
return 0;
|
|
62764
|
+
}
|
|
62765
|
+
function ac_toggle_node_labels(gobj, event, kw, src) {
|
|
62766
|
+
let priv = gobj.priv;
|
|
62767
|
+
let labels = !gobj_read_bool_attr(gobj, "node_labels");
|
|
62768
|
+
gobj_write_bool_attr(gobj, "node_labels", labels);
|
|
62769
|
+
gobj_save_persistent_attrs(gobj, "node_labels");
|
|
62770
|
+
refresh_node_shape_buttons(gobj, priv.$container);
|
|
62771
|
+
if (priv.gobj_nodes_tree) gobj_send_event(priv.gobj_nodes_tree, "EV_SET_NODE_LABELS", { node_labels: labels }, gobj);
|
|
62772
|
+
return 0;
|
|
62773
|
+
}
|
|
62774
|
+
/************************************************************
|
|
62430
62775
|
* How many nodes the term matched, from the graph child. Zero with a
|
|
62431
62776
|
* term typed is an ANSWER and is shown; an empty box shows nothing.
|
|
62432
62777
|
************************************************************/
|
|
@@ -62640,6 +62985,16 @@ function create_gclass$3(gclass_name) {
|
|
|
62640
62985
|
ac_collapse_all,
|
|
62641
62986
|
null
|
|
62642
62987
|
],
|
|
62988
|
+
[
|
|
62989
|
+
"EV_TOGGLE_NODE_MODE",
|
|
62990
|
+
ac_toggle_node_mode,
|
|
62991
|
+
null
|
|
62992
|
+
],
|
|
62993
|
+
[
|
|
62994
|
+
"EV_TOGGLE_NODE_LABELS",
|
|
62995
|
+
ac_toggle_node_labels,
|
|
62996
|
+
null
|
|
62997
|
+
],
|
|
62643
62998
|
[
|
|
62644
62999
|
"EV_LAYOUT_AUTOSET",
|
|
62645
63000
|
ac_layout_autoset,
|
|
@@ -62704,6 +63059,8 @@ function create_gclass$3(gclass_name) {
|
|
|
62704
63059
|
["EV_FIND_NODES", 0],
|
|
62705
63060
|
["EV_EXPAND_ALL", 0],
|
|
62706
63061
|
["EV_COLLAPSE_ALL", 0],
|
|
63062
|
+
["EV_TOGGLE_NODE_MODE", 0],
|
|
63063
|
+
["EV_TOGGLE_NODE_LABELS", 0],
|
|
62707
63064
|
["EV_FIND_RESULT", 0],
|
|
62708
63065
|
["EV_LAYOUT_AUTOSET", 0],
|
|
62709
63066
|
["EV_LEGEND_TOPIC", 0],
|