@yuneta/gobj-ui 7.23.24 → 7.23.25
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 +67 -8
- package/dist/gobj-ui.es.js +68 -9
- package/package.json +1 -1
- package/src/c_g6_nodes_tree.js +21 -1
- package/src/c_yui_gobj_tree_js.js +21 -1
- package/src/c_yui_json_graph.js +32 -1
- package/src/lib_graph.css +27 -1
- package/src/yui_graph_camera.js +61 -5
package/dist/gobj-ui.cjs.js
CHANGED
|
@@ -9679,7 +9679,7 @@ function yui_graph_update_anchor($container, state) {
|
|
|
9679
9679
|
if (!$container) return;
|
|
9680
9680
|
let $btn = $container.querySelector(".EV_TOGGLE_ANCHOR");
|
|
9681
9681
|
if (!$btn) return;
|
|
9682
|
-
set_pressed_state($container, ".EV_TOGGLE_ANCHOR", state
|
|
9682
|
+
set_pressed_state($container, ".EV_TOGGLE_ANCHOR", state === "on");
|
|
9683
9683
|
$btn.classList.toggle("color_pending_state", state === "arming");
|
|
9684
9684
|
$btn.setAttribute("aria-pressed", state === "on" ? "true" : "false");
|
|
9685
9685
|
let key = state === "arming" ? "click the element to centre on" : state === "on" ? "centred: click to release" : "anchor view";
|
|
@@ -9695,18 +9695,35 @@ function yui_graph_update_anchor($container, state) {
|
|
|
9695
9695
|
* the zoom is what the reader asked for, the centring is what
|
|
9696
9696
|
* keeps the thing they are reading under their eyes.
|
|
9697
9697
|
*
|
|
9698
|
+
* The translate is computed and applied HERE rather than
|
|
9699
|
+
* delegated to `graph.focusElement()`, which is the obvious
|
|
9700
|
+
* call and does NOT work on these graphs. Measured: it
|
|
9701
|
+
* resolves, having computed the very offset wanted -- `[0,
|
|
9702
|
+
* 306]` for a card 306px above centre -- and the camera does
|
|
9703
|
+
* not move. `getPosition()` reads the same before and after,
|
|
9704
|
+
* and so does the card's box on screen. Three public calls do
|
|
9705
|
+
* move it, so that is what is used.
|
|
9706
|
+
*
|
|
9698
9707
|
* Guarded on every side because it runs on every wheel notch:
|
|
9699
9708
|
* a graph mid-rebuild, an anchor whose node went away with a
|
|
9700
|
-
* fold, a G6
|
|
9709
|
+
* fold, a G6 missing one of these calls -- none of those is
|
|
9701
9710
|
* an error worth a log line per notch, they are all "there is
|
|
9702
9711
|
* nothing to centre right now".
|
|
9703
9712
|
************************************************************/
|
|
9704
|
-
function yui_graph_center_on(graph, node_id) {
|
|
9713
|
+
async function yui_graph_center_on(graph, node_id) {
|
|
9705
9714
|
if (!graph || !node_id) return false;
|
|
9706
9715
|
try {
|
|
9707
9716
|
if (typeof graph.getElementData === "function" && !graph.getElementData(node_id)) return false;
|
|
9708
|
-
if (typeof graph.
|
|
9709
|
-
|
|
9717
|
+
if (typeof graph.getElementPosition !== "function" || typeof graph.getViewportByCanvas !== "function" || typeof graph.getCanvasCenter !== "function" || typeof graph.translateTo !== "function") return false;
|
|
9718
|
+
for (let i = 0; i < 3; i++) {
|
|
9719
|
+
let at = graph.getViewportByCanvas(graph.getElementPosition(node_id));
|
|
9720
|
+
let want = graph.getCanvasCenter();
|
|
9721
|
+
let dx = want[0] - at[0];
|
|
9722
|
+
let dy = want[1] - at[1];
|
|
9723
|
+
if (Math.abs(dx) < 1 && Math.abs(dy) < 1) break;
|
|
9724
|
+
let pos = graph.getPosition();
|
|
9725
|
+
await graph.translateTo([pos[0] + dx, pos[1] + dy]);
|
|
9726
|
+
}
|
|
9710
9727
|
return true;
|
|
9711
9728
|
} catch (e) {
|
|
9712
9729
|
return false;
|
|
@@ -11596,6 +11613,14 @@ function reanchor$1(gobj) {
|
|
|
11596
11613
|
yui_graph_update_anchor((0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container"), priv.anchor_state);
|
|
11597
11614
|
}
|
|
11598
11615
|
/************************************************************
|
|
11616
|
+
* Centre on the anchor, one cycle after it was chosen.
|
|
11617
|
+
************************************************************/
|
|
11618
|
+
function ac_center_anchor$2(gobj, event, kw, src) {
|
|
11619
|
+
let priv = gobj.priv;
|
|
11620
|
+
if (priv.anchor_state === "on" && priv.anchor_id) yui_graph_center_on(priv.graph, priv.anchor_id);
|
|
11621
|
+
return 0;
|
|
11622
|
+
}
|
|
11623
|
+
/************************************************************
|
|
11599
11624
|
* Arm the anchor, or let it go.
|
|
11600
11625
|
*
|
|
11601
11626
|
* Three states and one button, so a press ADVANCES: with no
|
|
@@ -11678,7 +11703,7 @@ function ac_node_click$4(gobj, event, kw, src) {
|
|
|
11678
11703
|
priv.anchor_path = nodedata && nodedata.data ? nodedata.data.path : "";
|
|
11679
11704
|
priv.anchor_state = "on";
|
|
11680
11705
|
yui_graph_update_anchor((0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container"), priv.anchor_state);
|
|
11681
|
-
|
|
11706
|
+
(0, _yuneta_gobj_js.gobj_post_event)(gobj, "EV_CENTER_ANCHOR", {}, gobj);
|
|
11682
11707
|
return 0;
|
|
11683
11708
|
}
|
|
11684
11709
|
if (nodedata && nodedata.data) (0, _yuneta_gobj_js.gobj_publish_event)(gobj, "EV_JSON_ITEM_CLICKED", {
|
|
@@ -11819,6 +11844,11 @@ function create_gclass$11(gclass_name) {
|
|
|
11819
11844
|
ac_toggle_anchor$2,
|
|
11820
11845
|
null
|
|
11821
11846
|
],
|
|
11847
|
+
[
|
|
11848
|
+
"EV_CENTER_ANCHOR",
|
|
11849
|
+
ac_center_anchor$2,
|
|
11850
|
+
null
|
|
11851
|
+
],
|
|
11822
11852
|
[
|
|
11823
11853
|
"EV_RESIZE",
|
|
11824
11854
|
ac_resize$2,
|
|
@@ -11850,6 +11880,7 @@ function create_gclass$11(gclass_name) {
|
|
|
11850
11880
|
["EV_CENTER", 0],
|
|
11851
11881
|
["EV_NODE_CLICK", 0],
|
|
11852
11882
|
["EV_TOGGLE_ANCHOR", 0],
|
|
11883
|
+
["EV_CENTER_ANCHOR", 0],
|
|
11853
11884
|
["EV_RESIZE", 0],
|
|
11854
11885
|
["EV_SHOW", 0],
|
|
11855
11886
|
["EV_HIDE", 0],
|
|
@@ -14487,6 +14518,14 @@ function reanchor(gobj) {
|
|
|
14487
14518
|
yui_graph_update_anchor((0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container"), priv.anchor_state);
|
|
14488
14519
|
}
|
|
14489
14520
|
/************************************************************
|
|
14521
|
+
* Centre on the anchor, one cycle after it was chosen.
|
|
14522
|
+
************************************************************/
|
|
14523
|
+
function ac_center_anchor$1(gobj, event, kw, src) {
|
|
14524
|
+
let priv = gobj.priv;
|
|
14525
|
+
if (priv.anchor_state === "on" && priv.anchor_id) yui_graph_center_on(priv.graph, priv.anchor_id);
|
|
14526
|
+
return 0;
|
|
14527
|
+
}
|
|
14528
|
+
/************************************************************
|
|
14490
14529
|
* Arm the anchor, or let it go.
|
|
14491
14530
|
*
|
|
14492
14531
|
* Three states and one button, so a press ADVANCES: with no
|
|
@@ -14571,7 +14610,7 @@ function ac_node_click$3(gobj, event, kw, src) {
|
|
|
14571
14610
|
priv.anchor_name = node_data.full_name || "";
|
|
14572
14611
|
priv.anchor_state = "on";
|
|
14573
14612
|
yui_graph_update_anchor((0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container"), priv.anchor_state);
|
|
14574
|
-
|
|
14613
|
+
(0, _yuneta_gobj_js.gobj_post_event)(gobj, "EV_CENTER_ANCHOR", {}, gobj);
|
|
14575
14614
|
return 0;
|
|
14576
14615
|
}
|
|
14577
14616
|
let client_x = kw.evt && kw.evt.client ? kw.evt.client.x : 0;
|
|
@@ -14655,6 +14694,7 @@ function create_gclass$9(gclass_name) {
|
|
|
14655
14694
|
["EV_CENTER", 0],
|
|
14656
14695
|
["EV_NODE_CLICK", 0],
|
|
14657
14696
|
["EV_TOGGLE_ANCHOR", 0],
|
|
14697
|
+
["EV_CENTER_ANCHOR", 0],
|
|
14658
14698
|
["EV_RESIZE", 0],
|
|
14659
14699
|
["EV_SHOW", 0],
|
|
14660
14700
|
["EV_HIDE", 0]
|
|
@@ -14719,6 +14759,11 @@ function create_gclass$9(gclass_name) {
|
|
|
14719
14759
|
ac_toggle_anchor$1,
|
|
14720
14760
|
null
|
|
14721
14761
|
],
|
|
14762
|
+
[
|
|
14763
|
+
"EV_CENTER_ANCHOR",
|
|
14764
|
+
ac_center_anchor$1,
|
|
14765
|
+
null
|
|
14766
|
+
],
|
|
14722
14767
|
[
|
|
14723
14768
|
"EV_RESIZE",
|
|
14724
14769
|
ac_resize$1,
|
|
@@ -52931,6 +52976,14 @@ function ac_zoom_reset(gobj, event, kw, src) {
|
|
|
52931
52976
|
/************************************************************
|
|
52932
52977
|
* What the anchor button says it will do next.
|
|
52933
52978
|
************************************************************/
|
|
52979
|
+
function ac_center_anchor(gobj, event, kw, src) {
|
|
52980
|
+
let priv = gobj.priv;
|
|
52981
|
+
if (priv.anchor_state === "on" && priv.anchor_id) yui_graph_center_on(priv.graph, priv.anchor_id);
|
|
52982
|
+
return 0;
|
|
52983
|
+
}
|
|
52984
|
+
/************************************************************
|
|
52985
|
+
* What the anchor button says it will do next.
|
|
52986
|
+
************************************************************/
|
|
52934
52987
|
function anchor_title(state) {
|
|
52935
52988
|
if (state === "arming") return (0, i18next.t)("click the element to centre on");
|
|
52936
52989
|
if (state === "on") return (0, i18next.t)("centred: click to release");
|
|
@@ -53149,7 +53202,7 @@ function ac_node_click$2(gobj, event, kw, src) {
|
|
|
53149
53202
|
priv.anchor_id = node_id;
|
|
53150
53203
|
priv.anchor_state = "on";
|
|
53151
53204
|
update_toolbar(gobj);
|
|
53152
|
-
|
|
53205
|
+
(0, _yuneta_gobj_js.gobj_post_event)(gobj, "EV_CENTER_ANCHOR", {}, gobj);
|
|
53153
53206
|
return 0;
|
|
53154
53207
|
}
|
|
53155
53208
|
try {
|
|
@@ -53418,6 +53471,11 @@ function create_gclass$4(gclass_name) {
|
|
|
53418
53471
|
ac_toggle_anchor,
|
|
53419
53472
|
null
|
|
53420
53473
|
],
|
|
53474
|
+
[
|
|
53475
|
+
"EV_CENTER_ANCHOR",
|
|
53476
|
+
ac_center_anchor,
|
|
53477
|
+
null
|
|
53478
|
+
],
|
|
53421
53479
|
[
|
|
53422
53480
|
"EV_TOGGLE_TOOLBARS",
|
|
53423
53481
|
ac_toggle_toolbars,
|
|
@@ -53532,6 +53590,7 @@ function create_gclass$4(gclass_name) {
|
|
|
53532
53590
|
["EV_ZOOM_OUT", 0],
|
|
53533
53591
|
["EV_ZOOM_RESET", 0],
|
|
53534
53592
|
["EV_TOGGLE_ANCHOR", 0],
|
|
53593
|
+
["EV_CENTER_ANCHOR", 0],
|
|
53535
53594
|
["EV_TOGGLE_TOOLBARS", 0],
|
|
53536
53595
|
["EV_AUTO_FIT", 0],
|
|
53537
53596
|
["EV_ZOOM_SELECTION", 0],
|
package/dist/gobj-ui.es.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SDATA, SDATA_END, clean_name, createElement2, createOneHtml, create_template_record, data_type_t, debounce, duplicate_objects, empty_string, escapeHtml, event_flag_t, gclass_create, gclass_find_by_name, gclass_flag_t, getPositionRelativeToBody, gobj_change_state, gobj_command, gobj_create, gobj_create_pure_child, gobj_create_service, gobj_current_state, gobj_destroy, gobj_find_child, gobj_find_service, gobj_full_name, gobj_gclass_name, gobj_is_destroying, gobj_is_playing, gobj_is_pure_child, gobj_is_running, gobj_is_service, gobj_is_volatil, gobj_match_children, gobj_name, gobj_parent, gobj_publish_event, gobj_read_attr, gobj_read_bool_attr, gobj_read_integer_attr, gobj_read_pointer_attr, gobj_read_str_attr, gobj_save_persistent_attrs, gobj_send_event, gobj_set_trace_machine_format, gobj_short_name, gobj_start, gobj_start_tree, gobj_stop, gobj_stop_children, gobj_subscribe_event, gobj_unsubscribe_event, gobj_write_attr, gobj_write_bool_attr, gobj_write_integer_attr, gobj_write_str_attr, gobj_yuno, is_array, is_boolean, is_date, is_gobj, is_null, is_number, is_object, is_string, json_deep_copy, json_object_size, json_object_update, json_object_update_missing, json_size, kw_clone_by_keys, kw_flag_t, kw_get_dict, kw_get_dict_value, kw_get_int, kw_get_local_storage_value, kw_get_str, kw_has_key, kw_set_dict_value, kw_set_local_storage_value, kwid_find_one_record, kwid_get_ids, kwid_new_dict, log_error, log_warning, msg_iev_get_stack, parseBoolean, parseSVG, refresh_language, safeSrc, sdata_flag_t, set_console_log_enabled, set_log_callback, sprintf, str_in_list, template_get_field_desc, trace_msg, treedb_decoder_fkey, treedb_encoder_fkey, treedb_get_field_desc, treedb_hook_data_size } from "@yuneta/gobj-js";
|
|
1
|
+
import { SDATA, SDATA_END, clean_name, createElement2, createOneHtml, create_template_record, data_type_t, debounce, duplicate_objects, empty_string, escapeHtml, event_flag_t, gclass_create, gclass_find_by_name, gclass_flag_t, getPositionRelativeToBody, gobj_change_state, gobj_command, gobj_create, gobj_create_pure_child, gobj_create_service, gobj_current_state, gobj_destroy, gobj_find_child, gobj_find_service, gobj_full_name, gobj_gclass_name, gobj_is_destroying, gobj_is_playing, gobj_is_pure_child, gobj_is_running, gobj_is_service, gobj_is_volatil, gobj_match_children, gobj_name, gobj_parent, gobj_post_event, gobj_publish_event, gobj_read_attr, gobj_read_bool_attr, gobj_read_integer_attr, gobj_read_pointer_attr, gobj_read_str_attr, gobj_save_persistent_attrs, gobj_send_event, gobj_set_trace_machine_format, gobj_short_name, gobj_start, gobj_start_tree, gobj_stop, gobj_stop_children, gobj_subscribe_event, gobj_unsubscribe_event, gobj_write_attr, gobj_write_bool_attr, gobj_write_integer_attr, gobj_write_str_attr, gobj_yuno, is_array, is_boolean, is_date, is_gobj, is_null, is_number, is_object, is_string, json_deep_copy, json_object_size, json_object_update, json_object_update_missing, json_size, kw_clone_by_keys, kw_flag_t, kw_get_dict, kw_get_dict_value, kw_get_int, kw_get_local_storage_value, kw_get_str, kw_has_key, kw_set_dict_value, kw_set_local_storage_value, kwid_find_one_record, kwid_get_ids, kwid_new_dict, log_error, log_warning, msg_iev_get_stack, parseBoolean, parseSVG, refresh_language, safeSrc, sdata_flag_t, set_console_log_enabled, set_log_callback, sprintf, str_in_list, template_get_field_desc, trace_msg, treedb_decoder_fkey, treedb_encoder_fkey, treedb_get_field_desc, treedb_hook_data_size } from "@yuneta/gobj-js";
|
|
2
2
|
import i18next, { t } from "i18next";
|
|
3
3
|
import TomSelect from "tom-select";
|
|
4
4
|
import { createJSONEditor } from "vanilla-jsoneditor";
|
|
@@ -9674,7 +9674,7 @@ function yui_graph_update_anchor($container, state) {
|
|
|
9674
9674
|
if (!$container) return;
|
|
9675
9675
|
let $btn = $container.querySelector(".EV_TOGGLE_ANCHOR");
|
|
9676
9676
|
if (!$btn) return;
|
|
9677
|
-
set_pressed_state($container, ".EV_TOGGLE_ANCHOR", state
|
|
9677
|
+
set_pressed_state($container, ".EV_TOGGLE_ANCHOR", state === "on");
|
|
9678
9678
|
$btn.classList.toggle("color_pending_state", state === "arming");
|
|
9679
9679
|
$btn.setAttribute("aria-pressed", state === "on" ? "true" : "false");
|
|
9680
9680
|
let key = state === "arming" ? "click the element to centre on" : state === "on" ? "centred: click to release" : "anchor view";
|
|
@@ -9690,18 +9690,35 @@ function yui_graph_update_anchor($container, state) {
|
|
|
9690
9690
|
* the zoom is what the reader asked for, the centring is what
|
|
9691
9691
|
* keeps the thing they are reading under their eyes.
|
|
9692
9692
|
*
|
|
9693
|
+
* The translate is computed and applied HERE rather than
|
|
9694
|
+
* delegated to `graph.focusElement()`, which is the obvious
|
|
9695
|
+
* call and does NOT work on these graphs. Measured: it
|
|
9696
|
+
* resolves, having computed the very offset wanted -- `[0,
|
|
9697
|
+
* 306]` for a card 306px above centre -- and the camera does
|
|
9698
|
+
* not move. `getPosition()` reads the same before and after,
|
|
9699
|
+
* and so does the card's box on screen. Three public calls do
|
|
9700
|
+
* move it, so that is what is used.
|
|
9701
|
+
*
|
|
9693
9702
|
* Guarded on every side because it runs on every wheel notch:
|
|
9694
9703
|
* a graph mid-rebuild, an anchor whose node went away with a
|
|
9695
|
-
* fold, a G6
|
|
9704
|
+
* fold, a G6 missing one of these calls -- none of those is
|
|
9696
9705
|
* an error worth a log line per notch, they are all "there is
|
|
9697
9706
|
* nothing to centre right now".
|
|
9698
9707
|
************************************************************/
|
|
9699
|
-
function yui_graph_center_on(graph, node_id) {
|
|
9708
|
+
async function yui_graph_center_on(graph, node_id) {
|
|
9700
9709
|
if (!graph || !node_id) return false;
|
|
9701
9710
|
try {
|
|
9702
9711
|
if (typeof graph.getElementData === "function" && !graph.getElementData(node_id)) return false;
|
|
9703
|
-
if (typeof graph.
|
|
9704
|
-
|
|
9712
|
+
if (typeof graph.getElementPosition !== "function" || typeof graph.getViewportByCanvas !== "function" || typeof graph.getCanvasCenter !== "function" || typeof graph.translateTo !== "function") return false;
|
|
9713
|
+
for (let i = 0; i < 3; i++) {
|
|
9714
|
+
let at = graph.getViewportByCanvas(graph.getElementPosition(node_id));
|
|
9715
|
+
let want = graph.getCanvasCenter();
|
|
9716
|
+
let dx = want[0] - at[0];
|
|
9717
|
+
let dy = want[1] - at[1];
|
|
9718
|
+
if (Math.abs(dx) < 1 && Math.abs(dy) < 1) break;
|
|
9719
|
+
let pos = graph.getPosition();
|
|
9720
|
+
await graph.translateTo([pos[0] + dx, pos[1] + dy]);
|
|
9721
|
+
}
|
|
9705
9722
|
return true;
|
|
9706
9723
|
} catch (e) {
|
|
9707
9724
|
return false;
|
|
@@ -11591,6 +11608,14 @@ function reanchor$1(gobj) {
|
|
|
11591
11608
|
yui_graph_update_anchor(gobj_read_attr(gobj, "$container"), priv.anchor_state);
|
|
11592
11609
|
}
|
|
11593
11610
|
/************************************************************
|
|
11611
|
+
* Centre on the anchor, one cycle after it was chosen.
|
|
11612
|
+
************************************************************/
|
|
11613
|
+
function ac_center_anchor$2(gobj, event, kw, src) {
|
|
11614
|
+
let priv = gobj.priv;
|
|
11615
|
+
if (priv.anchor_state === "on" && priv.anchor_id) yui_graph_center_on(priv.graph, priv.anchor_id);
|
|
11616
|
+
return 0;
|
|
11617
|
+
}
|
|
11618
|
+
/************************************************************
|
|
11594
11619
|
* Arm the anchor, or let it go.
|
|
11595
11620
|
*
|
|
11596
11621
|
* Three states and one button, so a press ADVANCES: with no
|
|
@@ -11673,7 +11698,7 @@ function ac_node_click$4(gobj, event, kw, src) {
|
|
|
11673
11698
|
priv.anchor_path = nodedata && nodedata.data ? nodedata.data.path : "";
|
|
11674
11699
|
priv.anchor_state = "on";
|
|
11675
11700
|
yui_graph_update_anchor(gobj_read_attr(gobj, "$container"), priv.anchor_state);
|
|
11676
|
-
|
|
11701
|
+
gobj_post_event(gobj, "EV_CENTER_ANCHOR", {}, gobj);
|
|
11677
11702
|
return 0;
|
|
11678
11703
|
}
|
|
11679
11704
|
if (nodedata && nodedata.data) gobj_publish_event(gobj, "EV_JSON_ITEM_CLICKED", {
|
|
@@ -11814,6 +11839,11 @@ function create_gclass$11(gclass_name) {
|
|
|
11814
11839
|
ac_toggle_anchor$2,
|
|
11815
11840
|
null
|
|
11816
11841
|
],
|
|
11842
|
+
[
|
|
11843
|
+
"EV_CENTER_ANCHOR",
|
|
11844
|
+
ac_center_anchor$2,
|
|
11845
|
+
null
|
|
11846
|
+
],
|
|
11817
11847
|
[
|
|
11818
11848
|
"EV_RESIZE",
|
|
11819
11849
|
ac_resize$2,
|
|
@@ -11845,6 +11875,7 @@ function create_gclass$11(gclass_name) {
|
|
|
11845
11875
|
["EV_CENTER", 0],
|
|
11846
11876
|
["EV_NODE_CLICK", 0],
|
|
11847
11877
|
["EV_TOGGLE_ANCHOR", 0],
|
|
11878
|
+
["EV_CENTER_ANCHOR", 0],
|
|
11848
11879
|
["EV_RESIZE", 0],
|
|
11849
11880
|
["EV_SHOW", 0],
|
|
11850
11881
|
["EV_HIDE", 0],
|
|
@@ -14482,6 +14513,14 @@ function reanchor(gobj) {
|
|
|
14482
14513
|
yui_graph_update_anchor(gobj_read_attr(gobj, "$container"), priv.anchor_state);
|
|
14483
14514
|
}
|
|
14484
14515
|
/************************************************************
|
|
14516
|
+
* Centre on the anchor, one cycle after it was chosen.
|
|
14517
|
+
************************************************************/
|
|
14518
|
+
function ac_center_anchor$1(gobj, event, kw, src) {
|
|
14519
|
+
let priv = gobj.priv;
|
|
14520
|
+
if (priv.anchor_state === "on" && priv.anchor_id) yui_graph_center_on(priv.graph, priv.anchor_id);
|
|
14521
|
+
return 0;
|
|
14522
|
+
}
|
|
14523
|
+
/************************************************************
|
|
14485
14524
|
* Arm the anchor, or let it go.
|
|
14486
14525
|
*
|
|
14487
14526
|
* Three states and one button, so a press ADVANCES: with no
|
|
@@ -14566,7 +14605,7 @@ function ac_node_click$3(gobj, event, kw, src) {
|
|
|
14566
14605
|
priv.anchor_name = node_data.full_name || "";
|
|
14567
14606
|
priv.anchor_state = "on";
|
|
14568
14607
|
yui_graph_update_anchor(gobj_read_attr(gobj, "$container"), priv.anchor_state);
|
|
14569
|
-
|
|
14608
|
+
gobj_post_event(gobj, "EV_CENTER_ANCHOR", {}, gobj);
|
|
14570
14609
|
return 0;
|
|
14571
14610
|
}
|
|
14572
14611
|
let client_x = kw.evt && kw.evt.client ? kw.evt.client.x : 0;
|
|
@@ -14650,6 +14689,7 @@ function create_gclass$9(gclass_name) {
|
|
|
14650
14689
|
["EV_CENTER", 0],
|
|
14651
14690
|
["EV_NODE_CLICK", 0],
|
|
14652
14691
|
["EV_TOGGLE_ANCHOR", 0],
|
|
14692
|
+
["EV_CENTER_ANCHOR", 0],
|
|
14653
14693
|
["EV_RESIZE", 0],
|
|
14654
14694
|
["EV_SHOW", 0],
|
|
14655
14695
|
["EV_HIDE", 0]
|
|
@@ -14714,6 +14754,11 @@ function create_gclass$9(gclass_name) {
|
|
|
14714
14754
|
ac_toggle_anchor$1,
|
|
14715
14755
|
null
|
|
14716
14756
|
],
|
|
14757
|
+
[
|
|
14758
|
+
"EV_CENTER_ANCHOR",
|
|
14759
|
+
ac_center_anchor$1,
|
|
14760
|
+
null
|
|
14761
|
+
],
|
|
14717
14762
|
[
|
|
14718
14763
|
"EV_RESIZE",
|
|
14719
14764
|
ac_resize$1,
|
|
@@ -52926,6 +52971,14 @@ function ac_zoom_reset(gobj, event, kw, src) {
|
|
|
52926
52971
|
/************************************************************
|
|
52927
52972
|
* What the anchor button says it will do next.
|
|
52928
52973
|
************************************************************/
|
|
52974
|
+
function ac_center_anchor(gobj, event, kw, src) {
|
|
52975
|
+
let priv = gobj.priv;
|
|
52976
|
+
if (priv.anchor_state === "on" && priv.anchor_id) yui_graph_center_on(priv.graph, priv.anchor_id);
|
|
52977
|
+
return 0;
|
|
52978
|
+
}
|
|
52979
|
+
/************************************************************
|
|
52980
|
+
* What the anchor button says it will do next.
|
|
52981
|
+
************************************************************/
|
|
52929
52982
|
function anchor_title(state) {
|
|
52930
52983
|
if (state === "arming") return t("click the element to centre on");
|
|
52931
52984
|
if (state === "on") return t("centred: click to release");
|
|
@@ -53144,7 +53197,7 @@ function ac_node_click$2(gobj, event, kw, src) {
|
|
|
53144
53197
|
priv.anchor_id = node_id;
|
|
53145
53198
|
priv.anchor_state = "on";
|
|
53146
53199
|
update_toolbar(gobj);
|
|
53147
|
-
|
|
53200
|
+
gobj_post_event(gobj, "EV_CENTER_ANCHOR", {}, gobj);
|
|
53148
53201
|
return 0;
|
|
53149
53202
|
}
|
|
53150
53203
|
try {
|
|
@@ -53413,6 +53466,11 @@ function create_gclass$4(gclass_name) {
|
|
|
53413
53466
|
ac_toggle_anchor,
|
|
53414
53467
|
null
|
|
53415
53468
|
],
|
|
53469
|
+
[
|
|
53470
|
+
"EV_CENTER_ANCHOR",
|
|
53471
|
+
ac_center_anchor,
|
|
53472
|
+
null
|
|
53473
|
+
],
|
|
53416
53474
|
[
|
|
53417
53475
|
"EV_TOGGLE_TOOLBARS",
|
|
53418
53476
|
ac_toggle_toolbars,
|
|
@@ -53527,6 +53585,7 @@ function create_gclass$4(gclass_name) {
|
|
|
53527
53585
|
["EV_ZOOM_OUT", 0],
|
|
53528
53586
|
["EV_ZOOM_RESET", 0],
|
|
53529
53587
|
["EV_TOGGLE_ANCHOR", 0],
|
|
53588
|
+
["EV_CENTER_ANCHOR", 0],
|
|
53530
53589
|
["EV_TOGGLE_TOOLBARS", 0],
|
|
53531
53590
|
["EV_AUTO_FIT", 0],
|
|
53532
53591
|
["EV_ZOOM_SELECTION", 0],
|
package/package.json
CHANGED
package/src/c_g6_nodes_tree.js
CHANGED
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
gobj_subscribe_event,
|
|
43
43
|
gobj_publish_event,
|
|
44
44
|
gobj_send_event,
|
|
45
|
+
gobj_post_event,
|
|
45
46
|
gobj_save_persistent_attrs,
|
|
46
47
|
clean_name,
|
|
47
48
|
sprintf,
|
|
@@ -7505,6 +7506,19 @@ function ac_zoom_reset(gobj, event, kw, src)
|
|
|
7505
7506
|
return 0;
|
|
7506
7507
|
}
|
|
7507
7508
|
|
|
7509
|
+
/************************************************************
|
|
7510
|
+
* What the anchor button says it will do next.
|
|
7511
|
+
************************************************************/
|
|
7512
|
+
function ac_center_anchor(gobj, event, kw, src)
|
|
7513
|
+
{
|
|
7514
|
+
let priv = gobj.priv;
|
|
7515
|
+
|
|
7516
|
+
if(priv.anchor_state === "on" && priv.anchor_id) {
|
|
7517
|
+
yui_graph_center_on(priv.graph, priv.anchor_id);
|
|
7518
|
+
}
|
|
7519
|
+
return 0;
|
|
7520
|
+
}
|
|
7521
|
+
|
|
7508
7522
|
/************************************************************
|
|
7509
7523
|
* What the anchor button says it will do next.
|
|
7510
7524
|
************************************************************/
|
|
@@ -7824,7 +7838,11 @@ function ac_node_click(gobj, event, kw, src)
|
|
|
7824
7838
|
priv.anchor_id = node_id;
|
|
7825
7839
|
priv.anchor_state = "on";
|
|
7826
7840
|
update_toolbar(gobj);
|
|
7827
|
-
|
|
7841
|
+
|
|
7842
|
+
/* POSTED, not made here: a camera move issued inside G6's click
|
|
7843
|
+
* dispatch is swallowed -- see the note in yui_graph_center_on.
|
|
7844
|
+
* An event to itself and not a timer: a deferral is not a TIME. */
|
|
7845
|
+
gobj_post_event(gobj, "EV_CENTER_ANCHOR", {}, gobj);
|
|
7828
7846
|
return 0;
|
|
7829
7847
|
}
|
|
7830
7848
|
|
|
@@ -8140,6 +8158,7 @@ function create_gclass(gclass_name)
|
|
|
8140
8158
|
["EV_ZOOM_OUT", ac_zoom_out, null],
|
|
8141
8159
|
["EV_ZOOM_RESET", ac_zoom_reset, null],
|
|
8142
8160
|
["EV_TOGGLE_ANCHOR", ac_toggle_anchor, null],
|
|
8161
|
+
["EV_CENTER_ANCHOR", ac_center_anchor, null],
|
|
8143
8162
|
["EV_TOGGLE_TOOLBARS", ac_toggle_toolbars, null],
|
|
8144
8163
|
["EV_AUTO_FIT", ac_auto_fit, null],
|
|
8145
8164
|
["EV_ZOOM_SELECTION", ac_zoom_selection, null],
|
|
@@ -8190,6 +8209,7 @@ function create_gclass(gclass_name)
|
|
|
8190
8209
|
["EV_ZOOM_OUT", 0],
|
|
8191
8210
|
["EV_ZOOM_RESET", 0],
|
|
8192
8211
|
["EV_TOGGLE_ANCHOR", 0],
|
|
8212
|
+
["EV_CENTER_ANCHOR", 0],
|
|
8193
8213
|
["EV_TOGGLE_TOOLBARS", 0],
|
|
8194
8214
|
["EV_AUTO_FIT", 0],
|
|
8195
8215
|
["EV_ZOOM_SELECTION", 0],
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
gobj_read_attr,
|
|
22
22
|
gobj_write_attr,
|
|
23
23
|
gobj_send_event,
|
|
24
|
+
gobj_post_event,
|
|
24
25
|
gobj_write_str_attr,
|
|
25
26
|
gobj_read_str_attr,
|
|
26
27
|
gobj_publish_event,
|
|
@@ -2000,6 +2001,19 @@ function reanchor(gobj)
|
|
|
2000
2001
|
yui_graph_update_anchor(gobj_read_attr(gobj, "$container"), priv.anchor_state);
|
|
2001
2002
|
}
|
|
2002
2003
|
|
|
2004
|
+
/************************************************************
|
|
2005
|
+
* Centre on the anchor, one cycle after it was chosen.
|
|
2006
|
+
************************************************************/
|
|
2007
|
+
function ac_center_anchor(gobj, event, kw, src)
|
|
2008
|
+
{
|
|
2009
|
+
let priv = gobj.priv;
|
|
2010
|
+
|
|
2011
|
+
if(priv.anchor_state === "on" && priv.anchor_id) {
|
|
2012
|
+
yui_graph_center_on(priv.graph, priv.anchor_id);
|
|
2013
|
+
}
|
|
2014
|
+
return 0;
|
|
2015
|
+
}
|
|
2016
|
+
|
|
2003
2017
|
/************************************************************
|
|
2004
2018
|
* Arm the anchor, or let it go.
|
|
2005
2019
|
*
|
|
@@ -2125,7 +2139,11 @@ function ac_node_click(gobj, event, kw, src)
|
|
|
2125
2139
|
priv.anchor_name = node_data.full_name || "";
|
|
2126
2140
|
priv.anchor_state = "on";
|
|
2127
2141
|
yui_graph_update_anchor(gobj_read_attr(gobj, "$container"), priv.anchor_state);
|
|
2128
|
-
|
|
2142
|
+
|
|
2143
|
+
/* POSTED, not made here: a camera move issued inside G6's click
|
|
2144
|
+
* dispatch is swallowed -- see the note in yui_graph_center_on.
|
|
2145
|
+
* An event to itself and not a timer: a deferral is not a TIME. */
|
|
2146
|
+
gobj_post_event(gobj, "EV_CENTER_ANCHOR", {}, gobj);
|
|
2129
2147
|
return 0;
|
|
2130
2148
|
}
|
|
2131
2149
|
|
|
@@ -2255,6 +2273,7 @@ function create_gclass(gclass_name)
|
|
|
2255
2273
|
["EV_CENTER", ac_center, null],
|
|
2256
2274
|
["EV_NODE_CLICK", ac_node_click, null],
|
|
2257
2275
|
["EV_TOGGLE_ANCHOR", ac_toggle_anchor, null],
|
|
2276
|
+
["EV_CENTER_ANCHOR", ac_center_anchor, null],
|
|
2258
2277
|
["EV_RESIZE", ac_resize, null],
|
|
2259
2278
|
["EV_SHOW", ac_show, null],
|
|
2260
2279
|
["EV_HIDE", ac_hide, null],
|
|
@@ -2277,6 +2296,7 @@ function create_gclass(gclass_name)
|
|
|
2277
2296
|
["EV_CENTER", 0],
|
|
2278
2297
|
["EV_NODE_CLICK", 0],
|
|
2279
2298
|
["EV_TOGGLE_ANCHOR", 0],
|
|
2299
|
+
["EV_CENTER_ANCHOR", 0],
|
|
2280
2300
|
["EV_RESIZE", 0],
|
|
2281
2301
|
["EV_SHOW", 0],
|
|
2282
2302
|
["EV_HIDE", 0],
|
package/src/c_yui_json_graph.js
CHANGED
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
gobj_read_attr,
|
|
26
26
|
gobj_write_attr,
|
|
27
27
|
gobj_send_event,
|
|
28
|
+
gobj_post_event,
|
|
28
29
|
gobj_find_service,
|
|
29
30
|
gobj_short_name,
|
|
30
31
|
gobj_read_str_attr,
|
|
@@ -1819,6 +1820,19 @@ function reanchor(gobj)
|
|
|
1819
1820
|
yui_graph_update_anchor(gobj_read_attr(gobj, "$container"), priv.anchor_state);
|
|
1820
1821
|
}
|
|
1821
1822
|
|
|
1823
|
+
/************************************************************
|
|
1824
|
+
* Centre on the anchor, one cycle after it was chosen.
|
|
1825
|
+
************************************************************/
|
|
1826
|
+
function ac_center_anchor(gobj, event, kw, src)
|
|
1827
|
+
{
|
|
1828
|
+
let priv = gobj.priv;
|
|
1829
|
+
|
|
1830
|
+
if(priv.anchor_state === "on" && priv.anchor_id) {
|
|
1831
|
+
yui_graph_center_on(priv.graph, priv.anchor_id);
|
|
1832
|
+
}
|
|
1833
|
+
return 0;
|
|
1834
|
+
}
|
|
1835
|
+
|
|
1822
1836
|
/************************************************************
|
|
1823
1837
|
* Arm the anchor, or let it go.
|
|
1824
1838
|
*
|
|
@@ -1931,7 +1945,22 @@ function ac_node_click(gobj, event, kw, src)
|
|
|
1931
1945
|
priv.anchor_path = (nodedata && nodedata.data)? nodedata.data.path: "";
|
|
1932
1946
|
priv.anchor_state = "on";
|
|
1933
1947
|
yui_graph_update_anchor(gobj_read_attr(gobj, "$container"), priv.anchor_state);
|
|
1934
|
-
|
|
1948
|
+
|
|
1949
|
+
/*
|
|
1950
|
+
* The camera move is POSTED, not made here.
|
|
1951
|
+
*
|
|
1952
|
+
* A translate issued inside G6's click dispatch is swallowed:
|
|
1953
|
+
* measured, the call computes the right offset, resolves, and
|
|
1954
|
+
* the camera reads the same before and after -- while the very
|
|
1955
|
+
* same call from a zoom action centres the node exactly. So the
|
|
1956
|
+
* first thing an anchor did was nothing, which is what "I don't
|
|
1957
|
+
* see how it works" looks like.
|
|
1958
|
+
*
|
|
1959
|
+
* An event to itself and not a timer: a deferral is not a TIME,
|
|
1960
|
+
* and writing it as one costs the name of what happens next in
|
|
1961
|
+
* the trace.
|
|
1962
|
+
*/
|
|
1963
|
+
gobj_post_event(gobj, "EV_CENTER_ANCHOR", {}, gobj);
|
|
1935
1964
|
return 0;
|
|
1936
1965
|
}
|
|
1937
1966
|
|
|
@@ -2057,6 +2086,7 @@ function create_gclass(gclass_name)
|
|
|
2057
2086
|
["EV_CENTER", ac_center, null],
|
|
2058
2087
|
["EV_NODE_CLICK", ac_node_click, null],
|
|
2059
2088
|
["EV_TOGGLE_ANCHOR", ac_toggle_anchor, null],
|
|
2089
|
+
["EV_CENTER_ANCHOR", ac_center_anchor, null],
|
|
2060
2090
|
["EV_RESIZE", ac_resize, null],
|
|
2061
2091
|
["EV_SHOW", ac_show, null],
|
|
2062
2092
|
["EV_HIDE", ac_hide, null],
|
|
@@ -2081,6 +2111,7 @@ function create_gclass(gclass_name)
|
|
|
2081
2111
|
["EV_CENTER", 0],
|
|
2082
2112
|
["EV_NODE_CLICK", 0],
|
|
2083
2113
|
["EV_TOGGLE_ANCHOR", 0],
|
|
2114
|
+
["EV_CENTER_ANCHOR", 0],
|
|
2084
2115
|
["EV_RESIZE", 0],
|
|
2085
2116
|
["EV_SHOW", 0],
|
|
2086
2117
|
["EV_HIDE", 0],
|
package/src/lib_graph.css
CHANGED
|
@@ -14,7 +14,11 @@
|
|
|
14
14
|
.color_create_state {
|
|
15
15
|
color: #1890ff !important;
|
|
16
16
|
}
|
|
17
|
-
.
|
|
17
|
+
/* Orange is "needs attention, waiting on you". A toggle that is armed
|
|
18
|
+
* and waiting for its target is exactly that and not a submit, so it
|
|
19
|
+
* takes the same colour under a name that says so. */
|
|
20
|
+
.color_submit_state,
|
|
21
|
+
.color_pending_state {
|
|
18
22
|
color: #fa8c16 !important;
|
|
19
23
|
}
|
|
20
24
|
.color_active_state {
|
|
@@ -237,6 +241,28 @@
|
|
|
237
241
|
border-radius: 4px;
|
|
238
242
|
}
|
|
239
243
|
|
|
244
|
+
/*
|
|
245
|
+
* The same pressed look for a toggle in a DOM toolbar.
|
|
246
|
+
*
|
|
247
|
+
* `pressed_state` was written for the G6 plugin toolbar and styled ONLY
|
|
248
|
+
* there, so the two toolbars built by `yui_graph_camera.js` were given
|
|
249
|
+
* the class and no rule: pressing the button changed nothing on screen,
|
|
250
|
+
* which from the outside is indistinguishable from a button that does
|
|
251
|
+
* not work.
|
|
252
|
+
*
|
|
253
|
+
* `border-color` as well as the fill, or Bulma's own border stays and
|
|
254
|
+
* the button reads as outlined-and-filled, which is neither state.
|
|
255
|
+
* The `:hover` half is the same guard as above: without it, hovering a
|
|
256
|
+
* pressed button hands it back to Bulma's rule and the toggle appears
|
|
257
|
+
* to switch off under the pointer.
|
|
258
|
+
*/
|
|
259
|
+
.button.pressed_state,
|
|
260
|
+
.button.pressed_state:hover {
|
|
261
|
+
background-color: var(--bulma-text, #2e333d);
|
|
262
|
+
color: var(--bulma-background, #ffffff);
|
|
263
|
+
border-color: var(--bulma-text, #2e333d);
|
|
264
|
+
}
|
|
265
|
+
|
|
240
266
|
/*
|
|
241
267
|
* Touch: the context menu is a LIST OF COMMANDS, and G6 sizes its
|
|
242
268
|
* rows with `padding: 8px 12px` -- 34px, which is a mouse row. The
|
package/src/yui_graph_camera.js
CHANGED
|
@@ -191,7 +191,14 @@ export function yui_graph_update_anchor($container, state)
|
|
|
191
191
|
if(!$btn) {
|
|
192
192
|
return; /* a toolbar without the control: nothing to paint */
|
|
193
193
|
}
|
|
194
|
-
|
|
194
|
+
/*
|
|
195
|
+
* PRESSED is "on", and only "on": pressed is the state the control
|
|
196
|
+
* is IN, and while it is arming it is not in that state yet, it is
|
|
197
|
+
* asking for something. That gets the attention colour instead --
|
|
198
|
+
* which also keeps the two off each other, since an orange glyph on
|
|
199
|
+
* the pressed fill is orange on near-white in dark and unreadable.
|
|
200
|
+
*/
|
|
201
|
+
set_pressed_state($container, '.EV_TOGGLE_ANCHOR', state === "on");
|
|
195
202
|
$btn.classList.toggle('color_pending_state', state === "arming");
|
|
196
203
|
$btn.setAttribute("aria-pressed", (state === "on")? "true": "false");
|
|
197
204
|
|
|
@@ -211,13 +218,22 @@ export function yui_graph_update_anchor($container, state)
|
|
|
211
218
|
* the zoom is what the reader asked for, the centring is what
|
|
212
219
|
* keeps the thing they are reading under their eyes.
|
|
213
220
|
*
|
|
221
|
+
* The translate is computed and applied HERE rather than
|
|
222
|
+
* delegated to `graph.focusElement()`, which is the obvious
|
|
223
|
+
* call and does NOT work on these graphs. Measured: it
|
|
224
|
+
* resolves, having computed the very offset wanted -- `[0,
|
|
225
|
+
* 306]` for a card 306px above centre -- and the camera does
|
|
226
|
+
* not move. `getPosition()` reads the same before and after,
|
|
227
|
+
* and so does the card's box on screen. Three public calls do
|
|
228
|
+
* move it, so that is what is used.
|
|
229
|
+
*
|
|
214
230
|
* Guarded on every side because it runs on every wheel notch:
|
|
215
231
|
* a graph mid-rebuild, an anchor whose node went away with a
|
|
216
|
-
* fold, a G6
|
|
232
|
+
* fold, a G6 missing one of these calls -- none of those is
|
|
217
233
|
* an error worth a log line per notch, they are all "there is
|
|
218
234
|
* nothing to centre right now".
|
|
219
235
|
************************************************************/
|
|
220
|
-
export function yui_graph_center_on(graph, node_id)
|
|
236
|
+
export async function yui_graph_center_on(graph, node_id)
|
|
221
237
|
{
|
|
222
238
|
if(!graph || !node_id) {
|
|
223
239
|
return false;
|
|
@@ -226,10 +242,50 @@ export function yui_graph_center_on(graph, node_id)
|
|
|
226
242
|
if(typeof graph.getElementData === "function" && !graph.getElementData(node_id)) {
|
|
227
243
|
return false;
|
|
228
244
|
}
|
|
229
|
-
if(typeof graph.
|
|
245
|
+
if(typeof graph.getElementPosition !== "function" ||
|
|
246
|
+
typeof graph.getViewportByCanvas !== "function" ||
|
|
247
|
+
typeof graph.getCanvasCenter !== "function" ||
|
|
248
|
+
typeof graph.translateTo !== "function") {
|
|
230
249
|
return false;
|
|
231
250
|
}
|
|
232
|
-
|
|
251
|
+
|
|
252
|
+
/*
|
|
253
|
+
* MEASURE, MOVE, MEASURE AGAIN -- up to three times.
|
|
254
|
+
*
|
|
255
|
+
* Not the arithmetic anybody would write first, and the reason
|
|
256
|
+
* is worth keeping. The obvious call is `graph.focusElement()`,
|
|
257
|
+
* which computes the very offset wanted and then does not move
|
|
258
|
+
* the camera at all: measured on the JSON graph it resolves
|
|
259
|
+
* with `getPosition()` reading identical before and after.
|
|
260
|
+
* `translateBy()` (a RELATIVE transform) behaves the same way.
|
|
261
|
+
* `translateTo()` (ABSOLUTE) does move it -- and the units of
|
|
262
|
+
* its argument are not viewport pixels at any zoom but 1, so
|
|
263
|
+
* one shot lands short or long by a factor nobody should have
|
|
264
|
+
* to name.
|
|
265
|
+
*
|
|
266
|
+
* Probing for that factor gives noise: the camera settles
|
|
267
|
+
* asynchronously, so a position read straight after a
|
|
268
|
+
* translate is a value halfway through. AWAITING each move and
|
|
269
|
+
* measuring again needs no factor at all -- the direction is
|
|
270
|
+
* right, so the residual falls to nothing in two or three
|
|
271
|
+
* passes, and a graph whose maths change under us keeps
|
|
272
|
+
* working.
|
|
273
|
+
*
|
|
274
|
+
* The 1px floor is what stops it converging forever on the
|
|
275
|
+
* rounding.
|
|
276
|
+
*/
|
|
277
|
+
for(let i = 0; i < 3; i++) {
|
|
278
|
+
let at = graph.getViewportByCanvas(graph.getElementPosition(node_id));
|
|
279
|
+
let want = graph.getCanvasCenter();
|
|
280
|
+
let dx = want[0] - at[0];
|
|
281
|
+
let dy = want[1] - at[1];
|
|
282
|
+
|
|
283
|
+
if(Math.abs(dx) < 1 && Math.abs(dy) < 1) {
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
let pos = graph.getPosition();
|
|
287
|
+
await graph.translateTo([pos[0] + dx, pos[1] + dy]);
|
|
288
|
+
}
|
|
233
289
|
return true;
|
|
234
290
|
} catch(e) {
|
|
235
291
|
return false; /* the element is gone, or the graph is between renders */
|