@yuneta/gobj-ui 7.23.20 → 7.23.22
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 +65 -51
- package/dist/gobj-ui.es.js +73 -51
- package/package.json +1 -1
- package/src/c_g6_nodes_tree.js +1 -53
- package/src/c_yui_json_graph.js +92 -9
- package/src/lib_graph.js +55 -0
package/dist/gobj-ui.cjs.js
CHANGED
|
@@ -9474,6 +9474,23 @@ function getStrokeColor(fillColor, theme = "light", factor = .2) {
|
|
|
9474
9474
|
const adjust = (v) => lighten ? Math.min(255, Math.floor(v + (255 - v) * factor)) : Math.max(0, Math.floor(v * (1 - factor)));
|
|
9475
9475
|
return `rgba(${adjust(r)}, ${adjust(g)}, ${adjust(b)}, ${a.toFixed(3)})`;
|
|
9476
9476
|
}
|
|
9477
|
+
/************************************************************
|
|
9478
|
+
* Returns the proportional position (between 0 and 1) of a specific point,
|
|
9479
|
+
* centered and spaced with margins.
|
|
9480
|
+
*
|
|
9481
|
+
* index - Index of the point (0 to count-1)
|
|
9482
|
+
* count - Total number of points
|
|
9483
|
+
* margin - Total margin space (default 0.2 means 10% on each end)
|
|
9484
|
+
************************************************************/
|
|
9485
|
+
function getPointPosition(count, index, margin = .2) {
|
|
9486
|
+
if (count <= 0 || index < 0 || index >= count) {
|
|
9487
|
+
(0, _yuneta_gobj_js.log_error)("Invalid count or index");
|
|
9488
|
+
return .5;
|
|
9489
|
+
}
|
|
9490
|
+
const start = margin / 2;
|
|
9491
|
+
const step = (1 - margin / 2 - start) / count;
|
|
9492
|
+
return start + index * step + step / 2;
|
|
9493
|
+
}
|
|
9477
9494
|
//#endregion
|
|
9478
9495
|
//#region src/yui_graph_camera.js
|
|
9479
9496
|
/***********************************************************************
|
|
@@ -10942,6 +10959,16 @@ function build_graph$3(gobj) {
|
|
|
10942
10959
|
}
|
|
10943
10960
|
}
|
|
10944
10961
|
/************************************************************
|
|
10962
|
+
* The port a container key opens on its card.
|
|
10963
|
+
*
|
|
10964
|
+
* Prefixed so it can never collide with anything G6 puts in
|
|
10965
|
+
* the same namespace, and stringified because an array index
|
|
10966
|
+
* is a number and a port key is a string.
|
|
10967
|
+
************************************************************/
|
|
10968
|
+
function port_key(key) {
|
|
10969
|
+
return "p_" + String(key);
|
|
10970
|
+
}
|
|
10971
|
+
/************************************************************
|
|
10945
10972
|
* Build cell value HTML (matching old mx_json_viewer colors)
|
|
10946
10973
|
************************************************************/
|
|
10947
10974
|
function build_cell_html(key, value, type, dark, matched, fold) {
|
|
@@ -11004,6 +11031,8 @@ function build_cell_html(key, value, type, dark, matched, fold) {
|
|
|
11004
11031
|
* forever. `+3` and `−` need no language.
|
|
11005
11032
|
************************************************************/
|
|
11006
11033
|
var FOLD_SPACER = `<span style="width:24px; flex:0 0 auto;"></span>`;
|
|
11034
|
+
var CARD_HEADER_H$1 = 24;
|
|
11035
|
+
var CARD_ROW_H$1 = 22;
|
|
11007
11036
|
function fold_toggle_html(path, foldable, folded, branches, colors) {
|
|
11008
11037
|
if (!foldable) return FOLD_SPACER;
|
|
11009
11038
|
let label = folded ? "+" + branches : "−";
|
|
@@ -11084,7 +11113,7 @@ function get_group_label(path) {
|
|
|
11084
11113
|
/************************************************************
|
|
11085
11114
|
* Recursively build nodes and edges from JSON
|
|
11086
11115
|
************************************************************/
|
|
11087
|
-
function build_json_nodes(gobj, path, kw, nodes, edges, parent_id) {
|
|
11116
|
+
function build_json_nodes(gobj, path, kw, nodes, edges, parent_id, parent_port) {
|
|
11088
11117
|
let group_id = gen_node_id$1(gobj);
|
|
11089
11118
|
let is_dict = (0, _yuneta_gobj_js.is_object)(kw);
|
|
11090
11119
|
let is_list = (0, _yuneta_gobj_js.is_array)(kw);
|
|
@@ -11108,7 +11137,9 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id) {
|
|
|
11108
11137
|
if (has_branch(value)) {
|
|
11109
11138
|
pending_complex.push({
|
|
11110
11139
|
key,
|
|
11111
|
-
value
|
|
11140
|
+
value,
|
|
11141
|
+
port: port_key(key),
|
|
11142
|
+
row: lines.length
|
|
11112
11143
|
});
|
|
11113
11144
|
if (is_pure_collection(value)) {
|
|
11114
11145
|
let child_path = add_segment(path, key);
|
|
@@ -11124,7 +11155,7 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id) {
|
|
|
11124
11155
|
}
|
|
11125
11156
|
if (parent_id && is_pure_collection(kw)) {
|
|
11126
11157
|
if (priv.collapsed.has(path)) return parent_id;
|
|
11127
|
-
for (let pending of pending_complex) build_json_nodes(gobj, add_segment(path, pending.key), pending.value, nodes, edges, parent_id);
|
|
11158
|
+
for (let pending of pending_complex) build_json_nodes(gobj, add_segment(path, pending.key), pending.value, nodes, edges, parent_id, parent_port);
|
|
11128
11159
|
return parent_id;
|
|
11129
11160
|
}
|
|
11130
11161
|
let label = get_group_label(path) || (is_dict ? "{}" : "[]");
|
|
@@ -11134,6 +11165,7 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id) {
|
|
|
11134
11165
|
let border_width = card_matched ? 2 : 1;
|
|
11135
11166
|
let content_html = lines.map((line) => `<div style="font-family:monospace; font-size:13px; padding:1px 6px; white-space:nowrap;">${line}</div>`).join("");
|
|
11136
11167
|
let min_width = Math.max(180, label.length * 9);
|
|
11168
|
+
let card_height = CARD_HEADER_H$1 + lines.length * CARD_ROW_H$1;
|
|
11137
11169
|
let node_html = `
|
|
11138
11170
|
<div style="
|
|
11139
11171
|
min-width: ${min_width}px;
|
|
@@ -11155,6 +11187,17 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id) {
|
|
|
11155
11187
|
">${FOLD_SPACER}<span style="flex:1 1 auto; text-align:center;">${(0, _yuneta_gobj_js.escapeHtml)(label)}</span>${fold_toggle_html(path, foldable, folded, pending_complex.length, colors)}</div>
|
|
11156
11188
|
${content_html}
|
|
11157
11189
|
</div>`;
|
|
11190
|
+
let ports = [];
|
|
11191
|
+
for (let pending of pending_complex) {
|
|
11192
|
+
let child_colors = json_card_style((0, _yuneta_gobj_js.is_object)(pending.value) ? GROUP_COLORS.dict : GROUP_COLORS.list, dark);
|
|
11193
|
+
let row_mid = CARD_HEADER_H$1 + pending.row * CARD_ROW_H$1 + CARD_ROW_H$1 / 2;
|
|
11194
|
+
ports.push({
|
|
11195
|
+
key: pending.port,
|
|
11196
|
+
placement: [1, row_mid / card_height],
|
|
11197
|
+
fill: child_colors.border,
|
|
11198
|
+
stroke: colors.border
|
|
11199
|
+
});
|
|
11200
|
+
}
|
|
11158
11201
|
let node = {
|
|
11159
11202
|
id: group_id,
|
|
11160
11203
|
type: "html",
|
|
@@ -11164,22 +11207,30 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id) {
|
|
|
11164
11207
|
},
|
|
11165
11208
|
style: {
|
|
11166
11209
|
innerHTML: node_html,
|
|
11167
|
-
size: [min_width,
|
|
11210
|
+
size: [min_width, card_height],
|
|
11168
11211
|
dx: -(min_width / 2),
|
|
11169
|
-
dy: -(
|
|
11212
|
+
dy: -(card_height / 2),
|
|
11213
|
+
port: ports.length > 0,
|
|
11214
|
+
ports,
|
|
11215
|
+
portR: 4,
|
|
11216
|
+
portLineWidth: 1
|
|
11170
11217
|
}
|
|
11171
11218
|
};
|
|
11172
11219
|
nodes.push(node);
|
|
11173
|
-
if (parent_id)
|
|
11174
|
-
|
|
11175
|
-
|
|
11176
|
-
|
|
11177
|
-
|
|
11178
|
-
|
|
11179
|
-
|
|
11180
|
-
|
|
11220
|
+
if (parent_id) {
|
|
11221
|
+
let edge = {
|
|
11222
|
+
source: parent_id,
|
|
11223
|
+
target: group_id,
|
|
11224
|
+
style: {
|
|
11225
|
+
stroke: colors.border,
|
|
11226
|
+
lineWidth: 1
|
|
11227
|
+
}
|
|
11228
|
+
};
|
|
11229
|
+
if (parent_port) edge.style.sourcePort = parent_port;
|
|
11230
|
+
edges.push(edge);
|
|
11231
|
+
}
|
|
11181
11232
|
if (folded) return group_id;
|
|
11182
|
-
for (let pending of pending_complex) build_json_nodes(gobj, add_segment(path, pending.key), pending.value, nodes, edges, group_id);
|
|
11233
|
+
for (let pending of pending_complex) build_json_nodes(gobj, add_segment(path, pending.key), pending.value, nodes, edges, group_id, pending.port);
|
|
11183
11234
|
return group_id;
|
|
11184
11235
|
}
|
|
11185
11236
|
/************************************************************
|
|
@@ -49032,43 +49083,6 @@ function configure_behaviour(gobj) {
|
|
|
49032
49083
|
graph_write_behaviors(gobj, behaviors);
|
|
49033
49084
|
}
|
|
49034
49085
|
/************************************************************
|
|
49035
|
-
* Returns the proportional position (between 0 and 1) of a specific point,
|
|
49036
|
-
* centered and spaced with margins.
|
|
49037
|
-
*
|
|
49038
|
-
* index - Index of the point (0 to count-1)
|
|
49039
|
-
* count - Total number of points
|
|
49040
|
-
* margin - Total margin space (default 0.2 means 10% on each end)
|
|
49041
|
-
************************************************************/
|
|
49042
|
-
function getPointPosition(count, index, margin = .2) {
|
|
49043
|
-
if (count <= 0 || index < 0 || index >= count) {
|
|
49044
|
-
(0, _yuneta_gobj_js.log_error)("Invalid count or index");
|
|
49045
|
-
return .5;
|
|
49046
|
-
}
|
|
49047
|
-
const start = margin / 2;
|
|
49048
|
-
const step = (1 - margin / 2 - start) / count;
|
|
49049
|
-
return start + index * step + step / 2;
|
|
49050
|
-
}
|
|
49051
|
-
/************************************************************
|
|
49052
|
-
* Count hooks and fkeys in topic desc, classify node type
|
|
49053
|
-
************************************************************/
|
|
49054
|
-
function calculate_hooks_fkeys_counter(desc) {
|
|
49055
|
-
let cols = desc.cols;
|
|
49056
|
-
desc.hooks_counter = 0;
|
|
49057
|
-
desc.fkeys_counter = 0;
|
|
49058
|
-
for (let i = 0; i < cols.length; i++) {
|
|
49059
|
-
let col = cols[i];
|
|
49060
|
-
switch ((0, _yuneta_gobj_js.treedb_get_field_desc)(col).type) {
|
|
49061
|
-
case "hook":
|
|
49062
|
-
desc.hooks_counter++;
|
|
49063
|
-
break;
|
|
49064
|
-
case "fkey": desc.fkeys_counter++;
|
|
49065
|
-
}
|
|
49066
|
-
}
|
|
49067
|
-
if (desc.hooks_counter === 0) desc.node_treedb_type = "child";
|
|
49068
|
-
else if (desc.fkeys_counter === 0) desc.node_treedb_type = "extended";
|
|
49069
|
-
else desc.node_treedb_type = "hierarchical";
|
|
49070
|
-
}
|
|
49071
|
-
/************************************************************
|
|
49072
49086
|
* Build ports for a topic desc
|
|
49073
49087
|
************************************************************/
|
|
49074
49088
|
function build_ports(gobj, desc) {
|
package/dist/gobj-ui.es.js
CHANGED
|
@@ -9346,6 +9346,14 @@ function yui_toolbar(attrs = {}, items = []) {
|
|
|
9346
9346
|
}
|
|
9347
9347
|
//#endregion
|
|
9348
9348
|
//#region src/lib_graph.js
|
|
9349
|
+
/***********************************************************************
|
|
9350
|
+
* lib_graph.js
|
|
9351
|
+
*
|
|
9352
|
+
* Utilities for graph, using Bulma
|
|
9353
|
+
*
|
|
9354
|
+
* Copyright (c) 2025, ArtGins.
|
|
9355
|
+
* All Rights Reserved.
|
|
9356
|
+
***********************************************************************/
|
|
9349
9357
|
/************************************************************
|
|
9350
9358
|
* Add class to elements selected
|
|
9351
9359
|
************************************************************/
|
|
@@ -9461,6 +9469,23 @@ function getStrokeColor(fillColor, theme = "light", factor = .2) {
|
|
|
9461
9469
|
const adjust = (v) => lighten ? Math.min(255, Math.floor(v + (255 - v) * factor)) : Math.max(0, Math.floor(v * (1 - factor)));
|
|
9462
9470
|
return `rgba(${adjust(r)}, ${adjust(g)}, ${adjust(b)}, ${a.toFixed(3)})`;
|
|
9463
9471
|
}
|
|
9472
|
+
/************************************************************
|
|
9473
|
+
* Returns the proportional position (between 0 and 1) of a specific point,
|
|
9474
|
+
* centered and spaced with margins.
|
|
9475
|
+
*
|
|
9476
|
+
* index - Index of the point (0 to count-1)
|
|
9477
|
+
* count - Total number of points
|
|
9478
|
+
* margin - Total margin space (default 0.2 means 10% on each end)
|
|
9479
|
+
************************************************************/
|
|
9480
|
+
function getPointPosition(count, index, margin = .2) {
|
|
9481
|
+
if (count <= 0 || index < 0 || index >= count) {
|
|
9482
|
+
log_error("Invalid count or index");
|
|
9483
|
+
return .5;
|
|
9484
|
+
}
|
|
9485
|
+
const start = margin / 2;
|
|
9486
|
+
const step = (1 - margin / 2 - start) / count;
|
|
9487
|
+
return start + index * step + step / 2;
|
|
9488
|
+
}
|
|
9464
9489
|
//#endregion
|
|
9465
9490
|
//#region src/yui_graph_camera.js
|
|
9466
9491
|
/***********************************************************************
|
|
@@ -10929,6 +10954,16 @@ function build_graph$3(gobj) {
|
|
|
10929
10954
|
}
|
|
10930
10955
|
}
|
|
10931
10956
|
/************************************************************
|
|
10957
|
+
* The port a container key opens on its card.
|
|
10958
|
+
*
|
|
10959
|
+
* Prefixed so it can never collide with anything G6 puts in
|
|
10960
|
+
* the same namespace, and stringified because an array index
|
|
10961
|
+
* is a number and a port key is a string.
|
|
10962
|
+
************************************************************/
|
|
10963
|
+
function port_key(key) {
|
|
10964
|
+
return "p_" + String(key);
|
|
10965
|
+
}
|
|
10966
|
+
/************************************************************
|
|
10932
10967
|
* Build cell value HTML (matching old mx_json_viewer colors)
|
|
10933
10968
|
************************************************************/
|
|
10934
10969
|
function build_cell_html(key, value, type, dark, matched, fold) {
|
|
@@ -10991,6 +11026,8 @@ function build_cell_html(key, value, type, dark, matched, fold) {
|
|
|
10991
11026
|
* forever. `+3` and `−` need no language.
|
|
10992
11027
|
************************************************************/
|
|
10993
11028
|
var FOLD_SPACER = `<span style="width:24px; flex:0 0 auto;"></span>`;
|
|
11029
|
+
var CARD_HEADER_H$1 = 24;
|
|
11030
|
+
var CARD_ROW_H$1 = 22;
|
|
10994
11031
|
function fold_toggle_html(path, foldable, folded, branches, colors) {
|
|
10995
11032
|
if (!foldable) return FOLD_SPACER;
|
|
10996
11033
|
let label = folded ? "+" + branches : "−";
|
|
@@ -11071,7 +11108,7 @@ function get_group_label(path) {
|
|
|
11071
11108
|
/************************************************************
|
|
11072
11109
|
* Recursively build nodes and edges from JSON
|
|
11073
11110
|
************************************************************/
|
|
11074
|
-
function build_json_nodes(gobj, path, kw, nodes, edges, parent_id) {
|
|
11111
|
+
function build_json_nodes(gobj, path, kw, nodes, edges, parent_id, parent_port) {
|
|
11075
11112
|
let group_id = gen_node_id$1(gobj);
|
|
11076
11113
|
let is_dict = is_object(kw);
|
|
11077
11114
|
let is_list = is_array(kw);
|
|
@@ -11095,7 +11132,9 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id) {
|
|
|
11095
11132
|
if (has_branch(value)) {
|
|
11096
11133
|
pending_complex.push({
|
|
11097
11134
|
key,
|
|
11098
|
-
value
|
|
11135
|
+
value,
|
|
11136
|
+
port: port_key(key),
|
|
11137
|
+
row: lines.length
|
|
11099
11138
|
});
|
|
11100
11139
|
if (is_pure_collection(value)) {
|
|
11101
11140
|
let child_path = add_segment(path, key);
|
|
@@ -11111,7 +11150,7 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id) {
|
|
|
11111
11150
|
}
|
|
11112
11151
|
if (parent_id && is_pure_collection(kw)) {
|
|
11113
11152
|
if (priv.collapsed.has(path)) return parent_id;
|
|
11114
|
-
for (let pending of pending_complex) build_json_nodes(gobj, add_segment(path, pending.key), pending.value, nodes, edges, parent_id);
|
|
11153
|
+
for (let pending of pending_complex) build_json_nodes(gobj, add_segment(path, pending.key), pending.value, nodes, edges, parent_id, parent_port);
|
|
11115
11154
|
return parent_id;
|
|
11116
11155
|
}
|
|
11117
11156
|
let label = get_group_label(path) || (is_dict ? "{}" : "[]");
|
|
@@ -11121,6 +11160,7 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id) {
|
|
|
11121
11160
|
let border_width = card_matched ? 2 : 1;
|
|
11122
11161
|
let content_html = lines.map((line) => `<div style="font-family:monospace; font-size:13px; padding:1px 6px; white-space:nowrap;">${line}</div>`).join("");
|
|
11123
11162
|
let min_width = Math.max(180, label.length * 9);
|
|
11163
|
+
let card_height = CARD_HEADER_H$1 + lines.length * CARD_ROW_H$1;
|
|
11124
11164
|
let node_html = `
|
|
11125
11165
|
<div style="
|
|
11126
11166
|
min-width: ${min_width}px;
|
|
@@ -11142,6 +11182,17 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id) {
|
|
|
11142
11182
|
">${FOLD_SPACER}<span style="flex:1 1 auto; text-align:center;">${escapeHtml(label)}</span>${fold_toggle_html(path, foldable, folded, pending_complex.length, colors)}</div>
|
|
11143
11183
|
${content_html}
|
|
11144
11184
|
</div>`;
|
|
11185
|
+
let ports = [];
|
|
11186
|
+
for (let pending of pending_complex) {
|
|
11187
|
+
let child_colors = json_card_style(is_object(pending.value) ? GROUP_COLORS.dict : GROUP_COLORS.list, dark);
|
|
11188
|
+
let row_mid = CARD_HEADER_H$1 + pending.row * CARD_ROW_H$1 + CARD_ROW_H$1 / 2;
|
|
11189
|
+
ports.push({
|
|
11190
|
+
key: pending.port,
|
|
11191
|
+
placement: [1, row_mid / card_height],
|
|
11192
|
+
fill: child_colors.border,
|
|
11193
|
+
stroke: colors.border
|
|
11194
|
+
});
|
|
11195
|
+
}
|
|
11145
11196
|
let node = {
|
|
11146
11197
|
id: group_id,
|
|
11147
11198
|
type: "html",
|
|
@@ -11151,22 +11202,30 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id) {
|
|
|
11151
11202
|
},
|
|
11152
11203
|
style: {
|
|
11153
11204
|
innerHTML: node_html,
|
|
11154
|
-
size: [min_width,
|
|
11205
|
+
size: [min_width, card_height],
|
|
11155
11206
|
dx: -(min_width / 2),
|
|
11156
|
-
dy: -(
|
|
11207
|
+
dy: -(card_height / 2),
|
|
11208
|
+
port: ports.length > 0,
|
|
11209
|
+
ports,
|
|
11210
|
+
portR: 4,
|
|
11211
|
+
portLineWidth: 1
|
|
11157
11212
|
}
|
|
11158
11213
|
};
|
|
11159
11214
|
nodes.push(node);
|
|
11160
|
-
if (parent_id)
|
|
11161
|
-
|
|
11162
|
-
|
|
11163
|
-
|
|
11164
|
-
|
|
11165
|
-
|
|
11166
|
-
|
|
11167
|
-
|
|
11215
|
+
if (parent_id) {
|
|
11216
|
+
let edge = {
|
|
11217
|
+
source: parent_id,
|
|
11218
|
+
target: group_id,
|
|
11219
|
+
style: {
|
|
11220
|
+
stroke: colors.border,
|
|
11221
|
+
lineWidth: 1
|
|
11222
|
+
}
|
|
11223
|
+
};
|
|
11224
|
+
if (parent_port) edge.style.sourcePort = parent_port;
|
|
11225
|
+
edges.push(edge);
|
|
11226
|
+
}
|
|
11168
11227
|
if (folded) return group_id;
|
|
11169
|
-
for (let pending of pending_complex) build_json_nodes(gobj, add_segment(path, pending.key), pending.value, nodes, edges, group_id);
|
|
11228
|
+
for (let pending of pending_complex) build_json_nodes(gobj, add_segment(path, pending.key), pending.value, nodes, edges, group_id, pending.port);
|
|
11170
11229
|
return group_id;
|
|
11171
11230
|
}
|
|
11172
11231
|
/************************************************************
|
|
@@ -49019,43 +49078,6 @@ function configure_behaviour(gobj) {
|
|
|
49019
49078
|
graph_write_behaviors(gobj, behaviors);
|
|
49020
49079
|
}
|
|
49021
49080
|
/************************************************************
|
|
49022
|
-
* Returns the proportional position (between 0 and 1) of a specific point,
|
|
49023
|
-
* centered and spaced with margins.
|
|
49024
|
-
*
|
|
49025
|
-
* index - Index of the point (0 to count-1)
|
|
49026
|
-
* count - Total number of points
|
|
49027
|
-
* margin - Total margin space (default 0.2 means 10% on each end)
|
|
49028
|
-
************************************************************/
|
|
49029
|
-
function getPointPosition(count, index, margin = .2) {
|
|
49030
|
-
if (count <= 0 || index < 0 || index >= count) {
|
|
49031
|
-
log_error("Invalid count or index");
|
|
49032
|
-
return .5;
|
|
49033
|
-
}
|
|
49034
|
-
const start = margin / 2;
|
|
49035
|
-
const step = (1 - margin / 2 - start) / count;
|
|
49036
|
-
return start + index * step + step / 2;
|
|
49037
|
-
}
|
|
49038
|
-
/************************************************************
|
|
49039
|
-
* Count hooks and fkeys in topic desc, classify node type
|
|
49040
|
-
************************************************************/
|
|
49041
|
-
function calculate_hooks_fkeys_counter(desc) {
|
|
49042
|
-
let cols = desc.cols;
|
|
49043
|
-
desc.hooks_counter = 0;
|
|
49044
|
-
desc.fkeys_counter = 0;
|
|
49045
|
-
for (let i = 0; i < cols.length; i++) {
|
|
49046
|
-
let col = cols[i];
|
|
49047
|
-
switch (treedb_get_field_desc(col).type) {
|
|
49048
|
-
case "hook":
|
|
49049
|
-
desc.hooks_counter++;
|
|
49050
|
-
break;
|
|
49051
|
-
case "fkey": desc.fkeys_counter++;
|
|
49052
|
-
}
|
|
49053
|
-
}
|
|
49054
|
-
if (desc.hooks_counter === 0) desc.node_treedb_type = "child";
|
|
49055
|
-
else if (desc.fkeys_counter === 0) desc.node_treedb_type = "extended";
|
|
49056
|
-
else desc.node_treedb_type = "hierarchical";
|
|
49057
|
-
}
|
|
49058
|
-
/************************************************************
|
|
49059
49081
|
* Build ports for a topic desc
|
|
49060
49082
|
************************************************************/
|
|
49061
49083
|
function build_ports(gobj, desc) {
|
package/package.json
CHANGED
package/src/c_g6_nodes_tree.js
CHANGED
|
@@ -80,6 +80,7 @@ import {
|
|
|
80
80
|
set_cancel_state,
|
|
81
81
|
set_active_state,
|
|
82
82
|
set_pressed_state,
|
|
83
|
+
getPointPosition,
|
|
83
84
|
getStrokeColor,
|
|
84
85
|
} from "./lib_graph.js";
|
|
85
86
|
|
|
@@ -1598,59 +1599,6 @@ function configure_behaviour(gobj)
|
|
|
1598
1599
|
graph_write_behaviors(gobj, behaviors);
|
|
1599
1600
|
}
|
|
1600
1601
|
|
|
1601
|
-
/************************************************************
|
|
1602
|
-
* Returns the proportional position (between 0 and 1) of a specific point,
|
|
1603
|
-
* centered and spaced with margins.
|
|
1604
|
-
*
|
|
1605
|
-
* index - Index of the point (0 to count-1)
|
|
1606
|
-
* count - Total number of points
|
|
1607
|
-
* margin - Total margin space (default 0.2 means 10% on each end)
|
|
1608
|
-
************************************************************/
|
|
1609
|
-
function getPointPosition(count, index, margin = 0.2)
|
|
1610
|
-
{
|
|
1611
|
-
if(count <= 0 || index < 0 || index >= count) {
|
|
1612
|
-
log_error("Invalid count or index");
|
|
1613
|
-
return 0.5;
|
|
1614
|
-
}
|
|
1615
|
-
|
|
1616
|
-
const start = margin / 2;
|
|
1617
|
-
const end = 1 - margin / 2;
|
|
1618
|
-
const step = (end - start) / count;
|
|
1619
|
-
|
|
1620
|
-
return start + index * step + step / 2;
|
|
1621
|
-
}
|
|
1622
|
-
|
|
1623
|
-
/************************************************************
|
|
1624
|
-
* Count hooks and fkeys in topic desc, classify node type
|
|
1625
|
-
************************************************************/
|
|
1626
|
-
function calculate_hooks_fkeys_counter(desc)
|
|
1627
|
-
{
|
|
1628
|
-
let cols = desc.cols;
|
|
1629
|
-
desc.hooks_counter = 0;
|
|
1630
|
-
desc.fkeys_counter = 0;
|
|
1631
|
-
|
|
1632
|
-
for(let i=0; i<cols.length; i++) {
|
|
1633
|
-
let col = cols[i];
|
|
1634
|
-
const field_desc = treedb_get_field_desc(col);
|
|
1635
|
-
switch(field_desc.type) {
|
|
1636
|
-
case "hook":
|
|
1637
|
-
desc.hooks_counter++;
|
|
1638
|
-
break;
|
|
1639
|
-
case "fkey":
|
|
1640
|
-
desc.fkeys_counter++;
|
|
1641
|
-
break;
|
|
1642
|
-
}
|
|
1643
|
-
}
|
|
1644
|
-
|
|
1645
|
-
if(desc.hooks_counter === 0) {
|
|
1646
|
-
desc.node_treedb_type = 'child';
|
|
1647
|
-
} else if(desc.fkeys_counter === 0) {
|
|
1648
|
-
desc.node_treedb_type = 'extended';
|
|
1649
|
-
} else {
|
|
1650
|
-
desc.node_treedb_type = 'hierarchical';
|
|
1651
|
-
}
|
|
1652
|
-
}
|
|
1653
|
-
|
|
1654
1602
|
/************************************************************
|
|
1655
1603
|
* Build ports for a topic desc
|
|
1656
1604
|
************************************************************/
|
package/src/c_yui_json_graph.js
CHANGED
|
@@ -772,6 +772,18 @@ function build_graph(gobj)
|
|
|
772
772
|
}
|
|
773
773
|
}
|
|
774
774
|
|
|
775
|
+
/************************************************************
|
|
776
|
+
* The port a container key opens on its card.
|
|
777
|
+
*
|
|
778
|
+
* Prefixed so it can never collide with anything G6 puts in
|
|
779
|
+
* the same namespace, and stringified because an array index
|
|
780
|
+
* is a number and a port key is a string.
|
|
781
|
+
************************************************************/
|
|
782
|
+
function port_key(key)
|
|
783
|
+
{
|
|
784
|
+
return "p_" + String(key);
|
|
785
|
+
}
|
|
786
|
+
|
|
775
787
|
/************************************************************
|
|
776
788
|
* Build cell value HTML (matching old mx_json_viewer colors)
|
|
777
789
|
************************************************************/
|
|
@@ -872,6 +884,20 @@ function build_cell_html(key, value, type, dark, matched, fold)
|
|
|
872
884
|
************************************************************/
|
|
873
885
|
const FOLD_SPACER = `<span style="width:24px; flex:0 0 auto;"></span>`;
|
|
874
886
|
|
|
887
|
+
/*
|
|
888
|
+
* The card's geometry, in ONE place.
|
|
889
|
+
*
|
|
890
|
+
* A container key's port is placed by computing WHICH ROW it is, so a
|
|
891
|
+
* row height changed in the markup and not here would slide every port
|
|
892
|
+
* off the line it belongs to -- silently, because nothing would fail:
|
|
893
|
+
* the dots would just stop pointing at anything.
|
|
894
|
+
*
|
|
895
|
+
* These are the rendered heights of the header (`padding: 3px 8px` on
|
|
896
|
+
* 12px bold) and of one body row (`padding: 1px 6px` on 13px monospace).
|
|
897
|
+
*/
|
|
898
|
+
const CARD_HEADER_H = 24;
|
|
899
|
+
const CARD_ROW_H = 22;
|
|
900
|
+
|
|
875
901
|
function fold_toggle_html(path, foldable, folded, branches, colors)
|
|
876
902
|
{
|
|
877
903
|
if(!foldable) {
|
|
@@ -981,7 +1007,7 @@ function get_group_label(path)
|
|
|
981
1007
|
/************************************************************
|
|
982
1008
|
* Recursively build nodes and edges from JSON
|
|
983
1009
|
************************************************************/
|
|
984
|
-
function build_json_nodes(gobj, path, kw, nodes, edges, parent_id)
|
|
1010
|
+
function build_json_nodes(gobj, path, kw, nodes, edges, parent_id, parent_port)
|
|
985
1011
|
{
|
|
986
1012
|
let group_id = gen_node_id(gobj);
|
|
987
1013
|
let is_dict = is_object(kw);
|
|
@@ -1031,7 +1057,11 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id)
|
|
|
1031
1057
|
*/
|
|
1032
1058
|
let fold = null;
|
|
1033
1059
|
if(has_branch(value)) {
|
|
1034
|
-
|
|
1060
|
+
/* `lines.length` is the index the row of this entry is about
|
|
1061
|
+
* to take, and it is what puts the port on that line. */
|
|
1062
|
+
pending_complex.push({
|
|
1063
|
+
key: key, value: value, port: port_key(key), row: lines.length
|
|
1064
|
+
});
|
|
1035
1065
|
|
|
1036
1066
|
/*
|
|
1037
1067
|
* A child that gets no card of its own is folded from HERE
|
|
@@ -1062,13 +1092,21 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id)
|
|
|
1062
1092
|
return parent_id;
|
|
1063
1093
|
}
|
|
1064
1094
|
for(let pending of pending_complex) {
|
|
1095
|
+
/*
|
|
1096
|
+
* `parent_port` and not one of ours: this collection has no
|
|
1097
|
+
* card, so the port its row opened in the PARENT is the one
|
|
1098
|
+
* every one of these lines leaves from -- fourteen columns
|
|
1099
|
+
* out of the single `cols` port, which is what the document
|
|
1100
|
+
* says and what the reader traces back.
|
|
1101
|
+
*/
|
|
1065
1102
|
build_json_nodes(
|
|
1066
1103
|
gobj,
|
|
1067
1104
|
add_segment(path, pending.key),
|
|
1068
1105
|
pending.value,
|
|
1069
1106
|
nodes,
|
|
1070
1107
|
edges,
|
|
1071
|
-
parent_id
|
|
1108
|
+
parent_id,
|
|
1109
|
+
parent_port
|
|
1072
1110
|
);
|
|
1073
1111
|
}
|
|
1074
1112
|
return parent_id;
|
|
@@ -1097,6 +1135,7 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id)
|
|
|
1097
1135
|
).join("");
|
|
1098
1136
|
|
|
1099
1137
|
let min_width = Math.max(180, label.length * 9);
|
|
1138
|
+
let card_height = CARD_HEADER_H + lines.length * CARD_ROW_H;
|
|
1100
1139
|
|
|
1101
1140
|
let node_html = `
|
|
1102
1141
|
<div style="
|
|
@@ -1120,6 +1159,41 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id)
|
|
|
1120
1159
|
${content_html}
|
|
1121
1160
|
</div>`;
|
|
1122
1161
|
|
|
1162
|
+
/*
|
|
1163
|
+
* ONE PORT PER CONTAINER KEY, ON THE LINE OF ITS OWN ROW.
|
|
1164
|
+
*
|
|
1165
|
+
* Without ports each card was a single anchor: fourteen lines came
|
|
1166
|
+
* out of one point, and which row a line belonged to was a guess
|
|
1167
|
+
* the reader made from where it landed.
|
|
1168
|
+
*
|
|
1169
|
+
* Spread along the bottom edge they were distinguishable but still
|
|
1170
|
+
* not ATTACHED to anything -- the reader had to count dots, count
|
|
1171
|
+
* rows, and trust that the two orders matched. Placed at the row's
|
|
1172
|
+
* own height there is nothing to match: the line leaves from beside
|
|
1173
|
+
* the key it belongs to, which is the whole point of a port.
|
|
1174
|
+
*
|
|
1175
|
+
* On the RIGHT edge, and exactly ON it (`x = 1`) rather than inside:
|
|
1176
|
+
* an html node draws its HTML in a DOM layer above the canvas, so a
|
|
1177
|
+
* port fully inside the box would be painted under the card and
|
|
1178
|
+
* never seen. Half of it sticks out.
|
|
1179
|
+
*
|
|
1180
|
+
* Coloured by what the row LEADS TO -- a dict or a list -- which is
|
|
1181
|
+
* the one thing the port can say that the row does not.
|
|
1182
|
+
*/
|
|
1183
|
+
let ports = [];
|
|
1184
|
+
for(let pending of pending_complex) {
|
|
1185
|
+
let child_colors = json_card_style(
|
|
1186
|
+
is_object(pending.value)? GROUP_COLORS.dict: GROUP_COLORS.list, dark
|
|
1187
|
+
);
|
|
1188
|
+
let row_mid = CARD_HEADER_H + pending.row * CARD_ROW_H + CARD_ROW_H / 2;
|
|
1189
|
+
ports.push({
|
|
1190
|
+
key: pending.port,
|
|
1191
|
+
placement: [1, row_mid / card_height],
|
|
1192
|
+
fill: child_colors.border,
|
|
1193
|
+
stroke: colors.border,
|
|
1194
|
+
});
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1123
1197
|
let node = {
|
|
1124
1198
|
id: group_id,
|
|
1125
1199
|
type: 'html',
|
|
@@ -1129,25 +1203,33 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id)
|
|
|
1129
1203
|
},
|
|
1130
1204
|
style: {
|
|
1131
1205
|
innerHTML: node_html,
|
|
1132
|
-
size: [min_width,
|
|
1206
|
+
size: [min_width, card_height],
|
|
1133
1207
|
dx: -(min_width / 2),
|
|
1134
|
-
dy: -(
|
|
1208
|
+
dy: -(card_height / 2),
|
|
1209
|
+
port: ports.length > 0,
|
|
1210
|
+
ports: ports,
|
|
1211
|
+
portR: 4,
|
|
1212
|
+
portLineWidth: 1,
|
|
1135
1213
|
},
|
|
1136
1214
|
};
|
|
1137
1215
|
nodes.push(node);
|
|
1138
1216
|
|
|
1139
1217
|
/*
|
|
1140
|
-
* Edge from parent to this group
|
|
1218
|
+
* Edge from parent to this group, out of the port its key opened.
|
|
1141
1219
|
*/
|
|
1142
1220
|
if(parent_id) {
|
|
1143
|
-
|
|
1221
|
+
let edge = {
|
|
1144
1222
|
source: parent_id,
|
|
1145
1223
|
target: group_id,
|
|
1146
1224
|
style: {
|
|
1147
1225
|
stroke: colors.border,
|
|
1148
1226
|
lineWidth: 1,
|
|
1149
1227
|
}
|
|
1150
|
-
}
|
|
1228
|
+
};
|
|
1229
|
+
if(parent_port) {
|
|
1230
|
+
edge.style.sourcePort = parent_port;
|
|
1231
|
+
}
|
|
1232
|
+
edges.push(edge);
|
|
1151
1233
|
}
|
|
1152
1234
|
|
|
1153
1235
|
/*
|
|
@@ -1163,7 +1245,8 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id)
|
|
|
1163
1245
|
pending.value,
|
|
1164
1246
|
nodes,
|
|
1165
1247
|
edges,
|
|
1166
|
-
group_id
|
|
1248
|
+
group_id,
|
|
1249
|
+
pending.port
|
|
1167
1250
|
);
|
|
1168
1251
|
}
|
|
1169
1252
|
|
package/src/lib_graph.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
***********************************************************************/
|
|
9
9
|
import {
|
|
10
10
|
gobj_read_attr,
|
|
11
|
+
log_error,
|
|
11
12
|
} from "@yuneta/gobj-js";
|
|
12
13
|
|
|
13
14
|
// import {t} from "i18next";
|
|
@@ -195,6 +196,59 @@ function getStrokeColor(fillColor, theme = 'light', factor = 0.2) {
|
|
|
195
196
|
//=======================================================================
|
|
196
197
|
// Expose the class via the global object
|
|
197
198
|
//=======================================================================
|
|
199
|
+
/************************************************************
|
|
200
|
+
* Returns the proportional position (between 0 and 1) of a specific point,
|
|
201
|
+
* centered and spaced with margins.
|
|
202
|
+
*
|
|
203
|
+
* index - Index of the point (0 to count-1)
|
|
204
|
+
* count - Total number of points
|
|
205
|
+
* margin - Total margin space (default 0.2 means 10% on each end)
|
|
206
|
+
************************************************************/
|
|
207
|
+
function getPointPosition(count, index, margin = 0.2)
|
|
208
|
+
{
|
|
209
|
+
if(count <= 0 || index < 0 || index >= count) {
|
|
210
|
+
log_error("Invalid count or index");
|
|
211
|
+
return 0.5;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const start = margin / 2;
|
|
215
|
+
const end = 1 - margin / 2;
|
|
216
|
+
const step = (end - start) / count;
|
|
217
|
+
|
|
218
|
+
return start + index * step + step / 2;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/************************************************************
|
|
222
|
+
* Count hooks and fkeys in topic desc, classify node type
|
|
223
|
+
************************************************************/
|
|
224
|
+
function calculate_hooks_fkeys_counter(desc)
|
|
225
|
+
{
|
|
226
|
+
let cols = desc.cols;
|
|
227
|
+
desc.hooks_counter = 0;
|
|
228
|
+
desc.fkeys_counter = 0;
|
|
229
|
+
|
|
230
|
+
for(let i=0; i<cols.length; i++) {
|
|
231
|
+
let col = cols[i];
|
|
232
|
+
const field_desc = treedb_get_field_desc(col);
|
|
233
|
+
switch(field_desc.type) {
|
|
234
|
+
case "hook":
|
|
235
|
+
desc.hooks_counter++;
|
|
236
|
+
break;
|
|
237
|
+
case "fkey":
|
|
238
|
+
desc.fkeys_counter++;
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if(desc.hooks_counter === 0) {
|
|
244
|
+
desc.node_treedb_type = 'child';
|
|
245
|
+
} else if(desc.fkeys_counter === 0) {
|
|
246
|
+
desc.node_treedb_type = 'extended';
|
|
247
|
+
} else {
|
|
248
|
+
desc.node_treedb_type = 'hierarchical';
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
198
252
|
export {
|
|
199
253
|
addClasses,
|
|
200
254
|
removeClasses,
|
|
@@ -207,4 +261,5 @@ export {
|
|
|
207
261
|
set_active_state,
|
|
208
262
|
set_pressed_state,
|
|
209
263
|
getStrokeColor,
|
|
264
|
+
getPointPosition,
|
|
210
265
|
};
|