@yuneta/gobj-ui 7.23.82 → 7.23.84
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 +40 -11
- package/dist/gobj-ui.cjs.js +266 -126
- package/dist/gobj-ui.es.js +266 -126
- package/package.json +1 -1
- package/src/c_g6_nodes_tree.js +162 -38
- package/src/c_yui_treedb_graph.js +97 -29
- package/src/treedb_layout.js +55 -16
- package/src/treedb_layout.test.js +15 -0
package/package.json
CHANGED
package/src/c_g6_nodes_tree.js
CHANGED
|
@@ -58,6 +58,7 @@ import {
|
|
|
58
58
|
gobj_short_name,
|
|
59
59
|
gobj_is_destroying,
|
|
60
60
|
gobj_subscribe_event,
|
|
61
|
+
gobj_unsubscribe_event,
|
|
61
62
|
gobj_publish_event,
|
|
62
63
|
gobj_send_event,
|
|
63
64
|
gobj_post_event,
|
|
@@ -143,7 +144,7 @@ import {
|
|
|
143
144
|
} from '@antv/g6';
|
|
144
145
|
|
|
145
146
|
import {Circle as CircleGeometry, Rect as RectGeometry} from '@antv/g';
|
|
146
|
-
import
|
|
147
|
+
import {t} from "i18next";
|
|
147
148
|
|
|
148
149
|
import {inject_svg_icons} from "./lib_icons.js";
|
|
149
150
|
import {ensure_drag_canvas_patch} from "./g6_drag_canvas_touch.js";
|
|
@@ -157,6 +158,7 @@ import {
|
|
|
157
158
|
consume_long_press_click,
|
|
158
159
|
} from "./g6_touch_gestures.js";
|
|
159
160
|
import {yui_theme_now, yui_watch_theme} from "./yui_theme.js";
|
|
161
|
+
import {yui_shell_of} from "./c_yui_shell.js";
|
|
160
162
|
|
|
161
163
|
/***************************************************************
|
|
162
164
|
* YuiToolbar — G6 Toolbar subclass that adds per-item className
|
|
@@ -465,11 +467,14 @@ let PRIVATE_DATA = {
|
|
|
465
467
|
_edge_icon_el: null, // floating properties icon element
|
|
466
468
|
_edge_delete_el: null, // floating delete icon element for edge
|
|
467
469
|
_edge_popover_el: null, // edge properties popover element
|
|
470
|
+
_edge_preview_undo: null, // ...and how to undo what it previewed
|
|
468
471
|
_port_icon_el: null, // floating port properties icon element
|
|
469
472
|
_port_popover_el: null, // port properties popover element
|
|
473
|
+
_port_preview_undo: null, // ...and how to undo what it previewed
|
|
470
474
|
_node_icon_el: null, // floating node properties icon element
|
|
471
475
|
_node_delete_el: null, // floating delete icon element for node
|
|
472
476
|
_node_popover_el: null, // node properties popover element
|
|
477
|
+
_node_preview_undo: null, // ...and how to undo what it previewed
|
|
473
478
|
_node_detail_el: null, // read-only detail popover (on click)
|
|
474
479
|
_detail_node_id: null, // node id the detail popover is showing
|
|
475
480
|
_delete_confirm_el: null, // delete confirmation popover
|
|
@@ -613,6 +618,18 @@ function mt_writing(gobj, path)
|
|
|
613
618
|
***************************************************************/
|
|
614
619
|
function mt_start(gobj)
|
|
615
620
|
{
|
|
621
|
+
/* A language change reaches the toolbars and the `+N` chips as
|
|
622
|
+
* the shell's EVENT, not as a raw i18next listener: what the
|
|
623
|
+
* toolbar draws and what a chip says are built here, out of
|
|
624
|
+
* reach of refresh_language(), so somebody has to repaint them
|
|
625
|
+
* -- and that somebody is an action of this machine, where the
|
|
626
|
+
* `machine` trace can see it. Same wiring as C_YUI_PERIOD and
|
|
627
|
+
* C_YUI_GOBJ_TREE_JS. */
|
|
628
|
+
let shell = yui_shell_of(gobj);
|
|
629
|
+
if(shell) {
|
|
630
|
+
gobj_subscribe_event(shell, "EV_LANGUAGE_CHANGED", {}, gobj);
|
|
631
|
+
}
|
|
632
|
+
|
|
616
633
|
return 0;
|
|
617
634
|
}
|
|
618
635
|
|
|
@@ -621,6 +638,11 @@ function mt_start(gobj)
|
|
|
621
638
|
***************************************************************/
|
|
622
639
|
function mt_stop(gobj)
|
|
623
640
|
{
|
|
641
|
+
let shell = yui_shell_of(gobj);
|
|
642
|
+
if(shell) {
|
|
643
|
+
gobj_unsubscribe_event(shell, "EV_LANGUAGE_CHANGED", {}, gobj);
|
|
644
|
+
}
|
|
645
|
+
|
|
624
646
|
return 0;
|
|
625
647
|
}
|
|
626
648
|
|
|
@@ -631,11 +653,6 @@ function mt_destroy(gobj)
|
|
|
631
653
|
{
|
|
632
654
|
let priv = gobj.priv;
|
|
633
655
|
|
|
634
|
-
if(priv._on_language_changed) {
|
|
635
|
-
i18next.off('languageChanged', priv._on_language_changed);
|
|
636
|
-
priv._on_language_changed = null;
|
|
637
|
-
}
|
|
638
|
-
|
|
639
656
|
uninstall_fold_listener(gobj);
|
|
640
657
|
|
|
641
658
|
if(priv._on_pointerdown_focus) {
|
|
@@ -1022,12 +1039,6 @@ function configure_events(gobj)
|
|
|
1022
1039
|
}
|
|
1023
1040
|
});
|
|
1024
1041
|
|
|
1025
|
-
// Re-render G6 toolbars (and the `+N` chips' titles) when language changes
|
|
1026
|
-
priv._on_language_changed = () => {
|
|
1027
|
-
update_toolbar(gobj);
|
|
1028
|
-
repaint_more_chips(gobj);
|
|
1029
|
-
};
|
|
1030
|
-
i18next.on('languageChanged', priv._on_language_changed);
|
|
1031
1042
|
|
|
1032
1043
|
/* Clicking a CARD is clicking a DOM element inside the container,
|
|
1033
1044
|
* and that takes the keyboard away from G6's canvas -- the only
|
|
@@ -1865,6 +1876,17 @@ const LR_LAYOUTS = ["dagre"];
|
|
|
1865
1876
|
* toolbar's +/-, and the two-finger pinch of g6_touch_gestures.
|
|
1866
1877
|
* `enable` on the scroll keeps the two apart: a Ctrl wheel is
|
|
1867
1878
|
* the zoom's, so the scroll stands aside for it.
|
|
1879
|
+
*
|
|
1880
|
+
* And the two have to name the SAME key, or the gesture falls
|
|
1881
|
+
* between them: the scroll stood aside for Meta as well, while
|
|
1882
|
+
* the zoom listened for Control alone, so Cmd + wheel neither
|
|
1883
|
+
* scrolled nor zoomed. It is ONE key and not two because a G6
|
|
1884
|
+
* `trigger` is a CHORD, not a list of alternatives -- its
|
|
1885
|
+
* `Shortcut.match()` compares the held keys to the bound ones
|
|
1886
|
+
* as a SET, so ["Control", "Meta"] means both keys down at
|
|
1887
|
+
* once. Control it is, on every platform: it is what a
|
|
1888
|
+
* trackpad pinch arrives as, so a Mac keeps its pinch and
|
|
1889
|
+
* gains nothing to press by mistake.
|
|
1868
1890
|
************************************************************/
|
|
1869
1891
|
function camera_behaviors()
|
|
1870
1892
|
{
|
|
@@ -1872,7 +1894,7 @@ function camera_behaviors()
|
|
|
1872
1894
|
{
|
|
1873
1895
|
type: "scroll-canvas",
|
|
1874
1896
|
key: "scroll-canvas",
|
|
1875
|
-
enable: (event) => !(event &&
|
|
1897
|
+
enable: (event) => !(event && event.ctrlKey),
|
|
1876
1898
|
},
|
|
1877
1899
|
{
|
|
1878
1900
|
type: "zoom-canvas",
|
|
@@ -4046,6 +4068,42 @@ function hide_overlay(gobj, ...keys)
|
|
|
4046
4068
|
/************************************************************
|
|
4047
4069
|
* Enable the save button (mark graph as dirty).
|
|
4048
4070
|
************************************************************/
|
|
4071
|
+
/************************************************************
|
|
4072
|
+
* A popover that PREVIEWS its changes owes an undo.
|
|
4073
|
+
*
|
|
4074
|
+
* What the preview writes is not the reader's answer until
|
|
4075
|
+
* `apply` is pressed, and `cancel` used to be the only way
|
|
4076
|
+
* back: every other way out of the popover -- a click on the
|
|
4077
|
+
* canvas, the icon pressed again, the element going away --
|
|
4078
|
+
* left the preview standing on the element, and the next Save
|
|
4079
|
+
* wrote it to `__graphs__`. So the undo is kept beside the
|
|
4080
|
+
* popover and run by whoever hides it; `apply` drops it first,
|
|
4081
|
+
* because then the preview IS the answer.
|
|
4082
|
+
************************************************************/
|
|
4083
|
+
function set_preview_undo(gobj, key, undo)
|
|
4084
|
+
{
|
|
4085
|
+
gobj.priv[key] = undo;
|
|
4086
|
+
}
|
|
4087
|
+
|
|
4088
|
+
function drop_preview_undo(gobj, key)
|
|
4089
|
+
{
|
|
4090
|
+
gobj.priv[key] = null;
|
|
4091
|
+
}
|
|
4092
|
+
|
|
4093
|
+
function run_preview_undo(gobj, key)
|
|
4094
|
+
{
|
|
4095
|
+
let undo = gobj.priv[key];
|
|
4096
|
+
gobj.priv[key] = null;
|
|
4097
|
+
if(!undo || gobj_is_destroying(gobj)) {
|
|
4098
|
+
return;
|
|
4099
|
+
}
|
|
4100
|
+
try {
|
|
4101
|
+
undo();
|
|
4102
|
+
} catch(e) {
|
|
4103
|
+
log_error(`${gobj_short_name(gobj)}: cannot undo the preview: ${e}`);
|
|
4104
|
+
}
|
|
4105
|
+
}
|
|
4106
|
+
|
|
4049
4107
|
function mark_graph_dirty(gobj)
|
|
4050
4108
|
{
|
|
4051
4109
|
let $container = gobj_read_attr(gobj, "$container");
|
|
@@ -4990,6 +5048,34 @@ function port_hit_slop_world(graph)
|
|
|
4990
5048
|
return slop / zoom;
|
|
4991
5049
|
}
|
|
4992
5050
|
|
|
5051
|
+
/************************************************************
|
|
5052
|
+
* Whether a point landed on a port, by the port's SHAPE.
|
|
5053
|
+
*
|
|
5054
|
+
* A port was a circle and the test was a radius; since 7.23.81
|
|
5055
|
+
* it can be a square, a diamond or a triangle too, and a circle
|
|
5056
|
+
* around a diamond answers for the air off its corners while
|
|
5057
|
+
* missing the middle of its edges. `r` is the drawn radius with
|
|
5058
|
+
* the hit slop already added, and the shapes are the ones
|
|
5059
|
+
* TreedbCard.drawPortShapes() draws from it.
|
|
5060
|
+
*
|
|
5061
|
+
* dx, dy the point, relative to the port's centre
|
|
5062
|
+
************************************************************/
|
|
5063
|
+
function port_shape_hit(shape, dx, dy, r)
|
|
5064
|
+
{
|
|
5065
|
+
switch(shape) {
|
|
5066
|
+
case 'square':
|
|
5067
|
+
return Math.abs(dx) <= r && Math.abs(dy) <= r;
|
|
5068
|
+
case 'diamond':
|
|
5069
|
+
return Math.abs(dx) + Math.abs(dy) <= r;
|
|
5070
|
+
case 'triangle':
|
|
5071
|
+
/* (0,-r), (r,r), (-r,r): under the base and inside the
|
|
5072
|
+
* two slanted sides, which meet at 2|x| - y = r. */
|
|
5073
|
+
return dy <= r && (2 * Math.abs(dx) - dy) <= r;
|
|
5074
|
+
default:
|
|
5075
|
+
return Math.hypot(dx, dy) <= r;
|
|
5076
|
+
}
|
|
5077
|
+
}
|
|
5078
|
+
|
|
4993
5079
|
/************************************************************
|
|
4994
5080
|
* Detect if a click in canvas coordinates hits a port.
|
|
4995
5081
|
* Returns the port key string, or null if no port hit.
|
|
@@ -5021,8 +5107,9 @@ function detect_port_click(gobj, node_id, canvasX, canvasY)
|
|
|
5021
5107
|
let dist = Math.sqrt(dx * dx + dy * dy);
|
|
5022
5108
|
|
|
5023
5109
|
/* Nearest wins, so the enlarged areas of two ports
|
|
5024
|
-
* overlapping is not a tie -- it is the closer one.
|
|
5025
|
-
|
|
5110
|
+
* overlapping is not a tie -- it is the closer one. The
|
|
5111
|
+
* distance ranks them; the SHAPE says who is in the running. */
|
|
5112
|
+
if(port_shape_hit(ports[i].shape, dx, dy, r + slop) && dist < best_dist) {
|
|
5026
5113
|
best_dist = dist;
|
|
5027
5114
|
best_key = ports[i].key;
|
|
5028
5115
|
}
|
|
@@ -5240,6 +5327,7 @@ function toggle_port_popover(gobj)
|
|
|
5240
5327
|
|
|
5241
5328
|
function hide_port_popover(gobj)
|
|
5242
5329
|
{
|
|
5330
|
+
run_preview_undo(gobj, '_port_preview_undo');
|
|
5243
5331
|
hide_overlay(gobj, '_port_popover_el');
|
|
5244
5332
|
}
|
|
5245
5333
|
|
|
@@ -5280,6 +5368,17 @@ function show_port_popover(gobj)
|
|
|
5280
5368
|
xy.x + floating_popover_dx(), xy.y, 'g6-port-popover', '#d9d9d9', 180
|
|
5281
5369
|
);
|
|
5282
5370
|
|
|
5371
|
+
/* What the preview writes on this port, undone: whoever hides
|
|
5372
|
+
* the popover without applying runs it (see set_preview_undo). */
|
|
5373
|
+
let undo_port = () => {
|
|
5374
|
+
graph.updateNodeData([{id: node_id, style: {
|
|
5375
|
+
ports: ports_with(nodeData.style.ports, port_key, {shape: orig_shape, r: orig_r}),
|
|
5376
|
+
}}]);
|
|
5377
|
+
graph.draw().then(() => {
|
|
5378
|
+
update_port_resize_handles_position(gobj);
|
|
5379
|
+
});
|
|
5380
|
+
};
|
|
5381
|
+
|
|
5283
5382
|
/* Live preview on THIS port; the others wait for apply. */
|
|
5284
5383
|
function preview_port() {
|
|
5285
5384
|
let r = parseInt(rInput.value) || orig_r;
|
|
@@ -5313,13 +5412,7 @@ function show_port_popover(gobj)
|
|
|
5313
5412
|
text: 'cancel',
|
|
5314
5413
|
style: BTN_STYLE_CANCEL,
|
|
5315
5414
|
onClick: () => {
|
|
5316
|
-
|
|
5317
|
-
ports: ports_with(nodeData.style.ports, port_key, {shape: orig_shape, r: orig_r}),
|
|
5318
|
-
}}]);
|
|
5319
|
-
graph.draw().then(() => {
|
|
5320
|
-
update_port_resize_handles_position(gobj);
|
|
5321
|
-
});
|
|
5322
|
-
hide_port_popover(gobj);
|
|
5415
|
+
hide_port_popover(gobj); /* which undoes the preview */
|
|
5323
5416
|
},
|
|
5324
5417
|
},
|
|
5325
5418
|
{
|
|
@@ -5327,6 +5420,7 @@ function show_port_popover(gobj)
|
|
|
5327
5420
|
style: 'flex:1;padding:6px;background:#1890ff;color:#fff;border:none;' +
|
|
5328
5421
|
'border-radius:4px;cursor:pointer;font-size:13px;font-weight:500;',
|
|
5329
5422
|
onClick: () => {
|
|
5423
|
+
drop_preview_undo(gobj, '_port_preview_undo');
|
|
5330
5424
|
apply_port_properties(gobj, node_id, port_key,
|
|
5331
5425
|
shapeSelect.value, parseInt(rInput.value) || orig_r, scopeSelect.value
|
|
5332
5426
|
);
|
|
@@ -5336,6 +5430,7 @@ function show_port_popover(gobj)
|
|
|
5336
5430
|
|
|
5337
5431
|
priv.$container.appendChild(popover);
|
|
5338
5432
|
priv._port_popover_el = popover;
|
|
5433
|
+
set_preview_undo(gobj, '_port_preview_undo', undo_port);
|
|
5339
5434
|
clamp_popover_position(gobj, popover);
|
|
5340
5435
|
}
|
|
5341
5436
|
|
|
@@ -6184,6 +6279,12 @@ function show_edge_popover(gobj)
|
|
|
6184
6279
|
'g6-edge-popover', '#d9d9d9', 180
|
|
6185
6280
|
);
|
|
6186
6281
|
|
|
6282
|
+
/* What the preview writes, undone (see set_preview_undo). */
|
|
6283
|
+
let undo_edge = () => {
|
|
6284
|
+
graph.updateEdgeData([{ id: edge_id, style: { lineWidth: origLW, stroke: origStroke } }]);
|
|
6285
|
+
graph.draw();
|
|
6286
|
+
};
|
|
6287
|
+
|
|
6187
6288
|
// Live preview: update the selected edge in real time
|
|
6188
6289
|
function preview_edge() {
|
|
6189
6290
|
let lw = parseInt(lwInput.value) || 2;
|
|
@@ -6213,9 +6314,7 @@ function show_edge_popover(gobj)
|
|
|
6213
6314
|
text: 'cancel',
|
|
6214
6315
|
style: BTN_STYLE_CANCEL,
|
|
6215
6316
|
onClick: () => {
|
|
6216
|
-
|
|
6217
|
-
graph.draw();
|
|
6218
|
-
deselect_edge(gobj);
|
|
6317
|
+
deselect_edge(gobj); /* which undoes the preview */
|
|
6219
6318
|
},
|
|
6220
6319
|
},
|
|
6221
6320
|
{
|
|
@@ -6223,6 +6322,7 @@ function show_edge_popover(gobj)
|
|
|
6223
6322
|
style: 'flex:1;padding:6px;background:#52c41a;color:#fff;border:none;' +
|
|
6224
6323
|
'border-radius:4px;cursor:pointer;font-size:13px;font-weight:500;',
|
|
6225
6324
|
onClick: () => {
|
|
6325
|
+
drop_preview_undo(gobj, '_edge_preview_undo');
|
|
6226
6326
|
apply_edge_properties(gobj, edge_id,
|
|
6227
6327
|
parseInt(lwInput.value) || 2,
|
|
6228
6328
|
colorInput.value,
|
|
@@ -6234,6 +6334,7 @@ function show_edge_popover(gobj)
|
|
|
6234
6334
|
|
|
6235
6335
|
priv.$container.appendChild(popover);
|
|
6236
6336
|
priv._edge_popover_el = popover;
|
|
6337
|
+
set_preview_undo(gobj, '_edge_preview_undo', undo_edge);
|
|
6237
6338
|
|
|
6238
6339
|
// Clamp popover inside the container
|
|
6239
6340
|
clamp_popover_position(gobj, popover);
|
|
@@ -6278,6 +6379,7 @@ function clamp_popover_position(gobj, popover)
|
|
|
6278
6379
|
|
|
6279
6380
|
function hide_edge_popover(gobj)
|
|
6280
6381
|
{
|
|
6382
|
+
run_preview_undo(gobj, '_edge_preview_undo');
|
|
6281
6383
|
hide_overlay(gobj, '_edge_popover_el');
|
|
6282
6384
|
}
|
|
6283
6385
|
|
|
@@ -6404,6 +6506,22 @@ function show_node_popover(gobj)
|
|
|
6404
6506
|
let node_graph_type = nodeData.data && nodeData.data.desc ?
|
|
6405
6507
|
nodeData.data.desc.node_treedb_type : null;
|
|
6406
6508
|
|
|
6509
|
+
/* What the preview writes, undone (see set_preview_undo). */
|
|
6510
|
+
let undo_node = () => {
|
|
6511
|
+
let restoreStyle = { fill: origFill, stroke: origStroke, lineWidth: origLW };
|
|
6512
|
+
if(node_graph_type === 'hierarchical') {
|
|
6513
|
+
let record = nodeData.data.record || {};
|
|
6514
|
+
restoreStyle.innerHTML = build_node_innerHTML(
|
|
6515
|
+
origFill, priv.theme, record.icon,
|
|
6516
|
+
node_label(nodeData.data.desc, record),
|
|
6517
|
+
nodeData.data.desc.topic_name, false, record.id,
|
|
6518
|
+
false, false, false, pills_html_of(gobj, nodeData)
|
|
6519
|
+
);
|
|
6520
|
+
}
|
|
6521
|
+
graph.updateNodeData([{ id: node_id, style: restoreStyle }]);
|
|
6522
|
+
graph.draw();
|
|
6523
|
+
};
|
|
6524
|
+
|
|
6407
6525
|
// Live preview
|
|
6408
6526
|
function preview_node() {
|
|
6409
6527
|
let fill = fillInput.value;
|
|
@@ -6460,19 +6578,7 @@ function show_node_popover(gobj)
|
|
|
6460
6578
|
text: 'cancel',
|
|
6461
6579
|
style: BTN_STYLE_CANCEL,
|
|
6462
6580
|
onClick: () => {
|
|
6463
|
-
|
|
6464
|
-
if(node_graph_type === 'hierarchical') {
|
|
6465
|
-
let record = nodeData.data.record || {};
|
|
6466
|
-
restoreStyle.innerHTML = build_node_innerHTML(
|
|
6467
|
-
origFill, priv.theme, record.icon,
|
|
6468
|
-
node_label(nodeData.data.desc, record),
|
|
6469
|
-
nodeData.data.desc.topic_name, false, record.id,
|
|
6470
|
-
false, false, false, pills_html_of(gobj, nodeData)
|
|
6471
|
-
);
|
|
6472
|
-
}
|
|
6473
|
-
graph.updateNodeData([{ id: node_id, style: restoreStyle }]);
|
|
6474
|
-
graph.draw();
|
|
6475
|
-
hide_node_popover(gobj);
|
|
6581
|
+
hide_node_popover(gobj); /* which undoes the preview */
|
|
6476
6582
|
},
|
|
6477
6583
|
},
|
|
6478
6584
|
{
|
|
@@ -6480,6 +6586,7 @@ function show_node_popover(gobj)
|
|
|
6480
6586
|
style: 'flex:1;padding:6px;background:#1890ff;color:#fff;border:none;' +
|
|
6481
6587
|
'border-radius:4px;cursor:pointer;font-size:13px;font-weight:500;',
|
|
6482
6588
|
onClick: () => {
|
|
6589
|
+
drop_preview_undo(gobj, '_node_preview_undo');
|
|
6483
6590
|
apply_node_properties(gobj, node_id,
|
|
6484
6591
|
fillInput.value,
|
|
6485
6592
|
strokeInput.value,
|
|
@@ -6493,6 +6600,7 @@ function show_node_popover(gobj)
|
|
|
6493
6600
|
|
|
6494
6601
|
priv.$container.appendChild(popover);
|
|
6495
6602
|
priv._node_popover_el = popover;
|
|
6603
|
+
set_preview_undo(gobj, '_node_preview_undo', undo_node);
|
|
6496
6604
|
|
|
6497
6605
|
// Clamp popover inside the container
|
|
6498
6606
|
clamp_popover_position(gobj, popover);
|
|
@@ -6500,6 +6608,7 @@ function show_node_popover(gobj)
|
|
|
6500
6608
|
|
|
6501
6609
|
function hide_node_popover(gobj)
|
|
6502
6610
|
{
|
|
6611
|
+
run_preview_undo(gobj, '_node_preview_undo');
|
|
6503
6612
|
hide_overlay(gobj, '_node_popover_el');
|
|
6504
6613
|
}
|
|
6505
6614
|
|
|
@@ -8980,6 +9089,19 @@ async function reconcile_fold_apply(gobj, opts, visible)
|
|
|
8980
9089
|
return changed;
|
|
8981
9090
|
}
|
|
8982
9091
|
|
|
9092
|
+
/************************************************************
|
|
9093
|
+
* The application changed language: what this gclass DRAWS has
|
|
9094
|
+
* to be drawn again. `refresh_language()` reaches what carries
|
|
9095
|
+
* an i18n key in the DOM; a G6 toolbar and the html of a chip
|
|
9096
|
+
* are built here and carry none.
|
|
9097
|
+
************************************************************/
|
|
9098
|
+
function ac_language_changed(gobj, event, kw, src)
|
|
9099
|
+
{
|
|
9100
|
+
update_toolbar(gobj);
|
|
9101
|
+
repaint_more_chips(gobj);
|
|
9102
|
+
return 0;
|
|
9103
|
+
}
|
|
9104
|
+
|
|
8983
9105
|
/************************************************************
|
|
8984
9106
|
* Repaint the `+N` chips (theme or language changed).
|
|
8985
9107
|
************************************************************/
|
|
@@ -10527,6 +10649,7 @@ function create_gclass(gclass_name)
|
|
|
10527
10649
|
["EV_HIDE", ac_hide, null],
|
|
10528
10650
|
["EV_RESIZE", ac_resize, null],
|
|
10529
10651
|
["EV_THEME", ac_theme, null],
|
|
10652
|
+
["EV_LANGUAGE_CHANGED", ac_language_changed, null],
|
|
10530
10653
|
]]
|
|
10531
10654
|
];
|
|
10532
10655
|
|
|
@@ -10621,6 +10744,7 @@ function create_gclass(gclass_name)
|
|
|
10621
10744
|
["EV_HIDE", 0],
|
|
10622
10745
|
["EV_RESIZE", 0],
|
|
10623
10746
|
["EV_THEME", 0],
|
|
10747
|
+
["EV_LANGUAGE_CHANGED", 0],
|
|
10624
10748
|
];
|
|
10625
10749
|
|
|
10626
10750
|
/*----------------------------------------*
|
|
@@ -173,6 +173,7 @@ let PRIVATE_DATA = {
|
|
|
173
173
|
layout: null,
|
|
174
174
|
_topics_subscribed: {},
|
|
175
175
|
_legend_state: null, /* the engine's last EV_LEGEND_STATE */
|
|
176
|
+
_find_result: null, /* ...and its last EV_FIND_RESULT */
|
|
176
177
|
_links_subscribed: false, /* EV_TREEDB_NODE_LINKED/UNLINKED (treedb-wide) */
|
|
177
178
|
|
|
178
179
|
is_pinhold_window: false, // inherited of v6, todo review
|
|
@@ -303,6 +304,18 @@ function mt_start(gobj)
|
|
|
303
304
|
{
|
|
304
305
|
let priv = gobj.priv;
|
|
305
306
|
|
|
307
|
+
/* The legend is built from the engine's EV_LEGEND_STATE, which
|
|
308
|
+
* arrives after a reconcile and not when the language changes:
|
|
309
|
+
* a chip's title says an ACTION (show / hide this topic), and
|
|
310
|
+
* the strip would keep the old language until somebody folded
|
|
311
|
+
* something. The keys travel in `data-i18n-title` too, so this
|
|
312
|
+
* is the belt to that pair of braces -- and it is what repaints
|
|
313
|
+
* the counted line of the find box, which has no key at all. */
|
|
314
|
+
let shell = yui_shell_of(gobj);
|
|
315
|
+
if(shell) {
|
|
316
|
+
gobj_subscribe_event(shell, "EV_LANGUAGE_CHANGED", {}, gobj);
|
|
317
|
+
}
|
|
318
|
+
|
|
306
319
|
if(priv.gobj_nodes_tree) {
|
|
307
320
|
gobj_start(priv.gobj_nodes_tree);
|
|
308
321
|
}
|
|
@@ -323,6 +336,7 @@ function mt_stop(gobj)
|
|
|
323
336
|
let shell = yui_shell_of(gobj);
|
|
324
337
|
if(shell) {
|
|
325
338
|
yui_shell_set_sub_routes(shell, gobj_read_str_attr(gobj, "base_route"), null);
|
|
339
|
+
gobj_unsubscribe_event(shell, "EV_LANGUAGE_CHANGED", {}, gobj);
|
|
326
340
|
}
|
|
327
341
|
close_json_viewer(gobj);
|
|
328
342
|
gobj_stop_children(gobj);
|
|
@@ -547,26 +561,31 @@ function option_label(name)
|
|
|
547
561
|
************************************************************/
|
|
548
562
|
function node_shape_items(gobj, wide)
|
|
549
563
|
{
|
|
550
|
-
/*
|
|
551
|
-
*
|
|
552
|
-
*
|
|
553
|
-
*
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
564
|
+
/* Three push buttons in one group, not a select: a view is
|
|
565
|
+
* picked at a glance and in one press, and the pressed one
|
|
566
|
+
* SAYS which view is on -- a closed list says nothing until it
|
|
567
|
+
* is opened. Icons, because a card, a line and a figure draw
|
|
568
|
+
* themselves better than three words. */
|
|
569
|
+
let mode_buttons = NODE_MODES.map((mode) => {
|
|
570
|
+
let key = NODE_MODE_LABELS[mode];
|
|
571
|
+
return ['button', {class: 'GRAPH_NODE_MODE_BTN button', type: 'button',
|
|
572
|
+
'data-mode': mode,
|
|
573
|
+
style: {height: wide, width: '2.5em'},
|
|
574
|
+
title: t(key), 'data-i18n-title': key,
|
|
575
|
+
'aria-label': t(key), 'data-i18n-aria-label': key,
|
|
576
|
+
'aria-pressed': 'false'},
|
|
577
|
+
['i', {style: 'font-size:1.5em; color:inherit;', class: NODE_MODE_ICONS[mode]}],
|
|
578
|
+
{
|
|
579
|
+
click: (evt) => {
|
|
580
|
+
evt.stopPropagation();
|
|
581
|
+
gobj_send_event(gobj, "EV_SET_NODE_MODE", {node_mode: mode}, gobj);
|
|
582
|
+
}
|
|
568
583
|
}
|
|
569
|
-
|
|
584
|
+
];
|
|
585
|
+
});
|
|
586
|
+
return [
|
|
587
|
+
['div', {class: 'GRAPH_NODE_MODE buttons has-addons',
|
|
588
|
+
style: 'margin:0 0 0 .5rem; flex:0 0 auto; flex-wrap:nowrap;'}, mode_buttons],
|
|
570
589
|
['button', {class: 'GRAPH_NODE_LABELS button', type: 'button',
|
|
571
590
|
style: {height: wide, width: '2.5em'},
|
|
572
591
|
title: t('node labels'), 'data-i18n-title': 'node labels',
|
|
@@ -583,17 +602,23 @@ function node_shape_items(gobj, wide)
|
|
|
583
602
|
];
|
|
584
603
|
}
|
|
585
604
|
|
|
586
|
-
/* The three views of a record
|
|
587
|
-
*
|
|
605
|
+
/* The three views of a record: the child's `node_mode`, the i18n
|
|
606
|
+
* key of each, and the glyph -- a card, a line, a figure. */
|
|
588
607
|
const NODE_MODES = ['expanded', 'compact', 'shape'];
|
|
589
608
|
const NODE_MODE_LABELS = {
|
|
590
609
|
expanded: 'full',
|
|
591
610
|
compact: 'compact',
|
|
592
611
|
shape: 'shape',
|
|
593
612
|
};
|
|
613
|
+
const NODE_MODE_ICONS = {
|
|
614
|
+
expanded: 'yi-square',
|
|
615
|
+
compact: 'yi-bars',
|
|
616
|
+
shape: 'yi-hexagon-nodes',
|
|
617
|
+
};
|
|
594
618
|
|
|
595
|
-
/* The
|
|
596
|
-
* only means something on figures, so it is disabled
|
|
619
|
+
/* The pressed view and the labels toggle, from the attrs. The
|
|
620
|
+
* toggle only means something on figures, so it is disabled
|
|
621
|
+
* elsewhere.
|
|
597
622
|
* `$root` is whatever holds the toolbar: the toolbar itself before
|
|
598
623
|
* the view is mounted, the view's container after. */
|
|
599
624
|
function refresh_node_shape_buttons(gobj, $root)
|
|
@@ -606,9 +631,10 @@ function refresh_node_shape_buttons(gobj, $root)
|
|
|
606
631
|
mode = 'expanded';
|
|
607
632
|
}
|
|
608
633
|
let labels = gobj_read_bool_attr(gobj, "node_labels");
|
|
609
|
-
let $
|
|
610
|
-
|
|
611
|
-
$
|
|
634
|
+
for(let $btn of $root.querySelectorAll('.GRAPH_NODE_MODE_BTN')) {
|
|
635
|
+
let on = ($btn.getAttribute('data-mode') === mode);
|
|
636
|
+
$btn.classList.toggle('pressed_state', on);
|
|
637
|
+
$btn.setAttribute('aria-pressed', on? 'true' : 'false');
|
|
612
638
|
}
|
|
613
639
|
set_pressed_state($root, '.GRAPH_NODE_LABELS', labels);
|
|
614
640
|
let $labels = $root.querySelector('.GRAPH_NODE_LABELS');
|
|
@@ -2511,6 +2537,8 @@ function refresh_legend(gobj)
|
|
|
2511
2537
|
hidden? `${entry.total}` : `${entry.visible}/${entry.total}`]
|
|
2512
2538
|
);
|
|
2513
2539
|
|
|
2540
|
+
let body_key = is_main? 'main topic' : (hidden? 'show topic' : 'hide topic');
|
|
2541
|
+
|
|
2514
2542
|
/* Built as an object first: an attribute that is `undefined`
|
|
2515
2543
|
* is still SET by createElement2 (to the string "undefined"),
|
|
2516
2544
|
* and a `disabled="undefined"` button is a disabled button --
|
|
@@ -2521,7 +2549,14 @@ function refresh_legend(gobj)
|
|
|
2521
2549
|
(is_main? ' GRAPH_LEGEND_MAIN' : ''),
|
|
2522
2550
|
type: 'button',
|
|
2523
2551
|
style: 'gap:0; flex:0 0 auto;' + (focused? ' ' + LEGEND_FOCUSED_STYLE : ''),
|
|
2524
|
-
|
|
2552
|
+
/* The KEY as well as the text: the strip is redrawn only
|
|
2553
|
+
* when the engine speaks again (EV_LEGEND_STATE), and a
|
|
2554
|
+
* language change is not that -- refresh_language() reaches
|
|
2555
|
+
* what carries `data-i18n-title` and nothing else. The key
|
|
2556
|
+
* is picked here because the chip is rebuilt whenever the
|
|
2557
|
+
* state behind it changes. */
|
|
2558
|
+
title: t(body_key),
|
|
2559
|
+
'data-i18n-title': body_key,
|
|
2525
2560
|
'aria-label': topic_name,
|
|
2526
2561
|
'aria-pressed': hidden? 'false' : 'true',
|
|
2527
2562
|
};
|
|
@@ -2548,7 +2583,9 @@ function refresh_legend(gobj)
|
|
|
2548
2583
|
extras.push(['button', {class: 'GRAPH_LEGEND_STAR button is-small pressed_state',
|
|
2549
2584
|
type: 'button', style: 'padding:0 .4rem;',
|
|
2550
2585
|
title: t('main topic'), 'data-i18n-title': 'main topic',
|
|
2551
|
-
'aria-label': t('main topic'),
|
|
2586
|
+
'aria-label': t('main topic'),
|
|
2587
|
+
'data-i18n-aria-label': 'main topic',
|
|
2588
|
+
'aria-pressed': 'true'},
|
|
2552
2589
|
[['span', {style: LEGEND_GLYPH_STYLE}, '★']], {
|
|
2553
2590
|
click: (evt) => {
|
|
2554
2591
|
evt.stopPropagation();
|
|
@@ -2565,7 +2602,8 @@ function refresh_legend(gobj)
|
|
|
2565
2602
|
extras.push(['button', {class: 'GRAPH_LEGEND_STAR button is-small',
|
|
2566
2603
|
type: 'button', style: 'padding:0 .4rem;',
|
|
2567
2604
|
title: t('main topic'), 'data-i18n-title': 'main topic',
|
|
2568
|
-
'aria-label': t('main topic')
|
|
2605
|
+
'aria-label': t('main topic'),
|
|
2606
|
+
'data-i18n-aria-label': 'main topic'},
|
|
2569
2607
|
[['span', {style: LEGEND_GLYPH_STYLE}, '☆']], {
|
|
2570
2608
|
click: (evt) => {
|
|
2571
2609
|
evt.stopPropagation();
|
|
@@ -2585,6 +2623,7 @@ function refresh_legend(gobj)
|
|
|
2585
2623
|
type: 'button', style: 'padding:0 .45rem;',
|
|
2586
2624
|
title: t('loose records'), 'data-i18n-title': 'loose records',
|
|
2587
2625
|
'aria-label': t('loose records'),
|
|
2626
|
+
'data-i18n-aria-label': 'loose records',
|
|
2588
2627
|
'aria-pressed': entry.loose_shown? 'true' : 'false'
|
|
2589
2628
|
}, `+${entry.loose}`, {
|
|
2590
2629
|
click: (evt) => {
|
|
@@ -2602,6 +2641,7 @@ function refresh_legend(gobj)
|
|
|
2602
2641
|
type: 'button', style: 'padding:0 .4rem;',
|
|
2603
2642
|
title: t('highlight topic'), 'data-i18n-title': 'highlight topic',
|
|
2604
2643
|
'aria-label': t('highlight topic'),
|
|
2644
|
+
'data-i18n-aria-label': 'highlight topic',
|
|
2605
2645
|
'aria-pressed': focused? 'true' : 'false'
|
|
2606
2646
|
}, [['i', {class: 'yi-location-crosshairs', style: LEGEND_GLYPH_STYLE}]], {
|
|
2607
2647
|
click: (evt) => {
|
|
@@ -2621,6 +2661,20 @@ function refresh_legend(gobj)
|
|
|
2621
2661
|
}
|
|
2622
2662
|
}
|
|
2623
2663
|
|
|
2664
|
+
/************************************************************
|
|
2665
|
+
* The application changed language. `refresh_language()` has
|
|
2666
|
+
* already been over the document by now (the shell runs it
|
|
2667
|
+
* before publishing), so what is left is what carries no key:
|
|
2668
|
+
* the legend, whose chips say an ACTION that depends on the
|
|
2669
|
+
* state, and the find box's counted line.
|
|
2670
|
+
************************************************************/
|
|
2671
|
+
function ac_language_changed(gobj, event, kw, src)
|
|
2672
|
+
{
|
|
2673
|
+
refresh_legend(gobj);
|
|
2674
|
+
refresh_find_result(gobj);
|
|
2675
|
+
return 0;
|
|
2676
|
+
}
|
|
2677
|
+
|
|
2624
2678
|
/************************************************************
|
|
2625
2679
|
* The engine said what is drawn: repaint the strip.
|
|
2626
2680
|
************************************************************/
|
|
@@ -2836,6 +2890,18 @@ function ac_toggle_node_labels(gobj, event, kw, src)
|
|
|
2836
2890
|
************************************************************/
|
|
2837
2891
|
function ac_find_result(gobj, event, kw, src)
|
|
2838
2892
|
{
|
|
2893
|
+
/* Kept, because the line is COMPOSED -- a counted word and a
|
|
2894
|
+
* count of hidden topics -- so no i18n key in the DOM can
|
|
2895
|
+
* re-translate it: its owner repaints it from the last answer
|
|
2896
|
+
* when the language changes. */
|
|
2897
|
+
gobj.priv._find_result = kw || null;
|
|
2898
|
+
refresh_find_result(gobj);
|
|
2899
|
+
return 0;
|
|
2900
|
+
}
|
|
2901
|
+
|
|
2902
|
+
function refresh_find_result(gobj)
|
|
2903
|
+
{
|
|
2904
|
+
let kw = gobj.priv._find_result;
|
|
2839
2905
|
let $container = gobj_read_attr(gobj, "$container");
|
|
2840
2906
|
if(!$container) {
|
|
2841
2907
|
return 0;
|
|
@@ -2992,6 +3058,7 @@ function create_gclass(gclass_name)
|
|
|
2992
3058
|
["EV_SHOW", ac_show, null],
|
|
2993
3059
|
["EV_HIDE", ac_hide, null],
|
|
2994
3060
|
["EV_TRANSPORT_STATE", ac_transport_state, null],
|
|
3061
|
+
["EV_LANGUAGE_CHANGED", ac_language_changed, null],
|
|
2995
3062
|
]]
|
|
2996
3063
|
];
|
|
2997
3064
|
|
|
@@ -3040,6 +3107,7 @@ function create_gclass(gclass_name)
|
|
|
3040
3107
|
event_flag_t.EVF_OUTPUT_EVENT | event_flag_t.EVF_NO_WARN_SUBS],
|
|
3041
3108
|
["EV_SHOW", 0],
|
|
3042
3109
|
["EV_HIDE", 0],
|
|
3110
|
+
["EV_LANGUAGE_CHANGED", 0],
|
|
3043
3111
|
["EV_TRANSPORT_STATE", 0],
|
|
3044
3112
|
];
|
|
3045
3113
|
|