@yuneta/gobj-ui 7.4.4 → 7.5.0
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 +97 -26
- package/dist/gobj-ui.es.js +97 -26
- package/package.json +1 -1
- package/src/c_g6_nodes_tree.js +96 -26
- package/src/c_yui_treedb_graph.js +23 -0
package/dist/gobj-ui.cjs.js
CHANGED
|
@@ -19971,6 +19971,21 @@ function ac_legend_topic(gobj, event, kw, src) {
|
|
|
19971
19971
|
return 0;
|
|
19972
19972
|
}
|
|
19973
19973
|
/************************************************************
|
|
19974
|
+
* The child chose a layout for a treedb nobody has arranged yet.
|
|
19975
|
+
* Only the SELECT is moved: the pick is a default, not the user's
|
|
19976
|
+
* choice, so it is not persisted — the day somebody drags a node the
|
|
19977
|
+
* saved geometry exists and `manual` is right again.
|
|
19978
|
+
************************************************************/
|
|
19979
|
+
function ac_layout_autoset(gobj, event, kw, src) {
|
|
19980
|
+
let $container = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
|
|
19981
|
+
if (!$container) return 0;
|
|
19982
|
+
let $select = $container.querySelector(".GRAPH_LAYOUT_SELECT");
|
|
19983
|
+
let layout = kw && kw.layout || "";
|
|
19984
|
+
if (!$select || !layout) return 0;
|
|
19985
|
+
$select.value = layout;
|
|
19986
|
+
return 0;
|
|
19987
|
+
}
|
|
19988
|
+
/************************************************************
|
|
19974
19989
|
* Forward the find down to the graph child.
|
|
19975
19990
|
************************************************************/
|
|
19976
19991
|
function ac_find_nodes$1(gobj, event, kw, src) {
|
|
@@ -20171,6 +20186,11 @@ function create_gclass$4(gclass_name) {
|
|
|
20171
20186
|
ac_find_nodes$1,
|
|
20172
20187
|
null
|
|
20173
20188
|
],
|
|
20189
|
+
[
|
|
20190
|
+
"EV_LAYOUT_AUTOSET",
|
|
20191
|
+
ac_layout_autoset,
|
|
20192
|
+
null
|
|
20193
|
+
],
|
|
20174
20194
|
[
|
|
20175
20195
|
"EV_TOGGLE_LEGEND",
|
|
20176
20196
|
ac_toggle_legend,
|
|
@@ -20229,6 +20249,7 @@ function create_gclass$4(gclass_name) {
|
|
|
20229
20249
|
["EV_SET_FOCUS_TOPIC", 0],
|
|
20230
20250
|
["EV_FIND_NODES", 0],
|
|
20231
20251
|
["EV_FIND_RESULT", 0],
|
|
20252
|
+
["EV_LAYOUT_AUTOSET", 0],
|
|
20232
20253
|
["EV_TOGGLE_LEGEND", 0],
|
|
20233
20254
|
["EV_LEGEND_TOPIC", 0],
|
|
20234
20255
|
["EV_TOPIC_SELECTED", _yuneta_gobj_js.event_flag_t.EVF_OUTPUT_EVENT | _yuneta_gobj_js.event_flag_t.EVF_NO_WARN_SUBS],
|
|
@@ -55678,6 +55699,55 @@ function show_node_detail_popover(gobj, node_id) {
|
|
|
55678
55699
|
* junction diamonds get their neutral fill/stroke re-themed.
|
|
55679
55700
|
************************************************************/
|
|
55680
55701
|
/************************************************************
|
|
55702
|
+
* Has anybody ever PLACED a node of this treedb?
|
|
55703
|
+
*
|
|
55704
|
+
* Saved positions live in `__graphs__` (per topic, per node) and, on
|
|
55705
|
+
* older data, in a `_geometry` on the record itself. Both are read.
|
|
55706
|
+
************************************************************/
|
|
55707
|
+
function has_saved_geometry(gobj) {
|
|
55708
|
+
let priv = gobj.priv;
|
|
55709
|
+
for (let topic of Object.keys(priv._graph_properties || {})) {
|
|
55710
|
+
let props = priv._graph_properties[topic];
|
|
55711
|
+
if (props && (0, _yuneta_gobj_js.is_object)(props.nodes) && Object.keys(props.nodes).length > 0) return true;
|
|
55712
|
+
}
|
|
55713
|
+
for (let topic of Object.keys(priv.records || {})) {
|
|
55714
|
+
let records = priv.records[topic];
|
|
55715
|
+
if (!(0, _yuneta_gobj_js.is_array)(records)) continue;
|
|
55716
|
+
for (let record of records) if (record && (0, _yuneta_gobj_js.is_object)(record._geometry)) return true;
|
|
55717
|
+
}
|
|
55718
|
+
return false;
|
|
55719
|
+
}
|
|
55720
|
+
/************************************************************
|
|
55721
|
+
* Choose a layout for a treedb nobody has arranged yet.
|
|
55722
|
+
*
|
|
55723
|
+
* `manual` means "leave every node where it was put", and where none
|
|
55724
|
+
* was put it means a cascade: get_default_ne_xy() walks x and y
|
|
55725
|
+
* together, so a treedb opened for the first time was a diagonal pile
|
|
55726
|
+
* of cards — 126 of them on a real one — and the only way out was to
|
|
55727
|
+
* know to pick a layout by hand. It is the right default only once
|
|
55728
|
+
* there ARE saved positions to leave alone.
|
|
55729
|
+
*
|
|
55730
|
+
* So: nothing saved and no preference of the user's ⇒ dagre. The pick
|
|
55731
|
+
* is deliberately NOT persisted — it is a default, not a choice, and
|
|
55732
|
+
* the moment the user drags one node the geometry exists and `manual`
|
|
55733
|
+
* becomes right again by itself.
|
|
55734
|
+
************************************************************/
|
|
55735
|
+
function auto_layout(gobj) {
|
|
55736
|
+
let priv = gobj.priv;
|
|
55737
|
+
if (priv.layout) return;
|
|
55738
|
+
if (has_saved_geometry(gobj)) return;
|
|
55739
|
+
if (!priv.graph) return;
|
|
55740
|
+
let name = "dagre";
|
|
55741
|
+
(0, _yuneta_gobj_js.gobj_write_attr)(gobj, "layout", name);
|
|
55742
|
+
try {
|
|
55743
|
+
priv.graph.setLayout(_layouts[name]);
|
|
55744
|
+
} catch (e) {
|
|
55745
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: cannot set the '${name}' layout: ${e}`);
|
|
55746
|
+
return;
|
|
55747
|
+
}
|
|
55748
|
+
(0, _yuneta_gobj_js.gobj_publish_event)(gobj, "EV_LAYOUT_AUTOSET", { layout: name });
|
|
55749
|
+
}
|
|
55750
|
+
/************************************************************
|
|
55681
55751
|
* Show or hide the minimap, deciding by the SIZE of the graph.
|
|
55682
55752
|
*
|
|
55683
55753
|
* A minimap of a graph that already fits on screen is decoration; one
|
|
@@ -55708,7 +55778,6 @@ function refresh_minimap(gobj) {
|
|
|
55708
55778
|
return;
|
|
55709
55779
|
}
|
|
55710
55780
|
if (graph_get_plugin(gobj, "minimap")) return;
|
|
55711
|
-
(0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: minimap: adding for ${n} nodes (threshold ${threshold})`);
|
|
55712
55781
|
graph_add_plugin(gobj, "minimap", {
|
|
55713
55782
|
size: [200, 140],
|
|
55714
55783
|
position: "bottom-left",
|
|
@@ -55732,12 +55801,6 @@ function refresh_minimap(gobj) {
|
|
|
55732
55801
|
}
|
|
55733
55802
|
}
|
|
55734
55803
|
});
|
|
55735
|
-
try {
|
|
55736
|
-
graph.draw();
|
|
55737
|
-
} catch (e) {
|
|
55738
|
-
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: cannot draw the minimap: ${e}`);
|
|
55739
|
-
}
|
|
55740
|
-
(0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: minimap: plugin is ${graph_get_plugin(gobj, "minimap") ? "up" : "MISSING"}`);
|
|
55741
55804
|
}
|
|
55742
55805
|
/************************************************************
|
|
55743
55806
|
* The innerHTML of ONE node, in the given theme and highlight state.
|
|
@@ -56530,30 +56593,37 @@ function ac_load_data(gobj, event, kw, src) {
|
|
|
56530
56593
|
break;
|
|
56531
56594
|
}
|
|
56532
56595
|
}
|
|
56533
|
-
if (do_links && priv.graph)
|
|
56534
|
-
|
|
56596
|
+
if (do_links && priv.graph) {
|
|
56597
|
+
try {
|
|
56598
|
+
refresh_minimap(gobj);
|
|
56599
|
+
} catch (e) {
|
|
56600
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: refresh_minimap failed: ${e}`);
|
|
56601
|
+
}
|
|
56535
56602
|
graph_draw(gobj).then(() => {
|
|
56536
|
-
|
|
56537
|
-
|
|
56538
|
-
else graph_remove_plugin(gobj, "history");
|
|
56603
|
+
create_links(gobj);
|
|
56604
|
+
graph_draw(gobj).then(() => {
|
|
56539
56605
|
try {
|
|
56540
|
-
|
|
56606
|
+
auto_layout(gobj);
|
|
56541
56607
|
} catch (e) {
|
|
56542
|
-
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}:
|
|
56543
|
-
}
|
|
56544
|
-
|
|
56545
|
-
|
|
56546
|
-
|
|
56547
|
-
|
|
56548
|
-
|
|
56549
|
-
|
|
56550
|
-
|
|
56551
|
-
|
|
56552
|
-
|
|
56553
|
-
|
|
56608
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: auto_layout failed: ${e}`);
|
|
56609
|
+
}
|
|
56610
|
+
graph_layout(gobj).then(() => {
|
|
56611
|
+
if (priv.edit_mode) graph_add_plugin(gobj, "history");
|
|
56612
|
+
else graph_remove_plugin(gobj, "history");
|
|
56613
|
+
if (priv._pending_focus_topic !== null) {
|
|
56614
|
+
let ft = priv._pending_focus_topic;
|
|
56615
|
+
priv._pending_focus_topic = null;
|
|
56616
|
+
graph_focus_topic(gobj, ft);
|
|
56617
|
+
}
|
|
56618
|
+
if (priv._pending_find !== null) {
|
|
56619
|
+
let term = priv._pending_find;
|
|
56620
|
+
priv._pending_find = null;
|
|
56621
|
+
publish_find_result(gobj, term, graph_find_nodes(gobj, term));
|
|
56622
|
+
}
|
|
56623
|
+
});
|
|
56554
56624
|
});
|
|
56555
56625
|
});
|
|
56556
|
-
}
|
|
56626
|
+
}
|
|
56557
56627
|
return 0;
|
|
56558
56628
|
}
|
|
56559
56629
|
/************************************************************
|
|
@@ -57177,6 +57247,7 @@ function create_gclass$1(gclass_name) {
|
|
|
57177
57247
|
["EV_FOCUS_TOPIC", 0],
|
|
57178
57248
|
["EV_FIND_NODES", 0],
|
|
57179
57249
|
["EV_FIND_RESULT", _yuneta_gobj_js.event_flag_t.EVF_OUTPUT_EVENT],
|
|
57250
|
+
["EV_LAYOUT_AUTOSET", _yuneta_gobj_js.event_flag_t.EVF_OUTPUT_EVENT],
|
|
57180
57251
|
["EV_CENTER", 0],
|
|
57181
57252
|
["EV_FULLSCREEN", 0],
|
|
57182
57253
|
["EV_SET_LAYOUT", 0],
|
package/dist/gobj-ui.es.js
CHANGED
|
@@ -19958,6 +19958,21 @@ function ac_legend_topic(gobj, event, kw, src) {
|
|
|
19958
19958
|
return 0;
|
|
19959
19959
|
}
|
|
19960
19960
|
/************************************************************
|
|
19961
|
+
* The child chose a layout for a treedb nobody has arranged yet.
|
|
19962
|
+
* Only the SELECT is moved: the pick is a default, not the user's
|
|
19963
|
+
* choice, so it is not persisted — the day somebody drags a node the
|
|
19964
|
+
* saved geometry exists and `manual` is right again.
|
|
19965
|
+
************************************************************/
|
|
19966
|
+
function ac_layout_autoset(gobj, event, kw, src) {
|
|
19967
|
+
let $container = gobj_read_attr(gobj, "$container");
|
|
19968
|
+
if (!$container) return 0;
|
|
19969
|
+
let $select = $container.querySelector(".GRAPH_LAYOUT_SELECT");
|
|
19970
|
+
let layout = kw && kw.layout || "";
|
|
19971
|
+
if (!$select || !layout) return 0;
|
|
19972
|
+
$select.value = layout;
|
|
19973
|
+
return 0;
|
|
19974
|
+
}
|
|
19975
|
+
/************************************************************
|
|
19961
19976
|
* Forward the find down to the graph child.
|
|
19962
19977
|
************************************************************/
|
|
19963
19978
|
function ac_find_nodes$1(gobj, event, kw, src) {
|
|
@@ -20158,6 +20173,11 @@ function create_gclass$4(gclass_name) {
|
|
|
20158
20173
|
ac_find_nodes$1,
|
|
20159
20174
|
null
|
|
20160
20175
|
],
|
|
20176
|
+
[
|
|
20177
|
+
"EV_LAYOUT_AUTOSET",
|
|
20178
|
+
ac_layout_autoset,
|
|
20179
|
+
null
|
|
20180
|
+
],
|
|
20161
20181
|
[
|
|
20162
20182
|
"EV_TOGGLE_LEGEND",
|
|
20163
20183
|
ac_toggle_legend,
|
|
@@ -20216,6 +20236,7 @@ function create_gclass$4(gclass_name) {
|
|
|
20216
20236
|
["EV_SET_FOCUS_TOPIC", 0],
|
|
20217
20237
|
["EV_FIND_NODES", 0],
|
|
20218
20238
|
["EV_FIND_RESULT", 0],
|
|
20239
|
+
["EV_LAYOUT_AUTOSET", 0],
|
|
20219
20240
|
["EV_TOGGLE_LEGEND", 0],
|
|
20220
20241
|
["EV_LEGEND_TOPIC", 0],
|
|
20221
20242
|
["EV_TOPIC_SELECTED", event_flag_t.EVF_OUTPUT_EVENT | event_flag_t.EVF_NO_WARN_SUBS],
|
|
@@ -55665,6 +55686,55 @@ function show_node_detail_popover(gobj, node_id) {
|
|
|
55665
55686
|
* junction diamonds get their neutral fill/stroke re-themed.
|
|
55666
55687
|
************************************************************/
|
|
55667
55688
|
/************************************************************
|
|
55689
|
+
* Has anybody ever PLACED a node of this treedb?
|
|
55690
|
+
*
|
|
55691
|
+
* Saved positions live in `__graphs__` (per topic, per node) and, on
|
|
55692
|
+
* older data, in a `_geometry` on the record itself. Both are read.
|
|
55693
|
+
************************************************************/
|
|
55694
|
+
function has_saved_geometry(gobj) {
|
|
55695
|
+
let priv = gobj.priv;
|
|
55696
|
+
for (let topic of Object.keys(priv._graph_properties || {})) {
|
|
55697
|
+
let props = priv._graph_properties[topic];
|
|
55698
|
+
if (props && is_object(props.nodes) && Object.keys(props.nodes).length > 0) return true;
|
|
55699
|
+
}
|
|
55700
|
+
for (let topic of Object.keys(priv.records || {})) {
|
|
55701
|
+
let records = priv.records[topic];
|
|
55702
|
+
if (!is_array(records)) continue;
|
|
55703
|
+
for (let record of records) if (record && is_object(record._geometry)) return true;
|
|
55704
|
+
}
|
|
55705
|
+
return false;
|
|
55706
|
+
}
|
|
55707
|
+
/************************************************************
|
|
55708
|
+
* Choose a layout for a treedb nobody has arranged yet.
|
|
55709
|
+
*
|
|
55710
|
+
* `manual` means "leave every node where it was put", and where none
|
|
55711
|
+
* was put it means a cascade: get_default_ne_xy() walks x and y
|
|
55712
|
+
* together, so a treedb opened for the first time was a diagonal pile
|
|
55713
|
+
* of cards — 126 of them on a real one — and the only way out was to
|
|
55714
|
+
* know to pick a layout by hand. It is the right default only once
|
|
55715
|
+
* there ARE saved positions to leave alone.
|
|
55716
|
+
*
|
|
55717
|
+
* So: nothing saved and no preference of the user's ⇒ dagre. The pick
|
|
55718
|
+
* is deliberately NOT persisted — it is a default, not a choice, and
|
|
55719
|
+
* the moment the user drags one node the geometry exists and `manual`
|
|
55720
|
+
* becomes right again by itself.
|
|
55721
|
+
************************************************************/
|
|
55722
|
+
function auto_layout(gobj) {
|
|
55723
|
+
let priv = gobj.priv;
|
|
55724
|
+
if (priv.layout) return;
|
|
55725
|
+
if (has_saved_geometry(gobj)) return;
|
|
55726
|
+
if (!priv.graph) return;
|
|
55727
|
+
let name = "dagre";
|
|
55728
|
+
gobj_write_attr(gobj, "layout", name);
|
|
55729
|
+
try {
|
|
55730
|
+
priv.graph.setLayout(_layouts[name]);
|
|
55731
|
+
} catch (e) {
|
|
55732
|
+
log_error(`${gobj_short_name(gobj)}: cannot set the '${name}' layout: ${e}`);
|
|
55733
|
+
return;
|
|
55734
|
+
}
|
|
55735
|
+
gobj_publish_event(gobj, "EV_LAYOUT_AUTOSET", { layout: name });
|
|
55736
|
+
}
|
|
55737
|
+
/************************************************************
|
|
55668
55738
|
* Show or hide the minimap, deciding by the SIZE of the graph.
|
|
55669
55739
|
*
|
|
55670
55740
|
* A minimap of a graph that already fits on screen is decoration; one
|
|
@@ -55695,7 +55765,6 @@ function refresh_minimap(gobj) {
|
|
|
55695
55765
|
return;
|
|
55696
55766
|
}
|
|
55697
55767
|
if (graph_get_plugin(gobj, "minimap")) return;
|
|
55698
|
-
log_warning(`${gobj_short_name(gobj)}: minimap: adding for ${n} nodes (threshold ${threshold})`);
|
|
55699
55768
|
graph_add_plugin(gobj, "minimap", {
|
|
55700
55769
|
size: [200, 140],
|
|
55701
55770
|
position: "bottom-left",
|
|
@@ -55719,12 +55788,6 @@ function refresh_minimap(gobj) {
|
|
|
55719
55788
|
}
|
|
55720
55789
|
}
|
|
55721
55790
|
});
|
|
55722
|
-
try {
|
|
55723
|
-
graph.draw();
|
|
55724
|
-
} catch (e) {
|
|
55725
|
-
log_error(`${gobj_short_name(gobj)}: cannot draw the minimap: ${e}`);
|
|
55726
|
-
}
|
|
55727
|
-
log_warning(`${gobj_short_name(gobj)}: minimap: plugin is ${graph_get_plugin(gobj, "minimap") ? "up" : "MISSING"}`);
|
|
55728
55791
|
}
|
|
55729
55792
|
/************************************************************
|
|
55730
55793
|
* The innerHTML of ONE node, in the given theme and highlight state.
|
|
@@ -56517,30 +56580,37 @@ function ac_load_data(gobj, event, kw, src) {
|
|
|
56517
56580
|
break;
|
|
56518
56581
|
}
|
|
56519
56582
|
}
|
|
56520
|
-
if (do_links && priv.graph)
|
|
56521
|
-
|
|
56583
|
+
if (do_links && priv.graph) {
|
|
56584
|
+
try {
|
|
56585
|
+
refresh_minimap(gobj);
|
|
56586
|
+
} catch (e) {
|
|
56587
|
+
log_error(`${gobj_short_name(gobj)}: refresh_minimap failed: ${e}`);
|
|
56588
|
+
}
|
|
56522
56589
|
graph_draw(gobj).then(() => {
|
|
56523
|
-
|
|
56524
|
-
|
|
56525
|
-
else graph_remove_plugin(gobj, "history");
|
|
56590
|
+
create_links(gobj);
|
|
56591
|
+
graph_draw(gobj).then(() => {
|
|
56526
56592
|
try {
|
|
56527
|
-
|
|
56593
|
+
auto_layout(gobj);
|
|
56528
56594
|
} catch (e) {
|
|
56529
|
-
log_error(`${gobj_short_name(gobj)}:
|
|
56530
|
-
}
|
|
56531
|
-
|
|
56532
|
-
|
|
56533
|
-
|
|
56534
|
-
|
|
56535
|
-
|
|
56536
|
-
|
|
56537
|
-
|
|
56538
|
-
|
|
56539
|
-
|
|
56540
|
-
|
|
56595
|
+
log_error(`${gobj_short_name(gobj)}: auto_layout failed: ${e}`);
|
|
56596
|
+
}
|
|
56597
|
+
graph_layout(gobj).then(() => {
|
|
56598
|
+
if (priv.edit_mode) graph_add_plugin(gobj, "history");
|
|
56599
|
+
else graph_remove_plugin(gobj, "history");
|
|
56600
|
+
if (priv._pending_focus_topic !== null) {
|
|
56601
|
+
let ft = priv._pending_focus_topic;
|
|
56602
|
+
priv._pending_focus_topic = null;
|
|
56603
|
+
graph_focus_topic(gobj, ft);
|
|
56604
|
+
}
|
|
56605
|
+
if (priv._pending_find !== null) {
|
|
56606
|
+
let term = priv._pending_find;
|
|
56607
|
+
priv._pending_find = null;
|
|
56608
|
+
publish_find_result(gobj, term, graph_find_nodes(gobj, term));
|
|
56609
|
+
}
|
|
56610
|
+
});
|
|
56541
56611
|
});
|
|
56542
56612
|
});
|
|
56543
|
-
}
|
|
56613
|
+
}
|
|
56544
56614
|
return 0;
|
|
56545
56615
|
}
|
|
56546
56616
|
/************************************************************
|
|
@@ -57164,6 +57234,7 @@ function create_gclass$1(gclass_name) {
|
|
|
57164
57234
|
["EV_FOCUS_TOPIC", 0],
|
|
57165
57235
|
["EV_FIND_NODES", 0],
|
|
57166
57236
|
["EV_FIND_RESULT", event_flag_t.EVF_OUTPUT_EVENT],
|
|
57237
|
+
["EV_LAYOUT_AUTOSET", event_flag_t.EVF_OUTPUT_EVENT],
|
|
57167
57238
|
["EV_CENTER", 0],
|
|
57168
57239
|
["EV_FULLSCREEN", 0],
|
|
57169
57240
|
["EV_SET_LAYOUT", 0],
|
package/package.json
CHANGED
package/src/c_g6_nodes_tree.js
CHANGED
|
@@ -4483,6 +4483,80 @@ function show_node_detail_popover(gobj, node_id)
|
|
|
4483
4483
|
* not re-themed by setTheme()) are regenerated; structural
|
|
4484
4484
|
* junction diamonds get their neutral fill/stroke re-themed.
|
|
4485
4485
|
************************************************************/
|
|
4486
|
+
/************************************************************
|
|
4487
|
+
* Has anybody ever PLACED a node of this treedb?
|
|
4488
|
+
*
|
|
4489
|
+
* Saved positions live in `__graphs__` (per topic, per node) and, on
|
|
4490
|
+
* older data, in a `_geometry` on the record itself. Both are read.
|
|
4491
|
+
************************************************************/
|
|
4492
|
+
function has_saved_geometry(gobj)
|
|
4493
|
+
{
|
|
4494
|
+
let priv = gobj.priv;
|
|
4495
|
+
|
|
4496
|
+
for(let topic of Object.keys(priv._graph_properties || {})) {
|
|
4497
|
+
let props = priv._graph_properties[topic];
|
|
4498
|
+
if(props && is_object(props.nodes) && Object.keys(props.nodes).length > 0) {
|
|
4499
|
+
return true;
|
|
4500
|
+
}
|
|
4501
|
+
}
|
|
4502
|
+
|
|
4503
|
+
for(let topic of Object.keys(priv.records || {})) {
|
|
4504
|
+
let records = priv.records[topic];
|
|
4505
|
+
if(!is_array(records)) {
|
|
4506
|
+
continue;
|
|
4507
|
+
}
|
|
4508
|
+
for(let record of records) {
|
|
4509
|
+
if(record && is_object(record._geometry)) {
|
|
4510
|
+
return true;
|
|
4511
|
+
}
|
|
4512
|
+
}
|
|
4513
|
+
}
|
|
4514
|
+
|
|
4515
|
+
return false;
|
|
4516
|
+
}
|
|
4517
|
+
|
|
4518
|
+
/************************************************************
|
|
4519
|
+
* Choose a layout for a treedb nobody has arranged yet.
|
|
4520
|
+
*
|
|
4521
|
+
* `manual` means "leave every node where it was put", and where none
|
|
4522
|
+
* was put it means a cascade: get_default_ne_xy() walks x and y
|
|
4523
|
+
* together, so a treedb opened for the first time was a diagonal pile
|
|
4524
|
+
* of cards — 126 of them on a real one — and the only way out was to
|
|
4525
|
+
* know to pick a layout by hand. It is the right default only once
|
|
4526
|
+
* there ARE saved positions to leave alone.
|
|
4527
|
+
*
|
|
4528
|
+
* So: nothing saved and no preference of the user's ⇒ dagre. The pick
|
|
4529
|
+
* is deliberately NOT persisted — it is a default, not a choice, and
|
|
4530
|
+
* the moment the user drags one node the geometry exists and `manual`
|
|
4531
|
+
* becomes right again by itself.
|
|
4532
|
+
************************************************************/
|
|
4533
|
+
function auto_layout(gobj)
|
|
4534
|
+
{
|
|
4535
|
+
let priv = gobj.priv;
|
|
4536
|
+
|
|
4537
|
+
if(priv.layout) {
|
|
4538
|
+
return; /* the user picked one for this treedb */
|
|
4539
|
+
}
|
|
4540
|
+
if(has_saved_geometry(gobj)) {
|
|
4541
|
+
return; /* somebody arranged it: leave it alone */
|
|
4542
|
+
}
|
|
4543
|
+
if(!priv.graph) {
|
|
4544
|
+
return;
|
|
4545
|
+
}
|
|
4546
|
+
|
|
4547
|
+
let name = "dagre";
|
|
4548
|
+
gobj_write_attr(gobj, "layout", name);
|
|
4549
|
+
try {
|
|
4550
|
+
priv.graph.setLayout(_layouts[name]);
|
|
4551
|
+
} catch(e) {
|
|
4552
|
+
log_error(`${gobj_short_name(gobj)}: cannot set the '${name}' layout: ${e}`);
|
|
4553
|
+
return;
|
|
4554
|
+
}
|
|
4555
|
+
/* The toolbar's select was filled before the data arrived, so it is
|
|
4556
|
+
* still showing `manual`: tell it what the graph is actually doing. */
|
|
4557
|
+
gobj_publish_event(gobj, "EV_LAYOUT_AUTOSET", {layout: name});
|
|
4558
|
+
}
|
|
4559
|
+
|
|
4486
4560
|
/************************************************************
|
|
4487
4561
|
* Show or hide the minimap, deciding by the SIZE of the graph.
|
|
4488
4562
|
*
|
|
@@ -4524,8 +4598,6 @@ function refresh_minimap(gobj)
|
|
|
4524
4598
|
return; /* already up */
|
|
4525
4599
|
}
|
|
4526
4600
|
|
|
4527
|
-
log_warning(`${gobj_short_name(gobj)}: minimap: adding for ${n} nodes ` +
|
|
4528
|
-
`(threshold ${threshold})`);
|
|
4529
4601
|
graph_add_plugin(
|
|
4530
4602
|
gobj,
|
|
4531
4603
|
"minimap",
|
|
@@ -4558,18 +4630,6 @@ function refresh_minimap(gobj)
|
|
|
4558
4630
|
}
|
|
4559
4631
|
}
|
|
4560
4632
|
);
|
|
4561
|
-
|
|
4562
|
-
/* The plugin builds its canvas on its FIRST render, and it renders off
|
|
4563
|
-
* the graph's draw events — which have all already happened by the time
|
|
4564
|
-
* the node count is known and this runs. Without a draw of its own it
|
|
4565
|
-
* sits there having never painted, with no container in the DOM at all. */
|
|
4566
|
-
try {
|
|
4567
|
-
graph.draw();
|
|
4568
|
-
} catch(e) {
|
|
4569
|
-
log_error(`${gobj_short_name(gobj)}: cannot draw the minimap: ${e}`);
|
|
4570
|
-
}
|
|
4571
|
-
log_warning(`${gobj_short_name(gobj)}: minimap: plugin is ` +
|
|
4572
|
-
`${graph_get_plugin(gobj, "minimap")? "up" : "MISSING"}`);
|
|
4573
4633
|
}
|
|
4574
4634
|
|
|
4575
4635
|
/************************************************************
|
|
@@ -5768,27 +5828,36 @@ function ac_load_data(gobj, event, kw, src)
|
|
|
5768
5828
|
}
|
|
5769
5829
|
|
|
5770
5830
|
if(do_links && priv.graph) {
|
|
5831
|
+
/* Decided BEFORE the drawing, not after it.
|
|
5832
|
+
*
|
|
5833
|
+
* The plugin builds its canvas on its FIRST render, and it renders
|
|
5834
|
+
* off the graph's draw events — so a minimap added after the last
|
|
5835
|
+
* draw is instantiated, bound, and never painted: no container in
|
|
5836
|
+
* the DOM at all, and nothing anywhere says so. Added here it rides
|
|
5837
|
+
* the two draws and the layout that follow. The node count it needs
|
|
5838
|
+
* is already known: the records were turned into nodes above. */
|
|
5839
|
+
try {
|
|
5840
|
+
refresh_minimap(gobj);
|
|
5841
|
+
} catch(e) {
|
|
5842
|
+
log_error(`${gobj_short_name(gobj)}: refresh_minimap failed: ${e}`);
|
|
5843
|
+
}
|
|
5771
5844
|
graph_draw(gobj).then(() => { // draw nodes, else the link fails
|
|
5772
5845
|
create_links(gobj);
|
|
5773
5846
|
graph_draw(gobj).then(() => {
|
|
5847
|
+
/* Before the layout runs, and only now: whether anybody has
|
|
5848
|
+
* ever placed a node of this treedb is not known until its
|
|
5849
|
+
* records and __graphs__ are in. */
|
|
5850
|
+
try {
|
|
5851
|
+
auto_layout(gobj);
|
|
5852
|
+
} catch(e) {
|
|
5853
|
+
log_error(`${gobj_short_name(gobj)}: auto_layout failed: ${e}`);
|
|
5854
|
+
}
|
|
5774
5855
|
graph_layout(gobj).then(() => {
|
|
5775
5856
|
if(priv.edit_mode) {
|
|
5776
5857
|
graph_add_plugin(gobj, "history");
|
|
5777
5858
|
} else {
|
|
5778
5859
|
graph_remove_plugin(gobj, "history");
|
|
5779
5860
|
}
|
|
5780
|
-
/* The graph knows its size now: a minimap appears only
|
|
5781
|
-
* when there is something to be lost in.
|
|
5782
|
-
*
|
|
5783
|
-
* Guarded because this runs inside a .then(): an
|
|
5784
|
-
* exception here becomes an unhandled rejection, which
|
|
5785
|
-
* is not a console error and not a pageerror — it is
|
|
5786
|
-
* nothing at all, and the feature just fails to appear. */
|
|
5787
|
-
try {
|
|
5788
|
-
refresh_minimap(gobj);
|
|
5789
|
-
} catch(e) {
|
|
5790
|
-
log_error(`${gobj_short_name(gobj)}: refresh_minimap failed: ${e}`);
|
|
5791
|
-
}
|
|
5792
5861
|
/* Nodes exist and are positioned now: apply a focus
|
|
5793
5862
|
* requested before the data was ready (deep link). */
|
|
5794
5863
|
if(priv._pending_focus_topic !== null) {
|
|
@@ -6576,6 +6645,7 @@ function create_gclass(gclass_name)
|
|
|
6576
6645
|
["EV_FOCUS_TOPIC", 0],
|
|
6577
6646
|
["EV_FIND_NODES", 0],
|
|
6578
6647
|
["EV_FIND_RESULT", event_flag_t.EVF_OUTPUT_EVENT],
|
|
6648
|
+
["EV_LAYOUT_AUTOSET", event_flag_t.EVF_OUTPUT_EVENT],
|
|
6579
6649
|
["EV_CENTER", 0],
|
|
6580
6650
|
["EV_FULLSCREEN", 0],
|
|
6581
6651
|
["EV_SET_LAYOUT", 0],
|
|
@@ -2337,6 +2337,27 @@ function ac_legend_topic(gobj, event, kw, src)
|
|
|
2337
2337
|
return 0;
|
|
2338
2338
|
}
|
|
2339
2339
|
|
|
2340
|
+
/************************************************************
|
|
2341
|
+
* The child chose a layout for a treedb nobody has arranged yet.
|
|
2342
|
+
* Only the SELECT is moved: the pick is a default, not the user's
|
|
2343
|
+
* choice, so it is not persisted — the day somebody drags a node the
|
|
2344
|
+
* saved geometry exists and `manual` is right again.
|
|
2345
|
+
************************************************************/
|
|
2346
|
+
function ac_layout_autoset(gobj, event, kw, src)
|
|
2347
|
+
{
|
|
2348
|
+
let $container = gobj_read_attr(gobj, "$container");
|
|
2349
|
+
if(!$container) {
|
|
2350
|
+
return 0;
|
|
2351
|
+
}
|
|
2352
|
+
let $select = $container.querySelector(".GRAPH_LAYOUT_SELECT");
|
|
2353
|
+
let layout = (kw && kw.layout) || "";
|
|
2354
|
+
if(!$select || !layout) {
|
|
2355
|
+
return 0;
|
|
2356
|
+
}
|
|
2357
|
+
$select.value = layout;
|
|
2358
|
+
return 0;
|
|
2359
|
+
}
|
|
2360
|
+
|
|
2340
2361
|
/************************************************************
|
|
2341
2362
|
* Forward the find down to the graph child.
|
|
2342
2363
|
************************************************************/
|
|
@@ -2490,6 +2511,7 @@ function create_gclass(gclass_name)
|
|
|
2490
2511
|
["EV_SET_OPERATION_MODE", ac_set_operation_mode, null],
|
|
2491
2512
|
["EV_SET_FOCUS_TOPIC", ac_set_focus_topic, null],
|
|
2492
2513
|
["EV_FIND_NODES", ac_find_nodes, null],
|
|
2514
|
+
["EV_LAYOUT_AUTOSET", ac_layout_autoset, null],
|
|
2493
2515
|
["EV_TOGGLE_LEGEND", ac_toggle_legend, null],
|
|
2494
2516
|
["EV_LEGEND_TOPIC", ac_legend_topic, null],
|
|
2495
2517
|
["EV_FIND_RESULT", ac_find_result, null],
|
|
@@ -2529,6 +2551,7 @@ function create_gclass(gclass_name)
|
|
|
2529
2551
|
["EV_SET_FOCUS_TOPIC", 0],
|
|
2530
2552
|
["EV_FIND_NODES", 0],
|
|
2531
2553
|
["EV_FIND_RESULT", 0],
|
|
2554
|
+
["EV_LAYOUT_AUTOSET", 0],
|
|
2532
2555
|
["EV_TOGGLE_LEGEND", 0],
|
|
2533
2556
|
["EV_LEGEND_TOPIC", 0],
|
|
2534
2557
|
["EV_TOPIC_SELECTED",
|