@yuneta/gobj-ui 7.23.67 → 7.23.68
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 +57 -0
- package/dist/gobj-ui.cjs.js +438 -84
- package/dist/gobj-ui.es.js +439 -85
- package/package.json +1 -1
- package/src/c_g6_nodes_tree.js +146 -8
- package/src/c_yui_treedb_graph.js +261 -80
- package/src/treedb_fold_model.js +171 -15
- package/src/treedb_fold_model.test.js +120 -2
package/package.json
CHANGED
package/src/c_g6_nodes_tree.js
CHANGED
|
@@ -341,6 +341,9 @@ SDATA(data_type_t.DTP_STRING, "fkey_port_position", 0, "top", "Fkey po
|
|
|
341
341
|
/*---------------- Folding ----------------*/
|
|
342
342
|
SDATA(data_type_t.DTP_INTEGER, "expand_depth", 0, 2, "Levels open when a treedb loads: 1 = the roots alone, 2 = the roots and their children. Every open hook shows its first page"),
|
|
343
343
|
SDATA(data_type_t.DTP_INTEGER, "fold_page_size", 0, 24, "Children of one hook shown per page; the `+N` chip after the page opens the next one"),
|
|
344
|
+
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"),
|
|
345
|
+
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"),
|
|
346
|
+
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"),
|
|
344
347
|
SDATA(data_type_t.DTP_BOOLEAN, "confirm_delete_node", 0, true, "Ask confirmation before deleting a node"),
|
|
345
348
|
SDATA(data_type_t.DTP_BOOLEAN, "confirm_unlink_edge", 0, true, "Ask confirmation before unlinking an edge"),
|
|
346
349
|
|
|
@@ -421,6 +424,7 @@ let PRIVATE_DATA = {
|
|
|
421
424
|
// it exists to diff the repaint)
|
|
422
425
|
_pending_focus_topic: null, // focus requested before data was loaded
|
|
423
426
|
_pending_focus_all: false, // ...and whether it reveals the whole topic
|
|
427
|
+
_find_hidden_matches: 0, // matches of the last find in HIDDEN topics
|
|
424
428
|
_pending_find: null, // find requested before data was loaded
|
|
425
429
|
_layout_asked: "", // layout the host asked for at create (see mt_create)
|
|
426
430
|
_nodes_total: 0, // records of the treedb (auto_layout)
|
|
@@ -429,6 +433,9 @@ let PRIVATE_DATA = {
|
|
|
429
433
|
/*---------------- folding ----------------*/
|
|
430
434
|
expand_depth: 2,
|
|
431
435
|
fold_page_size: 24,
|
|
436
|
+
hidden_topics: null,
|
|
437
|
+
main_topic: "",
|
|
438
|
+
loose_topics: null,
|
|
432
439
|
_fold_model: null, // treedb_fold_model: the tree of the records
|
|
433
440
|
_fold_state: null, // ...and which groups of it are open
|
|
434
441
|
_fold_listener: null, // delegated click on the card pills
|
|
@@ -2992,27 +2999,40 @@ function graph_find_nodes(gobj, term)
|
|
|
2992
2999
|
* folded away, and a find that only read what was on screen would
|
|
2993
3000
|
* answer "nothing" for a device three levels down. */
|
|
2994
3001
|
let keys = [];
|
|
3002
|
+
let hidden_matches = 0;
|
|
2995
3003
|
if(!empty_string(term)) {
|
|
2996
3004
|
let needle = String(term).toLowerCase();
|
|
2997
|
-
|
|
2998
|
-
let record = node.record || {};
|
|
3005
|
+
let matches = (topic_name, record) => {
|
|
2999
3006
|
let label = "";
|
|
3000
3007
|
try {
|
|
3001
|
-
label = node_label(priv.descs[
|
|
3008
|
+
label = node_label(priv.descs[topic_name] || {}, record) || "";
|
|
3002
3009
|
} catch(e) {
|
|
3003
3010
|
label = "";
|
|
3004
3011
|
}
|
|
3005
3012
|
let haystack = [
|
|
3006
3013
|
label,
|
|
3007
3014
|
record.id,
|
|
3008
|
-
|
|
3015
|
+
topic_name
|
|
3009
3016
|
].filter((v) => typeof v === "string").join(" ").toLowerCase();
|
|
3010
|
-
|
|
3011
|
-
|
|
3017
|
+
return haystack.includes(needle);
|
|
3018
|
+
};
|
|
3019
|
+
for(let node of model.nodes.values()) {
|
|
3020
|
+
if(matches(node.topic_name, node.record || {})) {
|
|
3012
3021
|
keys.push(node.key);
|
|
3013
3022
|
}
|
|
3014
3023
|
}
|
|
3024
|
+
/* A hidden topic is searched too, and COUNTED apart: a term
|
|
3025
|
+
* that only matches there would otherwise answer "0", which
|
|
3026
|
+
* reads as "does not exist" when it means "is hidden". */
|
|
3027
|
+
for(let topic_name of model.hidden) {
|
|
3028
|
+
for(let record of (priv.records[topic_name] || [])) {
|
|
3029
|
+
if(is_object(record) && matches(topic_name, record)) {
|
|
3030
|
+
hidden_matches++;
|
|
3031
|
+
}
|
|
3032
|
+
}
|
|
3033
|
+
}
|
|
3015
3034
|
}
|
|
3035
|
+
priv._find_hidden_matches = hidden_matches;
|
|
3016
3036
|
|
|
3017
3037
|
/* Hidden matches are opened up to, one page of them at most: a
|
|
3018
3038
|
* single letter matches half the treedb, and unfolding half the
|
|
@@ -7536,7 +7556,11 @@ function rebuild_fold_model(gobj)
|
|
|
7536
7556
|
{
|
|
7537
7557
|
let priv = gobj.priv;
|
|
7538
7558
|
|
|
7539
|
-
priv._fold_model = fold_build_model(priv.descs || {}, priv.records || {}
|
|
7559
|
+
priv._fold_model = fold_build_model(priv.descs || {}, priv.records || {}, {
|
|
7560
|
+
hidden_topics: gobj_read_attr(gobj, "hidden_topics") || [],
|
|
7561
|
+
main_topic: gobj_read_str_attr(gobj, "main_topic") || "",
|
|
7562
|
+
loose_topics: gobj_read_attr(gobj, "loose_topics") || [],
|
|
7563
|
+
});
|
|
7540
7564
|
if(!priv._fold_state) {
|
|
7541
7565
|
priv._fold_state = fold_new_state(gobj_read_integer_attr(gobj, "fold_page_size"));
|
|
7542
7566
|
}
|
|
@@ -7622,9 +7646,60 @@ async function reconcile_fold_now(gobj, opts)
|
|
|
7622
7646
|
} finally {
|
|
7623
7647
|
history_resume(gobj);
|
|
7624
7648
|
}
|
|
7649
|
+
publish_legend_state(gobj, visible);
|
|
7625
7650
|
return changed;
|
|
7626
7651
|
}
|
|
7627
7652
|
|
|
7653
|
+
/************************************************************
|
|
7654
|
+
* What the legend has to say, published after every reconcile:
|
|
7655
|
+
* one entry per topic of the treedb, hidden ones included, with
|
|
7656
|
+
* its colour, how many records it has, how many are on screen,
|
|
7657
|
+
* how many are LOOSE, and the flags -- plus which topic is the
|
|
7658
|
+
* main one and whether it was deduced or chosen. The host draws
|
|
7659
|
+
* the strip from this and nothing else; the engine is the truth.
|
|
7660
|
+
************************************************************/
|
|
7661
|
+
function publish_legend_state(gobj, visible)
|
|
7662
|
+
{
|
|
7663
|
+
let priv = gobj.priv;
|
|
7664
|
+
let model = priv._fold_model;
|
|
7665
|
+
|
|
7666
|
+
if(!model || !priv.descs) {
|
|
7667
|
+
return;
|
|
7668
|
+
}
|
|
7669
|
+
|
|
7670
|
+
let on_screen = {};
|
|
7671
|
+
for(let key of visible) {
|
|
7672
|
+
let node = model.nodes.get(key);
|
|
7673
|
+
if(node) {
|
|
7674
|
+
on_screen[node.topic_name] = (on_screen[node.topic_name] || 0) + 1;
|
|
7675
|
+
}
|
|
7676
|
+
}
|
|
7677
|
+
|
|
7678
|
+
let topics = [];
|
|
7679
|
+
for(const [topic_name, desc] of Object.entries(priv.descs)) {
|
|
7680
|
+
if(topic_name.substring(0, 2) === "__" || !desc) {
|
|
7681
|
+
continue;
|
|
7682
|
+
}
|
|
7683
|
+
let loose = model.loose[topic_name] || [];
|
|
7684
|
+
topics.push({
|
|
7685
|
+
topic: topic_name,
|
|
7686
|
+
color: desc.color || "",
|
|
7687
|
+
total: model.totals[topic_name] || 0,
|
|
7688
|
+
visible: on_screen[topic_name] || 0,
|
|
7689
|
+
loose: loose.length,
|
|
7690
|
+
loose_shown: model.loose_shown.has(topic_name),
|
|
7691
|
+
hidden: model.hidden.has(topic_name),
|
|
7692
|
+
linked: model.linked.has(topic_name),
|
|
7693
|
+
});
|
|
7694
|
+
}
|
|
7695
|
+
|
|
7696
|
+
gobj_publish_event(gobj, "EV_LEGEND_STATE", {
|
|
7697
|
+
main_topic: model.main_topic,
|
|
7698
|
+
main_chosen: !!gobj_read_str_attr(gobj, "main_topic"),
|
|
7699
|
+
topics: topics,
|
|
7700
|
+
});
|
|
7701
|
+
}
|
|
7702
|
+
|
|
7628
7703
|
async function reconcile_fold_apply(gobj, opts, visible)
|
|
7629
7704
|
{
|
|
7630
7705
|
let priv = gobj.priv;
|
|
@@ -8627,6 +8702,58 @@ function ac_collapse_all(gobj, event, kw, src)
|
|
|
8627
8702
|
return 0;
|
|
8628
8703
|
}
|
|
8629
8704
|
|
|
8705
|
+
/************************************************************
|
|
8706
|
+
* The legend's three settings, from the host, which persists
|
|
8707
|
+
* them. Each rebuilds the tree; the fold state is kept -- it is
|
|
8708
|
+
* keyed by group, and a group that is gone is never read -- except
|
|
8709
|
+
* for a new MAIN topic, whose roots are other roots: the tree
|
|
8710
|
+
* opens again at `expand_depth`.
|
|
8711
|
+
************************************************************/
|
|
8712
|
+
function ac_set_hidden_topics(gobj, event, kw, src)
|
|
8713
|
+
{
|
|
8714
|
+
let priv = gobj.priv;
|
|
8715
|
+
let topics = (kw && is_array(kw.topics))? kw.topics : [];
|
|
8716
|
+
|
|
8717
|
+
gobj_write_attr(gobj, "hidden_topics", topics);
|
|
8718
|
+
if(!priv._fold_model) {
|
|
8719
|
+
return 0; /* applied when the records arrive */
|
|
8720
|
+
}
|
|
8721
|
+
rebuild_fold_model(gobj);
|
|
8722
|
+
reconcile_fold(gobj, {});
|
|
8723
|
+
return 0;
|
|
8724
|
+
}
|
|
8725
|
+
|
|
8726
|
+
function ac_set_main_topic(gobj, event, kw, src)
|
|
8727
|
+
{
|
|
8728
|
+
let priv = gobj.priv;
|
|
8729
|
+
|
|
8730
|
+
gobj_write_str_attr(gobj, "main_topic", (kw && kw.topic) || "");
|
|
8731
|
+
if(!priv._fold_model) {
|
|
8732
|
+
return 0;
|
|
8733
|
+
}
|
|
8734
|
+
rebuild_fold_model(gobj);
|
|
8735
|
+
fold_expand_to_depth(
|
|
8736
|
+
priv._fold_model, priv._fold_state,
|
|
8737
|
+
gobj_read_integer_attr(gobj, "expand_depth")
|
|
8738
|
+
);
|
|
8739
|
+
reconcile_fold(gobj, {relayout: true, fit: true});
|
|
8740
|
+
return 0;
|
|
8741
|
+
}
|
|
8742
|
+
|
|
8743
|
+
function ac_set_loose_topics(gobj, event, kw, src)
|
|
8744
|
+
{
|
|
8745
|
+
let priv = gobj.priv;
|
|
8746
|
+
let topics = (kw && is_array(kw.topics))? kw.topics : [];
|
|
8747
|
+
|
|
8748
|
+
gobj_write_attr(gobj, "loose_topics", topics);
|
|
8749
|
+
if(!priv._fold_model) {
|
|
8750
|
+
return 0;
|
|
8751
|
+
}
|
|
8752
|
+
rebuild_fold_model(gobj);
|
|
8753
|
+
reconcile_fold(gobj, {});
|
|
8754
|
+
return 0;
|
|
8755
|
+
}
|
|
8756
|
+
|
|
8630
8757
|
/************************************************************
|
|
8631
8758
|
* Tell whoever asked how many nodes the term matched. The count is
|
|
8632
8759
|
* the answer to the question the box asks; without it "nothing moved"
|
|
@@ -8634,7 +8761,11 @@ function ac_collapse_all(gobj, event, kw, src)
|
|
|
8634
8761
|
************************************************************/
|
|
8635
8762
|
function publish_find_result(gobj, term, matches)
|
|
8636
8763
|
{
|
|
8637
|
-
gobj_publish_event(gobj, "EV_FIND_RESULT", {
|
|
8764
|
+
gobj_publish_event(gobj, "EV_FIND_RESULT", {
|
|
8765
|
+
term: term,
|
|
8766
|
+
matches: matches,
|
|
8767
|
+
hidden_matches: gobj.priv._find_hidden_matches || 0,
|
|
8768
|
+
});
|
|
8638
8769
|
}
|
|
8639
8770
|
|
|
8640
8771
|
/************************************************************
|
|
@@ -9184,6 +9315,9 @@ function create_gclass(gclass_name)
|
|
|
9184
9315
|
["EV_SHOW_MORE", ac_show_more, null],
|
|
9185
9316
|
["EV_EXPAND_ALL", ac_expand_all, null],
|
|
9186
9317
|
["EV_COLLAPSE_ALL", ac_collapse_all, null],
|
|
9318
|
+
["EV_SET_HIDDEN_TOPICS", ac_set_hidden_topics, null],
|
|
9319
|
+
["EV_SET_MAIN_TOPIC", ac_set_main_topic, null],
|
|
9320
|
+
["EV_SET_LOOSE_TOPICS", ac_set_loose_topics, null],
|
|
9187
9321
|
["EV_CENTER", ac_center, null],
|
|
9188
9322
|
["EV_FULLSCREEN", ac_fullscreen, null],
|
|
9189
9323
|
["EV_SET_LAYOUT", ac_set_layout, null],
|
|
@@ -9241,6 +9375,10 @@ function create_gclass(gclass_name)
|
|
|
9241
9375
|
["EV_SHOW_MORE", 0],
|
|
9242
9376
|
["EV_EXPAND_ALL", 0],
|
|
9243
9377
|
["EV_COLLAPSE_ALL", 0],
|
|
9378
|
+
["EV_SET_HIDDEN_TOPICS", 0],
|
|
9379
|
+
["EV_SET_MAIN_TOPIC", 0],
|
|
9380
|
+
["EV_SET_LOOSE_TOPICS", 0],
|
|
9381
|
+
["EV_LEGEND_STATE", event_flag_t.EVF_OUTPUT_EVENT],
|
|
9244
9382
|
["EV_CENTER", 0],
|
|
9245
9383
|
["EV_FULLSCREEN", 0],
|
|
9246
9384
|
["EV_SET_LAYOUT", 0],
|