@yuneta/gobj-ui 7.23.9 → 7.23.11
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 +36 -11
- package/dist/gobj-ui.cjs.js +175 -9
- package/dist/gobj-ui.es.js +176 -10
- package/package.json +1 -1
- package/src/c_g6_nodes_tree.js +193 -18
- package/src/g6_brush_select_owned.js +69 -0
- package/src/lib_icons.js +13 -0
package/README.md
CHANGED
|
@@ -877,11 +877,19 @@ a card with a border sitting on the graph). Above that width nothing changes.
|
|
|
877
877
|
|
|
878
878
|
**New keys for consumers: `show toolbar`, `hide toolbar`.**
|
|
879
879
|
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
880
|
+
**Multi-selection reaches a finger through a MODE, not through a gesture**
|
|
881
|
+
(`7.23.11`). Both halves of it — shift+click to add a card, shift+drag for the
|
|
882
|
+
rubber band — hang off a key a phone does not have, and there is no spare
|
|
883
|
+
gesture to give them: G6 binds panning and the band to the same plain drag, so
|
|
884
|
+
one of the two has to stand aside. The edit toolbar carries a **selection
|
|
885
|
+
mode** toggle (the dashed marquee, next to `+`): while it is on, a tap picks a
|
|
886
|
+
card and a drag on the background draws the band, and panning is what stands
|
|
887
|
+
aside. It is deliberately a button and not a heuristic — the toolbar says which
|
|
888
|
+
of the two the graph is listening for, and turning it off gives the camera
|
|
889
|
+
back. It is not device-specific: the same button spares a desktop reader the
|
|
890
|
+
key. Leaving edition turns it off, and it is not persisted.
|
|
891
|
+
|
|
892
|
+
**New key for consumers: `selection mode`.**
|
|
885
893
|
|
|
886
894
|
### Tabs opened at runtime, and the two decisions their url costs
|
|
887
895
|
|
|
@@ -928,6 +936,7 @@ clicked":
|
|
|
928
936
|
| click a node | selects it **and opens it**: resize handles, ports, popovers |
|
|
929
937
|
| **shift + click** | adds that node to the selection, or takes it out |
|
|
930
938
|
| **shift + drag on the canvas** | rubber band: the selection becomes what it enclosed |
|
|
939
|
+
| the **selection mode** button | makes those two the PLAIN gestures — a tap picks, a canvas drag is the band — for as long as it is on (panning stands aside meanwhile) |
|
|
931
940
|
| **ctrl/cmd + A** | every node |
|
|
932
941
|
| the **fit-to-selection** button | puts the viewport on what is selected |
|
|
933
942
|
| drag any selected node | **moves the whole selection**, as one undo |
|
|
@@ -964,12 +973,28 @@ gone wrong:
|
|
|
964
973
|
work — so a marquee shows up in the `machine` trace like every other action.
|
|
965
974
|
Shift+click is not G6's `click-select` at all: this gclass already owns
|
|
966
975
|
`EV_NODE_CLICK`, and adding a second selection owner outside the FSM is how
|
|
967
|
-
the two end up disagreeing.
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
976
|
+
the two end up disagreeing. The band comes from `g6_brush_select_owned.js`,
|
|
977
|
+
a `brush-select` under our own id with ONE half removed: the built-in also
|
|
978
|
+
rewrites the `selected` state of every node and every edge on each canvas
|
|
979
|
+
click, behind the gclass and outside the history pause with which it sets
|
|
980
|
+
and clears the selection — a recorded command whose before and after are
|
|
981
|
+
identical, which is a lit Save on a graph nobody has touched (`7.23.10`).
|
|
982
|
+
|
|
983
|
+
Panning gives way while **Shift** is held AND while the pointer is on a card
|
|
984
|
+
(`drag-canvas` takes an `enable` predicate) — the first because the canvas
|
|
985
|
+
would otherwise pan under the rubber band, the second because it would
|
|
986
|
+
otherwise pan under the node being dragged. That second half is G6's own
|
|
987
|
+
default, and an `enable` REPLACES the default rather than adding to it: while
|
|
988
|
+
it was missing, a drag moved the card at twice the pointer and slid the whole
|
|
989
|
+
graph underneath it (`7.23.10`).
|
|
990
|
+
|
|
991
|
+
**Undo, Redo and Save are the history plugin, and it follows the MODE.** It is
|
|
992
|
+
installed on entering edition and removed on leaving it — including when
|
|
993
|
+
edition is reached through the mode selector on a graph whose data is already
|
|
994
|
+
loaded, which is the ordinary way in. Before `7.23.10` it was installed at the
|
|
995
|
+
arrival of the last topic of the load and only if the graph was in edition
|
|
996
|
+
right then, so that ordinary way left the graph with dead Undo/Redo buttons
|
|
997
|
+
and a `history_pause()` nothing answered, while Save still lit on its own.
|
|
973
998
|
|
|
974
999
|
**A delete says what it takes, whether it is one or twenty.** The Delete key
|
|
975
1000
|
asks the same question the per-node delete icon asks, built by the same
|
package/dist/gobj-ui.cjs.js
CHANGED
|
@@ -47493,6 +47493,19 @@ var ICONS = `<svg xmlns="http://www.w3.org/2000/svg">
|
|
|
47493
47493
|
<symbol id="g6-icon-toolbar-hide" viewBox="0 0 384 512">
|
|
47494
47494
|
<path fill="currentColor" d="M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3 297.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256 342.6 150.6z"/>
|
|
47495
47495
|
</symbol>
|
|
47496
|
+
<!-- dashed marquee (selection mode).
|
|
47497
|
+
The band ITSELF, because that is what the button turns on: a
|
|
47498
|
+
drag on the canvas draws one and a tap picks a card. Not the
|
|
47499
|
+
fit-to-selection glyph next to it in the other toolbar -- that
|
|
47500
|
+
one is solid brackets around a solid object and means "put the
|
|
47501
|
+
camera on what is picked", which is the opposite end of the
|
|
47502
|
+
gesture. Dashes: 16 segments of 59 with gaps of 36 over a
|
|
47503
|
+
perimeter of 1520, so they land on the corners. -->
|
|
47504
|
+
<symbol id="g6-icon-select-mode" viewBox="0 0 512 512">
|
|
47505
|
+
<rect x="46" y="86" width="420" height="340" fill="none"
|
|
47506
|
+
stroke="currentColor" stroke-width="40"
|
|
47507
|
+
stroke-dasharray="59 36"/>
|
|
47508
|
+
</symbol>
|
|
47496
47509
|
<!-- floppy-disk (save) -->
|
|
47497
47510
|
<symbol id="g6-icon-save" viewBox="0 0 448 512">
|
|
47498
47511
|
<path fill="currentColor" d="M64 32C28.7 32 0 60.7 0 96L0 416c0 35.3 28.7 64 64 64l320 0c35.3 0 64-28.7 64-64l0-242.7c0-17-6.7-33.3-18.7-45.3L352 50.7C340 38.7 323.7 32 306.7 32L64 32zm32 96c0-17.7 14.3-32 32-32l160 0c17.7 0 32 14.3 32 32l0 64c0 17.7-14.3 32-32 32l-160 0c-17.7 0-32-14.3-32-32l0-64zM224 288a64 64 0 1 1 0 128 64 64 0 1 1 0-128z"/>
|
|
@@ -47507,6 +47520,58 @@ function inject_svg_icons() {
|
|
|
47507
47520
|
document.body.appendChild(div);
|
|
47508
47521
|
}
|
|
47509
47522
|
//#endregion
|
|
47523
|
+
//#region src/g6_brush_select_owned.js
|
|
47524
|
+
/***********************************************************************
|
|
47525
|
+
* g6_brush_select_owned.js
|
|
47526
|
+
*
|
|
47527
|
+
* The rubber band, for a graph whose FSM owns the selection.
|
|
47528
|
+
*
|
|
47529
|
+
* Why this exists
|
|
47530
|
+
* ----------------
|
|
47531
|
+
* G6 v5 `brush-select` does two things: it draws the band and
|
|
47532
|
+
* it keeps the `selected` element state. The second one is
|
|
47533
|
+
* not ours to give away -- `C_G6_NODES_TREE` owns the
|
|
47534
|
+
* selection, sets it in `set_selection()` and clears it in
|
|
47535
|
+
* `deselect_node()`, both with the history recorder paused,
|
|
47536
|
+
* because a selection is not an edit.
|
|
47537
|
+
*
|
|
47538
|
+
* The built-in disagrees on one path: on EVERY canvas click
|
|
47539
|
+
* it calls `clearElementsStates()`, which writes the state of
|
|
47540
|
+
* every node and every edge of the graph -- whether or not
|
|
47541
|
+
* any of them carried it -- outside our pause. G6's history
|
|
47542
|
+
* then records the redraw as a command whose `original` and
|
|
47543
|
+
* `current` are identical: an undo entry that undoes nothing,
|
|
47544
|
+
* and a Save button lit on a graph nobody has touched. One
|
|
47545
|
+
* click on the background was enough.
|
|
47546
|
+
*
|
|
47547
|
+
* So this subclass drops that half and keeps the band. The
|
|
47548
|
+
* selection still clears on a canvas click -- through
|
|
47549
|
+
* `EV_CANVAS_CLICK`, where the gclass has always cleared it.
|
|
47550
|
+
*
|
|
47551
|
+
* Registered under its OWN id: the built-in `brush-select` is
|
|
47552
|
+
* right for a graph that does not own its selection, and no
|
|
47553
|
+
* other consumer of this library asked for this.
|
|
47554
|
+
*
|
|
47555
|
+
* Copyright (c) 2026, ArtGins.
|
|
47556
|
+
* All Rights Reserved.
|
|
47557
|
+
***********************************************************************/
|
|
47558
|
+
/************************************************************
|
|
47559
|
+
* Same band, no state bookkeeping behind the gclass's back
|
|
47560
|
+
************************************************************/
|
|
47561
|
+
var BrushSelectOwned = class extends _antv_g6.BrushSelect {
|
|
47562
|
+
clearElementsStates() {}
|
|
47563
|
+
};
|
|
47564
|
+
/************************************************************
|
|
47565
|
+
* Register once, under our own id
|
|
47566
|
+
************************************************************/
|
|
47567
|
+
var BRUSH_SELECT_OWNED = "yui-brush-select";
|
|
47568
|
+
var __brush_select_registered__ = false;
|
|
47569
|
+
function ensure_brush_select_owned() {
|
|
47570
|
+
if (__brush_select_registered__) return;
|
|
47571
|
+
(0, _antv_g6.register)(_antv_g6.ExtensionCategory.BEHAVIOR, BRUSH_SELECT_OWNED, BrushSelectOwned);
|
|
47572
|
+
__brush_select_registered__ = true;
|
|
47573
|
+
}
|
|
47574
|
+
//#endregion
|
|
47510
47575
|
//#region src/c_g6_nodes_tree.js
|
|
47511
47576
|
/***********************************************************************
|
|
47512
47577
|
* c_g6_nodes_tree.js
|
|
@@ -47565,6 +47630,7 @@ var YuiToolbar = class extends _antv_g6.Toolbar {
|
|
|
47565
47630
|
};
|
|
47566
47631
|
(0, _antv_g6.register)(_antv_g6.ExtensionCategory.PLUGIN, "yui-toolbar", YuiToolbar);
|
|
47567
47632
|
ensure_drag_canvas_patch();
|
|
47633
|
+
ensure_brush_select_owned();
|
|
47568
47634
|
ensure_pinch_zoom_patch();
|
|
47569
47635
|
/***************************************************************
|
|
47570
47636
|
* Constants
|
|
@@ -47689,6 +47755,7 @@ var PRIVATE_DATA$4 = {
|
|
|
47689
47755
|
toolbar_collapsed: true,
|
|
47690
47756
|
_toolbars_could_collapse: null,
|
|
47691
47757
|
_on_focusout_restore: null,
|
|
47758
|
+
selection_mode: false,
|
|
47692
47759
|
_selected_paint_ids: [],
|
|
47693
47760
|
_pending_focus_topic: null,
|
|
47694
47761
|
_pending_find: null,
|
|
@@ -48012,6 +48079,7 @@ function update_toolbar(gobj) {
|
|
|
48012
48079
|
configure_toolbar_edit(gobj);
|
|
48013
48080
|
if (graph_get_plugin(gobj, "toolbar-edit")) graph.updatePlugin({ key: "toolbar-edit" });
|
|
48014
48081
|
update_zoom_selection_button(gobj);
|
|
48082
|
+
update_selection_mode_button(gobj);
|
|
48015
48083
|
}
|
|
48016
48084
|
/************************************************************
|
|
48017
48085
|
* The floating toolbars follow the theme.
|
|
@@ -48226,7 +48294,8 @@ function configure_toolbar(gobj) {
|
|
|
48226
48294
|
* Contains edit-mode buttons: Undo, Redo, Save
|
|
48227
48295
|
************************************************************/
|
|
48228
48296
|
function configure_toolbar_edit(gobj) {
|
|
48229
|
-
|
|
48297
|
+
let priv = gobj.priv;
|
|
48298
|
+
if (!priv.edit_mode || toolbars_collapsed(gobj)) {
|
|
48230
48299
|
graph_remove_plugin(gobj, "toolbar-edit");
|
|
48231
48300
|
return;
|
|
48232
48301
|
}
|
|
@@ -48245,6 +48314,12 @@ function configure_toolbar_edit(gobj) {
|
|
|
48245
48314
|
className: "EV_CREATE_NODE_BTN color_create_state",
|
|
48246
48315
|
title: (0, i18next.t)("create node")
|
|
48247
48316
|
},
|
|
48317
|
+
{
|
|
48318
|
+
id: "g6-icon-select-mode",
|
|
48319
|
+
value: "selection-mode",
|
|
48320
|
+
className: "EV_TOGGLE_SELECTION_MODE" + (priv.selection_mode ? " color_active_state" : ""),
|
|
48321
|
+
title: (0, i18next.t)("selection mode")
|
|
48322
|
+
},
|
|
48248
48323
|
{
|
|
48249
48324
|
id: "g6-icon-save",
|
|
48250
48325
|
value: "save",
|
|
@@ -48273,6 +48348,9 @@ function configure_toolbar_edit(gobj) {
|
|
|
48273
48348
|
case "create-node":
|
|
48274
48349
|
toggle_create_popover(gobj);
|
|
48275
48350
|
break;
|
|
48351
|
+
case "selection-mode":
|
|
48352
|
+
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_TOGGLE_SELECTION_MODE", {}, gobj);
|
|
48353
|
+
break;
|
|
48276
48354
|
case "undo":
|
|
48277
48355
|
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_HISTORY_UNDO", {}, gobj);
|
|
48278
48356
|
break;
|
|
@@ -48315,14 +48393,19 @@ function configure_behaviour(gobj) {
|
|
|
48315
48393
|
{
|
|
48316
48394
|
type: "drag-canvas",
|
|
48317
48395
|
key: "drag-canvas",
|
|
48318
|
-
enable: (event) =>
|
|
48396
|
+
enable: (event) => {
|
|
48397
|
+
if (event.shiftKey || priv.selection_mode) return false;
|
|
48398
|
+
if ("targetType" in event) return event.targetType === "canvas";
|
|
48399
|
+
return true;
|
|
48400
|
+
}
|
|
48319
48401
|
},
|
|
48320
48402
|
"zoom-canvas",
|
|
48321
48403
|
"drag-element",
|
|
48322
48404
|
{
|
|
48323
|
-
type:
|
|
48405
|
+
type: BRUSH_SELECT_OWNED,
|
|
48324
48406
|
key: "brush-select",
|
|
48325
|
-
trigger: ["shift"],
|
|
48407
|
+
trigger: priv.selection_mode ? [] : ["shift"],
|
|
48408
|
+
enable: (event) => event.targetType === "canvas",
|
|
48326
48409
|
enableElements: ["node"],
|
|
48327
48410
|
immediately: false,
|
|
48328
48411
|
onSelect: (states) => {
|
|
@@ -48338,7 +48421,10 @@ function configure_behaviour(gobj) {
|
|
|
48338
48421
|
break;
|
|
48339
48422
|
default: (0, _yuneta_gobj_js.log_error)(`operation mode unknown: ${operation_mode}`);
|
|
48340
48423
|
}
|
|
48341
|
-
if (!priv.edit_mode)
|
|
48424
|
+
if (!priv.edit_mode) {
|
|
48425
|
+
priv.selection_mode = false;
|
|
48426
|
+
deselect_node(gobj);
|
|
48427
|
+
}
|
|
48342
48428
|
graph_write_behaviors(gobj, behaviors);
|
|
48343
48429
|
}
|
|
48344
48430
|
/************************************************************
|
|
@@ -48904,6 +48990,30 @@ function history_resume(gobj) {
|
|
|
48904
48990
|
gobj.priv._history_paused = false;
|
|
48905
48991
|
}
|
|
48906
48992
|
/************************************************************
|
|
48993
|
+
* The history plugin exists while the graph is in EDITION,
|
|
48994
|
+
* and only there.
|
|
48995
|
+
*
|
|
48996
|
+
* It used to be installed at one MOMENT -- the arrival of the
|
|
48997
|
+
* last topic of the load -- and only if the graph happened to
|
|
48998
|
+
* be in edition right then. Entering edition afterwards, which
|
|
48999
|
+
* is the ordinary way in (the graph opens in reading and the
|
|
49000
|
+
* mode selector is next to it), left no history at all: Undo
|
|
49001
|
+
* and Redo were dead buttons that never even lit, `history_
|
|
49002
|
+
* pause()` had no `beforeAddCommand` to answer, and the Save
|
|
49003
|
+
* button was told the graph was dirty by `mark_graph_dirty()`
|
|
49004
|
+
* alone -- which is why a move offered Save without Undo.
|
|
49005
|
+
*
|
|
49006
|
+
* So it follows the MODE, and every place that changes the
|
|
49007
|
+
* mode calls this.
|
|
49008
|
+
************************************************************/
|
|
49009
|
+
function sync_history_plugin(gobj) {
|
|
49010
|
+
let priv = gobj.priv;
|
|
49011
|
+
if (!priv.graph || !priv.graph_rendered) return;
|
|
49012
|
+
if (priv.edit_mode) graph_add_plugin(gobj, "history");
|
|
49013
|
+
else graph_remove_plugin(gobj, "history");
|
|
49014
|
+
update_history_buttons(gobj);
|
|
49015
|
+
}
|
|
49016
|
+
/************************************************************
|
|
48907
49017
|
*
|
|
48908
49018
|
************************************************************/
|
|
48909
49019
|
function update_history_buttons(gobj) {
|
|
@@ -49194,6 +49304,7 @@ function graph_add_plugin(gobj, plugin_key, options) {
|
|
|
49194
49304
|
let priv = gobj.priv;
|
|
49195
49305
|
let graph = priv.graph;
|
|
49196
49306
|
let plugin = graph_get_plugin(gobj, plugin_key);
|
|
49307
|
+
let existed = !!plugin;
|
|
49197
49308
|
if (!plugin) {
|
|
49198
49309
|
let plugin_def = {
|
|
49199
49310
|
key: plugin_key,
|
|
@@ -49204,7 +49315,7 @@ function graph_add_plugin(gobj, plugin_key, options) {
|
|
|
49204
49315
|
}
|
|
49205
49316
|
plugin = graph_get_plugin(gobj, plugin_key);
|
|
49206
49317
|
switch (plugin_key) {
|
|
49207
|
-
case "history": if (plugin) {
|
|
49318
|
+
case "history": if (plugin && !existed) {
|
|
49208
49319
|
plugin.on(_antv_g6.HistoryEvent.CHANGE, () => {
|
|
49209
49320
|
update_history_buttons(gobj);
|
|
49210
49321
|
});
|
|
@@ -49639,6 +49750,21 @@ function update_zoom_selection_button(gobj) {
|
|
|
49639
49750
|
else disableElements($container, ".EV_ZOOM_SELECTION");
|
|
49640
49751
|
}
|
|
49641
49752
|
/************************************************************
|
|
49753
|
+
* The selection mode is a state, so it has to LOOK like one.
|
|
49754
|
+
*
|
|
49755
|
+
* Toggled on the element rather than re-rendered with the
|
|
49756
|
+
* toolbar, for the same reason as the button above: a
|
|
49757
|
+
* re-render rebuilds the innerHTML and drops what every OTHER
|
|
49758
|
+
* button was told.
|
|
49759
|
+
************************************************************/
|
|
49760
|
+
function update_selection_mode_button(gobj) {
|
|
49761
|
+
let priv = gobj.priv;
|
|
49762
|
+
let $container = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
|
|
49763
|
+
if (!$container) return;
|
|
49764
|
+
if (!$container.querySelector(".EV_TOGGLE_SELECTION_MODE")) return;
|
|
49765
|
+
set_active_state($container, ".EV_TOGGLE_SELECTION_MODE", priv.selection_mode);
|
|
49766
|
+
}
|
|
49767
|
+
/************************************************************
|
|
49642
49768
|
* Select a SET of nodes: what a marquee and a shift-click do.
|
|
49643
49769
|
*
|
|
49644
49770
|
* It leaves `_selected_node_id` null even for a set of one,
|
|
@@ -51935,8 +52061,7 @@ function ac_load_data(gobj, event, kw, src) {
|
|
|
51935
52061
|
if (auto_laid) graph_fit_readable(gobj).catch((e) => {
|
|
51936
52062
|
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: cannot fit the graph: ${e}`);
|
|
51937
52063
|
});
|
|
51938
|
-
|
|
51939
|
-
else graph_remove_plugin(gobj, "history");
|
|
52064
|
+
sync_history_plugin(gobj);
|
|
51940
52065
|
if (priv._pending_focus_topic !== null) {
|
|
51941
52066
|
let ft = priv._pending_focus_topic;
|
|
51942
52067
|
priv._pending_focus_topic = null;
|
|
@@ -52238,6 +52363,41 @@ function ac_set_operation_mode$1(gobj, event, kw, src) {
|
|
|
52238
52363
|
(0, _yuneta_gobj_js.gobj_write_attr)(gobj, "operation_mode", kw.operation_mode);
|
|
52239
52364
|
configure_behaviour(gobj);
|
|
52240
52365
|
update_toolbar(gobj);
|
|
52366
|
+
sync_history_plugin(gobj);
|
|
52367
|
+
return 0;
|
|
52368
|
+
}
|
|
52369
|
+
/************************************************************
|
|
52370
|
+
* Selection mode on/off, from the edit toolbar.
|
|
52371
|
+
*
|
|
52372
|
+
* Shift is what the selection is built on, and a telephone has
|
|
52373
|
+
* no Shift: the marquee and the add-to-selection click were a
|
|
52374
|
+
* desktop feature by construction. This makes that key a MODE
|
|
52375
|
+
* -- while it is on, a tap picks a card and a drag on the
|
|
52376
|
+
* background draws the band, so the same two gestures are
|
|
52377
|
+
* reachable with one finger.
|
|
52378
|
+
*
|
|
52379
|
+
* It costs panning while it is on, and deliberately: G6 binds
|
|
52380
|
+
* both to a plain drag, and a gesture cannot be two things.
|
|
52381
|
+
* That is why it is a button and not a heuristic -- the reader
|
|
52382
|
+
* turns it off to move the camera, and the toolbar says which
|
|
52383
|
+
* of the two the graph is listening for.
|
|
52384
|
+
************************************************************/
|
|
52385
|
+
function ac_toggle_selection_mode(gobj, event, kw, src) {
|
|
52386
|
+
let priv = gobj.priv;
|
|
52387
|
+
if (!priv.edit_mode) {
|
|
52388
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: selection mode asked outside edition`);
|
|
52389
|
+
return 0;
|
|
52390
|
+
}
|
|
52391
|
+
priv.selection_mode = !priv.selection_mode;
|
|
52392
|
+
if (priv.selection_mode) {
|
|
52393
|
+
deselect_port(gobj);
|
|
52394
|
+
hide_node_icon(gobj);
|
|
52395
|
+
hide_node_popover(gobj);
|
|
52396
|
+
hide_resize_handles(gobj);
|
|
52397
|
+
priv._selected_node_id = null;
|
|
52398
|
+
}
|
|
52399
|
+
configure_behaviour(gobj);
|
|
52400
|
+
update_selection_mode_button(gobj);
|
|
52241
52401
|
return 0;
|
|
52242
52402
|
}
|
|
52243
52403
|
/************************************************************
|
|
@@ -52305,7 +52465,7 @@ function ac_node_click$2(gobj, event, kw, src) {
|
|
|
52305
52465
|
topic_name: nodedata.data.desc.topic_name,
|
|
52306
52466
|
record: nodedata.data.record
|
|
52307
52467
|
});
|
|
52308
|
-
if (priv.edit_mode && kw.evt.shiftKey) toggle_in_selection(gobj, node_id);
|
|
52468
|
+
if (priv.edit_mode && (kw.evt.shiftKey || priv.selection_mode)) toggle_in_selection(gobj, node_id);
|
|
52309
52469
|
else if (priv.edit_mode) {
|
|
52310
52470
|
let containerRect = priv.$container.getBoundingClientRect();
|
|
52311
52471
|
let canvasPoint = graph.getCanvasByViewport([kw.evt.client.x - containerRect.left, kw.evt.client.y - containerRect.top]);
|
|
@@ -52603,6 +52763,11 @@ function create_gclass$4(gclass_name) {
|
|
|
52603
52763
|
ac_set_operation_mode$1,
|
|
52604
52764
|
null
|
|
52605
52765
|
],
|
|
52766
|
+
[
|
|
52767
|
+
"EV_TOGGLE_SELECTION_MODE",
|
|
52768
|
+
ac_toggle_selection_mode,
|
|
52769
|
+
null
|
|
52770
|
+
],
|
|
52606
52771
|
[
|
|
52607
52772
|
"EV_SAVE_GRAPH",
|
|
52608
52773
|
ac_save_graph,
|
|
@@ -52677,6 +52842,7 @@ function create_gclass$4(gclass_name) {
|
|
|
52677
52842
|
["EV_FULLSCREEN", 0],
|
|
52678
52843
|
["EV_SET_LAYOUT", 0],
|
|
52679
52844
|
["EV_SET_OPERATION_MODE", 0],
|
|
52845
|
+
["EV_TOGGLE_SELECTION_MODE", 0],
|
|
52680
52846
|
["EV_HISTORY_UNDO", 0],
|
|
52681
52847
|
["EV_HISTORY_REDO", 0],
|
|
52682
52848
|
["EV_SAVE_GRAPH", 0],
|
package/dist/gobj-ui.es.js
CHANGED
|
@@ -5,7 +5,7 @@ import { createJSONEditor } from "vanilla-jsoneditor";
|
|
|
5
5
|
import { TabulatorFull } from "tabulator-tables";
|
|
6
6
|
import * as maplibregl from "maplibre-gl";
|
|
7
7
|
import uPlot from "uplot";
|
|
8
|
-
import { BaseLayout, CanvasEvent, Circle, CommonEvent, DragCanvas, EdgeEvent, ExtensionCategory, Graph, HistoryEvent, NodeEvent, Toolbar, ZoomCanvas, register } from "@antv/g6";
|
|
8
|
+
import { BaseLayout, BrushSelect, CanvasEvent, Circle, CommonEvent, DragCanvas, EdgeEvent, ExtensionCategory, Graph, HistoryEvent, NodeEvent, Toolbar, ZoomCanvas, register } from "@antv/g6";
|
|
9
9
|
//#region \0rolldown/runtime.js
|
|
10
10
|
var __create = Object.create;
|
|
11
11
|
var __defProp = Object.defineProperty;
|
|
@@ -47480,6 +47480,19 @@ var ICONS = `<svg xmlns="http://www.w3.org/2000/svg">
|
|
|
47480
47480
|
<symbol id="g6-icon-toolbar-hide" viewBox="0 0 384 512">
|
|
47481
47481
|
<path fill="currentColor" d="M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3 297.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256 342.6 150.6z"/>
|
|
47482
47482
|
</symbol>
|
|
47483
|
+
<!-- dashed marquee (selection mode).
|
|
47484
|
+
The band ITSELF, because that is what the button turns on: a
|
|
47485
|
+
drag on the canvas draws one and a tap picks a card. Not the
|
|
47486
|
+
fit-to-selection glyph next to it in the other toolbar -- that
|
|
47487
|
+
one is solid brackets around a solid object and means "put the
|
|
47488
|
+
camera on what is picked", which is the opposite end of the
|
|
47489
|
+
gesture. Dashes: 16 segments of 59 with gaps of 36 over a
|
|
47490
|
+
perimeter of 1520, so they land on the corners. -->
|
|
47491
|
+
<symbol id="g6-icon-select-mode" viewBox="0 0 512 512">
|
|
47492
|
+
<rect x="46" y="86" width="420" height="340" fill="none"
|
|
47493
|
+
stroke="currentColor" stroke-width="40"
|
|
47494
|
+
stroke-dasharray="59 36"/>
|
|
47495
|
+
</symbol>
|
|
47483
47496
|
<!-- floppy-disk (save) -->
|
|
47484
47497
|
<symbol id="g6-icon-save" viewBox="0 0 448 512">
|
|
47485
47498
|
<path fill="currentColor" d="M64 32C28.7 32 0 60.7 0 96L0 416c0 35.3 28.7 64 64 64l320 0c35.3 0 64-28.7 64-64l0-242.7c0-17-6.7-33.3-18.7-45.3L352 50.7C340 38.7 323.7 32 306.7 32L64 32zm32 96c0-17.7 14.3-32 32-32l160 0c17.7 0 32 14.3 32 32l0 64c0 17.7-14.3 32-32 32l-160 0c-17.7 0-32-14.3-32-32l0-64zM224 288a64 64 0 1 1 0 128 64 64 0 1 1 0-128z"/>
|
|
@@ -47494,6 +47507,58 @@ function inject_svg_icons() {
|
|
|
47494
47507
|
document.body.appendChild(div);
|
|
47495
47508
|
}
|
|
47496
47509
|
//#endregion
|
|
47510
|
+
//#region src/g6_brush_select_owned.js
|
|
47511
|
+
/***********************************************************************
|
|
47512
|
+
* g6_brush_select_owned.js
|
|
47513
|
+
*
|
|
47514
|
+
* The rubber band, for a graph whose FSM owns the selection.
|
|
47515
|
+
*
|
|
47516
|
+
* Why this exists
|
|
47517
|
+
* ----------------
|
|
47518
|
+
* G6 v5 `brush-select` does two things: it draws the band and
|
|
47519
|
+
* it keeps the `selected` element state. The second one is
|
|
47520
|
+
* not ours to give away -- `C_G6_NODES_TREE` owns the
|
|
47521
|
+
* selection, sets it in `set_selection()` and clears it in
|
|
47522
|
+
* `deselect_node()`, both with the history recorder paused,
|
|
47523
|
+
* because a selection is not an edit.
|
|
47524
|
+
*
|
|
47525
|
+
* The built-in disagrees on one path: on EVERY canvas click
|
|
47526
|
+
* it calls `clearElementsStates()`, which writes the state of
|
|
47527
|
+
* every node and every edge of the graph -- whether or not
|
|
47528
|
+
* any of them carried it -- outside our pause. G6's history
|
|
47529
|
+
* then records the redraw as a command whose `original` and
|
|
47530
|
+
* `current` are identical: an undo entry that undoes nothing,
|
|
47531
|
+
* and a Save button lit on a graph nobody has touched. One
|
|
47532
|
+
* click on the background was enough.
|
|
47533
|
+
*
|
|
47534
|
+
* So this subclass drops that half and keeps the band. The
|
|
47535
|
+
* selection still clears on a canvas click -- through
|
|
47536
|
+
* `EV_CANVAS_CLICK`, where the gclass has always cleared it.
|
|
47537
|
+
*
|
|
47538
|
+
* Registered under its OWN id: the built-in `brush-select` is
|
|
47539
|
+
* right for a graph that does not own its selection, and no
|
|
47540
|
+
* other consumer of this library asked for this.
|
|
47541
|
+
*
|
|
47542
|
+
* Copyright (c) 2026, ArtGins.
|
|
47543
|
+
* All Rights Reserved.
|
|
47544
|
+
***********************************************************************/
|
|
47545
|
+
/************************************************************
|
|
47546
|
+
* Same band, no state bookkeeping behind the gclass's back
|
|
47547
|
+
************************************************************/
|
|
47548
|
+
var BrushSelectOwned = class extends BrushSelect {
|
|
47549
|
+
clearElementsStates() {}
|
|
47550
|
+
};
|
|
47551
|
+
/************************************************************
|
|
47552
|
+
* Register once, under our own id
|
|
47553
|
+
************************************************************/
|
|
47554
|
+
var BRUSH_SELECT_OWNED = "yui-brush-select";
|
|
47555
|
+
var __brush_select_registered__ = false;
|
|
47556
|
+
function ensure_brush_select_owned() {
|
|
47557
|
+
if (__brush_select_registered__) return;
|
|
47558
|
+
register(ExtensionCategory.BEHAVIOR, BRUSH_SELECT_OWNED, BrushSelectOwned);
|
|
47559
|
+
__brush_select_registered__ = true;
|
|
47560
|
+
}
|
|
47561
|
+
//#endregion
|
|
47497
47562
|
//#region src/c_g6_nodes_tree.js
|
|
47498
47563
|
/***********************************************************************
|
|
47499
47564
|
* c_g6_nodes_tree.js
|
|
@@ -47552,6 +47617,7 @@ var YuiToolbar = class extends Toolbar {
|
|
|
47552
47617
|
};
|
|
47553
47618
|
register(ExtensionCategory.PLUGIN, "yui-toolbar", YuiToolbar);
|
|
47554
47619
|
ensure_drag_canvas_patch();
|
|
47620
|
+
ensure_brush_select_owned();
|
|
47555
47621
|
ensure_pinch_zoom_patch();
|
|
47556
47622
|
/***************************************************************
|
|
47557
47623
|
* Constants
|
|
@@ -47676,6 +47742,7 @@ var PRIVATE_DATA$4 = {
|
|
|
47676
47742
|
toolbar_collapsed: true,
|
|
47677
47743
|
_toolbars_could_collapse: null,
|
|
47678
47744
|
_on_focusout_restore: null,
|
|
47745
|
+
selection_mode: false,
|
|
47679
47746
|
_selected_paint_ids: [],
|
|
47680
47747
|
_pending_focus_topic: null,
|
|
47681
47748
|
_pending_find: null,
|
|
@@ -47999,6 +48066,7 @@ function update_toolbar(gobj) {
|
|
|
47999
48066
|
configure_toolbar_edit(gobj);
|
|
48000
48067
|
if (graph_get_plugin(gobj, "toolbar-edit")) graph.updatePlugin({ key: "toolbar-edit" });
|
|
48001
48068
|
update_zoom_selection_button(gobj);
|
|
48069
|
+
update_selection_mode_button(gobj);
|
|
48002
48070
|
}
|
|
48003
48071
|
/************************************************************
|
|
48004
48072
|
* The floating toolbars follow the theme.
|
|
@@ -48213,7 +48281,8 @@ function configure_toolbar(gobj) {
|
|
|
48213
48281
|
* Contains edit-mode buttons: Undo, Redo, Save
|
|
48214
48282
|
************************************************************/
|
|
48215
48283
|
function configure_toolbar_edit(gobj) {
|
|
48216
|
-
|
|
48284
|
+
let priv = gobj.priv;
|
|
48285
|
+
if (!priv.edit_mode || toolbars_collapsed(gobj)) {
|
|
48217
48286
|
graph_remove_plugin(gobj, "toolbar-edit");
|
|
48218
48287
|
return;
|
|
48219
48288
|
}
|
|
@@ -48232,6 +48301,12 @@ function configure_toolbar_edit(gobj) {
|
|
|
48232
48301
|
className: "EV_CREATE_NODE_BTN color_create_state",
|
|
48233
48302
|
title: t("create node")
|
|
48234
48303
|
},
|
|
48304
|
+
{
|
|
48305
|
+
id: "g6-icon-select-mode",
|
|
48306
|
+
value: "selection-mode",
|
|
48307
|
+
className: "EV_TOGGLE_SELECTION_MODE" + (priv.selection_mode ? " color_active_state" : ""),
|
|
48308
|
+
title: t("selection mode")
|
|
48309
|
+
},
|
|
48235
48310
|
{
|
|
48236
48311
|
id: "g6-icon-save",
|
|
48237
48312
|
value: "save",
|
|
@@ -48260,6 +48335,9 @@ function configure_toolbar_edit(gobj) {
|
|
|
48260
48335
|
case "create-node":
|
|
48261
48336
|
toggle_create_popover(gobj);
|
|
48262
48337
|
break;
|
|
48338
|
+
case "selection-mode":
|
|
48339
|
+
gobj_send_event(gobj, "EV_TOGGLE_SELECTION_MODE", {}, gobj);
|
|
48340
|
+
break;
|
|
48263
48341
|
case "undo":
|
|
48264
48342
|
gobj_send_event(gobj, "EV_HISTORY_UNDO", {}, gobj);
|
|
48265
48343
|
break;
|
|
@@ -48302,14 +48380,19 @@ function configure_behaviour(gobj) {
|
|
|
48302
48380
|
{
|
|
48303
48381
|
type: "drag-canvas",
|
|
48304
48382
|
key: "drag-canvas",
|
|
48305
|
-
enable: (event) =>
|
|
48383
|
+
enable: (event) => {
|
|
48384
|
+
if (event.shiftKey || priv.selection_mode) return false;
|
|
48385
|
+
if ("targetType" in event) return event.targetType === "canvas";
|
|
48386
|
+
return true;
|
|
48387
|
+
}
|
|
48306
48388
|
},
|
|
48307
48389
|
"zoom-canvas",
|
|
48308
48390
|
"drag-element",
|
|
48309
48391
|
{
|
|
48310
|
-
type:
|
|
48392
|
+
type: BRUSH_SELECT_OWNED,
|
|
48311
48393
|
key: "brush-select",
|
|
48312
|
-
trigger: ["shift"],
|
|
48394
|
+
trigger: priv.selection_mode ? [] : ["shift"],
|
|
48395
|
+
enable: (event) => event.targetType === "canvas",
|
|
48313
48396
|
enableElements: ["node"],
|
|
48314
48397
|
immediately: false,
|
|
48315
48398
|
onSelect: (states) => {
|
|
@@ -48325,7 +48408,10 @@ function configure_behaviour(gobj) {
|
|
|
48325
48408
|
break;
|
|
48326
48409
|
default: log_error(`operation mode unknown: ${operation_mode}`);
|
|
48327
48410
|
}
|
|
48328
|
-
if (!priv.edit_mode)
|
|
48411
|
+
if (!priv.edit_mode) {
|
|
48412
|
+
priv.selection_mode = false;
|
|
48413
|
+
deselect_node(gobj);
|
|
48414
|
+
}
|
|
48329
48415
|
graph_write_behaviors(gobj, behaviors);
|
|
48330
48416
|
}
|
|
48331
48417
|
/************************************************************
|
|
@@ -48891,6 +48977,30 @@ function history_resume(gobj) {
|
|
|
48891
48977
|
gobj.priv._history_paused = false;
|
|
48892
48978
|
}
|
|
48893
48979
|
/************************************************************
|
|
48980
|
+
* The history plugin exists while the graph is in EDITION,
|
|
48981
|
+
* and only there.
|
|
48982
|
+
*
|
|
48983
|
+
* It used to be installed at one MOMENT -- the arrival of the
|
|
48984
|
+
* last topic of the load -- and only if the graph happened to
|
|
48985
|
+
* be in edition right then. Entering edition afterwards, which
|
|
48986
|
+
* is the ordinary way in (the graph opens in reading and the
|
|
48987
|
+
* mode selector is next to it), left no history at all: Undo
|
|
48988
|
+
* and Redo were dead buttons that never even lit, `history_
|
|
48989
|
+
* pause()` had no `beforeAddCommand` to answer, and the Save
|
|
48990
|
+
* button was told the graph was dirty by `mark_graph_dirty()`
|
|
48991
|
+
* alone -- which is why a move offered Save without Undo.
|
|
48992
|
+
*
|
|
48993
|
+
* So it follows the MODE, and every place that changes the
|
|
48994
|
+
* mode calls this.
|
|
48995
|
+
************************************************************/
|
|
48996
|
+
function sync_history_plugin(gobj) {
|
|
48997
|
+
let priv = gobj.priv;
|
|
48998
|
+
if (!priv.graph || !priv.graph_rendered) return;
|
|
48999
|
+
if (priv.edit_mode) graph_add_plugin(gobj, "history");
|
|
49000
|
+
else graph_remove_plugin(gobj, "history");
|
|
49001
|
+
update_history_buttons(gobj);
|
|
49002
|
+
}
|
|
49003
|
+
/************************************************************
|
|
48894
49004
|
*
|
|
48895
49005
|
************************************************************/
|
|
48896
49006
|
function update_history_buttons(gobj) {
|
|
@@ -49181,6 +49291,7 @@ function graph_add_plugin(gobj, plugin_key, options) {
|
|
|
49181
49291
|
let priv = gobj.priv;
|
|
49182
49292
|
let graph = priv.graph;
|
|
49183
49293
|
let plugin = graph_get_plugin(gobj, plugin_key);
|
|
49294
|
+
let existed = !!plugin;
|
|
49184
49295
|
if (!plugin) {
|
|
49185
49296
|
let plugin_def = {
|
|
49186
49297
|
key: plugin_key,
|
|
@@ -49191,7 +49302,7 @@ function graph_add_plugin(gobj, plugin_key, options) {
|
|
|
49191
49302
|
}
|
|
49192
49303
|
plugin = graph_get_plugin(gobj, plugin_key);
|
|
49193
49304
|
switch (plugin_key) {
|
|
49194
|
-
case "history": if (plugin) {
|
|
49305
|
+
case "history": if (plugin && !existed) {
|
|
49195
49306
|
plugin.on(HistoryEvent.CHANGE, () => {
|
|
49196
49307
|
update_history_buttons(gobj);
|
|
49197
49308
|
});
|
|
@@ -49626,6 +49737,21 @@ function update_zoom_selection_button(gobj) {
|
|
|
49626
49737
|
else disableElements($container, ".EV_ZOOM_SELECTION");
|
|
49627
49738
|
}
|
|
49628
49739
|
/************************************************************
|
|
49740
|
+
* The selection mode is a state, so it has to LOOK like one.
|
|
49741
|
+
*
|
|
49742
|
+
* Toggled on the element rather than re-rendered with the
|
|
49743
|
+
* toolbar, for the same reason as the button above: a
|
|
49744
|
+
* re-render rebuilds the innerHTML and drops what every OTHER
|
|
49745
|
+
* button was told.
|
|
49746
|
+
************************************************************/
|
|
49747
|
+
function update_selection_mode_button(gobj) {
|
|
49748
|
+
let priv = gobj.priv;
|
|
49749
|
+
let $container = gobj_read_attr(gobj, "$container");
|
|
49750
|
+
if (!$container) return;
|
|
49751
|
+
if (!$container.querySelector(".EV_TOGGLE_SELECTION_MODE")) return;
|
|
49752
|
+
set_active_state($container, ".EV_TOGGLE_SELECTION_MODE", priv.selection_mode);
|
|
49753
|
+
}
|
|
49754
|
+
/************************************************************
|
|
49629
49755
|
* Select a SET of nodes: what a marquee and a shift-click do.
|
|
49630
49756
|
*
|
|
49631
49757
|
* It leaves `_selected_node_id` null even for a set of one,
|
|
@@ -51922,8 +52048,7 @@ function ac_load_data(gobj, event, kw, src) {
|
|
|
51922
52048
|
if (auto_laid) graph_fit_readable(gobj).catch((e) => {
|
|
51923
52049
|
log_error(`${gobj_short_name(gobj)}: cannot fit the graph: ${e}`);
|
|
51924
52050
|
});
|
|
51925
|
-
|
|
51926
|
-
else graph_remove_plugin(gobj, "history");
|
|
52051
|
+
sync_history_plugin(gobj);
|
|
51927
52052
|
if (priv._pending_focus_topic !== null) {
|
|
51928
52053
|
let ft = priv._pending_focus_topic;
|
|
51929
52054
|
priv._pending_focus_topic = null;
|
|
@@ -52225,6 +52350,41 @@ function ac_set_operation_mode$1(gobj, event, kw, src) {
|
|
|
52225
52350
|
gobj_write_attr(gobj, "operation_mode", kw.operation_mode);
|
|
52226
52351
|
configure_behaviour(gobj);
|
|
52227
52352
|
update_toolbar(gobj);
|
|
52353
|
+
sync_history_plugin(gobj);
|
|
52354
|
+
return 0;
|
|
52355
|
+
}
|
|
52356
|
+
/************************************************************
|
|
52357
|
+
* Selection mode on/off, from the edit toolbar.
|
|
52358
|
+
*
|
|
52359
|
+
* Shift is what the selection is built on, and a telephone has
|
|
52360
|
+
* no Shift: the marquee and the add-to-selection click were a
|
|
52361
|
+
* desktop feature by construction. This makes that key a MODE
|
|
52362
|
+
* -- while it is on, a tap picks a card and a drag on the
|
|
52363
|
+
* background draws the band, so the same two gestures are
|
|
52364
|
+
* reachable with one finger.
|
|
52365
|
+
*
|
|
52366
|
+
* It costs panning while it is on, and deliberately: G6 binds
|
|
52367
|
+
* both to a plain drag, and a gesture cannot be two things.
|
|
52368
|
+
* That is why it is a button and not a heuristic -- the reader
|
|
52369
|
+
* turns it off to move the camera, and the toolbar says which
|
|
52370
|
+
* of the two the graph is listening for.
|
|
52371
|
+
************************************************************/
|
|
52372
|
+
function ac_toggle_selection_mode(gobj, event, kw, src) {
|
|
52373
|
+
let priv = gobj.priv;
|
|
52374
|
+
if (!priv.edit_mode) {
|
|
52375
|
+
log_error(`${gobj_short_name(gobj)}: selection mode asked outside edition`);
|
|
52376
|
+
return 0;
|
|
52377
|
+
}
|
|
52378
|
+
priv.selection_mode = !priv.selection_mode;
|
|
52379
|
+
if (priv.selection_mode) {
|
|
52380
|
+
deselect_port(gobj);
|
|
52381
|
+
hide_node_icon(gobj);
|
|
52382
|
+
hide_node_popover(gobj);
|
|
52383
|
+
hide_resize_handles(gobj);
|
|
52384
|
+
priv._selected_node_id = null;
|
|
52385
|
+
}
|
|
52386
|
+
configure_behaviour(gobj);
|
|
52387
|
+
update_selection_mode_button(gobj);
|
|
52228
52388
|
return 0;
|
|
52229
52389
|
}
|
|
52230
52390
|
/************************************************************
|
|
@@ -52292,7 +52452,7 @@ function ac_node_click$2(gobj, event, kw, src) {
|
|
|
52292
52452
|
topic_name: nodedata.data.desc.topic_name,
|
|
52293
52453
|
record: nodedata.data.record
|
|
52294
52454
|
});
|
|
52295
|
-
if (priv.edit_mode && kw.evt.shiftKey) toggle_in_selection(gobj, node_id);
|
|
52455
|
+
if (priv.edit_mode && (kw.evt.shiftKey || priv.selection_mode)) toggle_in_selection(gobj, node_id);
|
|
52296
52456
|
else if (priv.edit_mode) {
|
|
52297
52457
|
let containerRect = priv.$container.getBoundingClientRect();
|
|
52298
52458
|
let canvasPoint = graph.getCanvasByViewport([kw.evt.client.x - containerRect.left, kw.evt.client.y - containerRect.top]);
|
|
@@ -52590,6 +52750,11 @@ function create_gclass$4(gclass_name) {
|
|
|
52590
52750
|
ac_set_operation_mode$1,
|
|
52591
52751
|
null
|
|
52592
52752
|
],
|
|
52753
|
+
[
|
|
52754
|
+
"EV_TOGGLE_SELECTION_MODE",
|
|
52755
|
+
ac_toggle_selection_mode,
|
|
52756
|
+
null
|
|
52757
|
+
],
|
|
52593
52758
|
[
|
|
52594
52759
|
"EV_SAVE_GRAPH",
|
|
52595
52760
|
ac_save_graph,
|
|
@@ -52664,6 +52829,7 @@ function create_gclass$4(gclass_name) {
|
|
|
52664
52829
|
["EV_FULLSCREEN", 0],
|
|
52665
52830
|
["EV_SET_LAYOUT", 0],
|
|
52666
52831
|
["EV_SET_OPERATION_MODE", 0],
|
|
52832
|
+
["EV_TOGGLE_SELECTION_MODE", 0],
|
|
52667
52833
|
["EV_HISTORY_UNDO", 0],
|
|
52668
52834
|
["EV_HISTORY_REDO", 0],
|
|
52669
52835
|
["EV_SAVE_GRAPH", 0],
|
package/package.json
CHANGED
package/src/c_g6_nodes_tree.js
CHANGED
|
@@ -103,6 +103,10 @@ import i18next, {t} from "i18next";
|
|
|
103
103
|
|
|
104
104
|
import {inject_svg_icons} from "./lib_icons.js";
|
|
105
105
|
import {ensure_drag_canvas_patch} from "./g6_drag_canvas_touch.js";
|
|
106
|
+
import {
|
|
107
|
+
ensure_brush_select_owned,
|
|
108
|
+
BRUSH_SELECT_OWNED,
|
|
109
|
+
} from "./g6_brush_select_owned.js";
|
|
106
110
|
import {
|
|
107
111
|
ensure_pinch_zoom_patch,
|
|
108
112
|
install_long_press_contextmenu,
|
|
@@ -176,6 +180,7 @@ class YuiToolbar extends Toolbar
|
|
|
176
180
|
}
|
|
177
181
|
register(ExtensionCategory.PLUGIN, 'yui-toolbar', YuiToolbar);
|
|
178
182
|
ensure_drag_canvas_patch();
|
|
183
|
+
ensure_brush_select_owned();
|
|
179
184
|
ensure_pinch_zoom_patch();
|
|
180
185
|
|
|
181
186
|
/***************************************************************
|
|
@@ -345,6 +350,9 @@ let PRIVATE_DATA = {
|
|
|
345
350
|
toolbar_collapsed: true, // floating toolbars folded (narrow only)
|
|
346
351
|
_toolbars_could_collapse: null, // last answer, to notice it changed
|
|
347
352
|
_on_focusout_restore: null, // ...and putting it back when it goes nowhere
|
|
353
|
+
selection_mode: false, // taps pick cards, a canvas drag is the band
|
|
354
|
+
// (edition only, transient: a mode nobody
|
|
355
|
+
// can see is a mode nobody can leave)
|
|
348
356
|
_selected_paint_ids: [], // node ids whose card is PAINTED selected
|
|
349
357
|
// (G6's 'selected' state is the selection
|
|
350
358
|
// itself; this is what is on screen, and
|
|
@@ -1021,6 +1029,7 @@ function update_toolbar(gobj)
|
|
|
1021
1029
|
/* A re-render rebuilds the innerHTML, so a button whose enabled
|
|
1022
1030
|
* state is not part of getItems() has to be told again. */
|
|
1023
1031
|
update_zoom_selection_button(gobj);
|
|
1032
|
+
update_selection_mode_button(gobj);
|
|
1024
1033
|
}
|
|
1025
1034
|
|
|
1026
1035
|
/************************************************************
|
|
@@ -1321,6 +1330,19 @@ function configure_toolbar_edit(gobj)
|
|
|
1321
1330
|
getItems: () => {
|
|
1322
1331
|
return [
|
|
1323
1332
|
{ id: 'g6-icon-plus', value: 'create-node', className: 'EV_CREATE_NODE_BTN color_create_state', title: t('create node') },
|
|
1333
|
+
/* The mode is carried in the class getItems()
|
|
1334
|
+
* returns, not only pushed onto the element after
|
|
1335
|
+
* the fact: this toolbar is rebuilt whole (a fold,
|
|
1336
|
+
* a language change), and the rebuilt DOM is not
|
|
1337
|
+
* there yet when the rebuild returns -- so a
|
|
1338
|
+
* button told afterwards came back OFF while the
|
|
1339
|
+
* graph was still listening for a selection. */
|
|
1340
|
+
{
|
|
1341
|
+
id: 'g6-icon-select-mode', value: 'selection-mode',
|
|
1342
|
+
className: 'EV_TOGGLE_SELECTION_MODE' +
|
|
1343
|
+
(priv.selection_mode? ' color_active_state' : ''),
|
|
1344
|
+
title: t('selection mode')
|
|
1345
|
+
},
|
|
1324
1346
|
{ id: 'g6-icon-save', value: 'save', className: 'EV_SAVE_GRAPH', title: t('save'), disabled: true },
|
|
1325
1347
|
{ id: 'g6-icon-undo', value: 'undo', className: 'EV_HISTORY_UNDO', title: t('undo'), disabled: true },
|
|
1326
1348
|
{ id: 'g6-icon-redo', value: 'redo', className: 'EV_HISTORY_REDO', title: t('redo'), disabled: true },
|
|
@@ -1331,6 +1353,9 @@ function configure_toolbar_edit(gobj)
|
|
|
1331
1353
|
case 'create-node':
|
|
1332
1354
|
toggle_create_popover(gobj);
|
|
1333
1355
|
break;
|
|
1356
|
+
case 'selection-mode':
|
|
1357
|
+
gobj_send_event(gobj, "EV_TOGGLE_SELECTION_MODE", {}, gobj);
|
|
1358
|
+
break;
|
|
1334
1359
|
case 'undo':
|
|
1335
1360
|
gobj_send_event(gobj, "EV_HISTORY_UNDO", {}, gobj);
|
|
1336
1361
|
break;
|
|
@@ -1410,11 +1435,28 @@ function configure_behaviour(gobj)
|
|
|
1410
1435
|
/* Panning gives way while Shift is held: that is the
|
|
1411
1436
|
* marquee's gesture, and G6 binds drag-canvas straight
|
|
1412
1437
|
* to the drag events, so without this the canvas pans
|
|
1413
|
-
* under the rubber band.
|
|
1438
|
+
* under the rubber band.
|
|
1439
|
+
*
|
|
1440
|
+
* And it gives way to a NODE drag, which is what G6's
|
|
1441
|
+
* own default `enable` says and what this one has to
|
|
1442
|
+
* repeat: `enable` REPLACES it, it does not add to it.
|
|
1443
|
+
* Dropping the `targetType` half made every drag of a
|
|
1444
|
+
* card pan the canvas as well as move the card -- the
|
|
1445
|
+
* card ran at twice the pointer and the whole graph
|
|
1446
|
+
* slid underneath it, on a move whose RESULT was
|
|
1447
|
+
* right, because a pan writes nothing. */
|
|
1414
1448
|
{
|
|
1415
1449
|
type: "drag-canvas",
|
|
1416
1450
|
key: "drag-canvas",
|
|
1417
|
-
enable: (event) =>
|
|
1451
|
+
enable: (event) => {
|
|
1452
|
+
if(event.shiftKey || priv.selection_mode) {
|
|
1453
|
+
return false;
|
|
1454
|
+
}
|
|
1455
|
+
if('targetType' in event) {
|
|
1456
|
+
return event.targetType === 'canvas';
|
|
1457
|
+
}
|
|
1458
|
+
return true; /* a key, not a pointer */
|
|
1459
|
+
},
|
|
1418
1460
|
},
|
|
1419
1461
|
"zoom-canvas",
|
|
1420
1462
|
/* Moves EVERY node in the `selected` state, not just
|
|
@@ -1429,9 +1471,25 @@ function configure_behaviour(gobj)
|
|
|
1429
1471
|
* ids travel with the event and the action does not
|
|
1430
1472
|
* have to race it. */
|
|
1431
1473
|
{
|
|
1432
|
-
|
|
1474
|
+
/* Ours: the built-in also rewrites the state of
|
|
1475
|
+
* EVERY element on a canvas click, behind the
|
|
1476
|
+
* gclass's back and outside its history pause --
|
|
1477
|
+
* a command that changed nothing, and a Save
|
|
1478
|
+
* button lit on a graph nobody had touched. */
|
|
1479
|
+
type: BRUSH_SELECT_OWNED,
|
|
1433
1480
|
key: "brush-select",
|
|
1434
|
-
|
|
1481
|
+
/* There is no Shift on a phone. The toolbar's
|
|
1482
|
+
* selection mode is that key made into a state:
|
|
1483
|
+
* with it on, the band needs no modifier -- and
|
|
1484
|
+
* panning stands aside above, because the two
|
|
1485
|
+
* cannot both be a plain drag. */
|
|
1486
|
+
trigger: priv.selection_mode ? [] : ["shift"],
|
|
1487
|
+
/* A band starts on the BACKGROUND. G6's default
|
|
1488
|
+
* (`enable: true`) does not look at what is under
|
|
1489
|
+
* the pointer, so a drag that begins on a card
|
|
1490
|
+
* drew a band and moved the card at the same
|
|
1491
|
+
* time. */
|
|
1492
|
+
enable: (event) => event.targetType === 'canvas',
|
|
1435
1493
|
enableElements: ["node"],
|
|
1436
1494
|
/* Left at G6's default (false): the set is read at
|
|
1437
1495
|
* pointerup, not on every pointermove. Each answer
|
|
@@ -1467,6 +1525,9 @@ function configure_behaviour(gobj)
|
|
|
1467
1525
|
break;
|
|
1468
1526
|
}
|
|
1469
1527
|
if(!priv.edit_mode) {
|
|
1528
|
+
/* The selection and the mode that picks it both belong to
|
|
1529
|
+
* edition, and neither survives leaving it. */
|
|
1530
|
+
priv.selection_mode = false;
|
|
1470
1531
|
deselect_node(gobj);
|
|
1471
1532
|
}
|
|
1472
1533
|
graph_write_behaviors(gobj, behaviors);
|
|
@@ -2370,6 +2431,42 @@ function history_resume(gobj)
|
|
|
2370
2431
|
gobj.priv._history_paused = false;
|
|
2371
2432
|
}
|
|
2372
2433
|
|
|
2434
|
+
/************************************************************
|
|
2435
|
+
* The history plugin exists while the graph is in EDITION,
|
|
2436
|
+
* and only there.
|
|
2437
|
+
*
|
|
2438
|
+
* It used to be installed at one MOMENT -- the arrival of the
|
|
2439
|
+
* last topic of the load -- and only if the graph happened to
|
|
2440
|
+
* be in edition right then. Entering edition afterwards, which
|
|
2441
|
+
* is the ordinary way in (the graph opens in reading and the
|
|
2442
|
+
* mode selector is next to it), left no history at all: Undo
|
|
2443
|
+
* and Redo were dead buttons that never even lit, `history_
|
|
2444
|
+
* pause()` had no `beforeAddCommand` to answer, and the Save
|
|
2445
|
+
* button was told the graph was dirty by `mark_graph_dirty()`
|
|
2446
|
+
* alone -- which is why a move offered Save without Undo.
|
|
2447
|
+
*
|
|
2448
|
+
* So it follows the MODE, and every place that changes the
|
|
2449
|
+
* mode calls this.
|
|
2450
|
+
************************************************************/
|
|
2451
|
+
function sync_history_plugin(gobj)
|
|
2452
|
+
{
|
|
2453
|
+
let priv = gobj.priv;
|
|
2454
|
+
|
|
2455
|
+
if(!priv.graph || !priv.graph_rendered) {
|
|
2456
|
+
/* Nothing to hang a plugin on yet: the load path calls
|
|
2457
|
+
* this again once the graph is drawn. */
|
|
2458
|
+
return;
|
|
2459
|
+
}
|
|
2460
|
+
|
|
2461
|
+
if(priv.edit_mode) {
|
|
2462
|
+
graph_add_plugin(gobj, "history");
|
|
2463
|
+
} else {
|
|
2464
|
+
graph_remove_plugin(gobj, "history");
|
|
2465
|
+
}
|
|
2466
|
+
|
|
2467
|
+
update_history_buttons(gobj);
|
|
2468
|
+
}
|
|
2469
|
+
|
|
2373
2470
|
/************************************************************
|
|
2374
2471
|
*
|
|
2375
2472
|
************************************************************/
|
|
@@ -2775,6 +2872,7 @@ function graph_add_plugin(gobj, plugin_key, options)
|
|
|
2775
2872
|
let graph = priv.graph;
|
|
2776
2873
|
|
|
2777
2874
|
let plugin = graph_get_plugin(gobj, plugin_key);
|
|
2875
|
+
let existed = !!plugin;
|
|
2778
2876
|
if(!plugin) {
|
|
2779
2877
|
let plugin_def = {
|
|
2780
2878
|
key: plugin_key,
|
|
@@ -2790,7 +2888,11 @@ function graph_add_plugin(gobj, plugin_key, options)
|
|
|
2790
2888
|
|
|
2791
2889
|
switch(plugin_key) {
|
|
2792
2890
|
case "history":
|
|
2793
|
-
|
|
2891
|
+
/* Wired once per INSTANCE: this is called again on every
|
|
2892
|
+
* load and on every entry into edition, and a second
|
|
2893
|
+
* listener on the same emitter is a second repaint of the
|
|
2894
|
+
* same two buttons. */
|
|
2895
|
+
if(plugin && !existed) {
|
|
2794
2896
|
plugin.on(HistoryEvent.CHANGE, () => {
|
|
2795
2897
|
update_history_buttons(gobj);
|
|
2796
2898
|
});
|
|
@@ -3505,6 +3607,30 @@ function update_zoom_selection_button(gobj)
|
|
|
3505
3607
|
}
|
|
3506
3608
|
}
|
|
3507
3609
|
|
|
3610
|
+
/************************************************************
|
|
3611
|
+
* The selection mode is a state, so it has to LOOK like one.
|
|
3612
|
+
*
|
|
3613
|
+
* Toggled on the element rather than re-rendered with the
|
|
3614
|
+
* toolbar, for the same reason as the button above: a
|
|
3615
|
+
* re-render rebuilds the innerHTML and drops what every OTHER
|
|
3616
|
+
* button was told.
|
|
3617
|
+
************************************************************/
|
|
3618
|
+
function update_selection_mode_button(gobj)
|
|
3619
|
+
{
|
|
3620
|
+
let priv = gobj.priv;
|
|
3621
|
+
let $container = gobj_read_attr(gobj, "$container");
|
|
3622
|
+
|
|
3623
|
+
if(!$container) {
|
|
3624
|
+
return;
|
|
3625
|
+
}
|
|
3626
|
+
|
|
3627
|
+
if(!$container.querySelector(".EV_TOGGLE_SELECTION_MODE")) {
|
|
3628
|
+
return; /* no edit toolbar: not in edition, or folded away */
|
|
3629
|
+
}
|
|
3630
|
+
|
|
3631
|
+
set_active_state($container, ".EV_TOGGLE_SELECTION_MODE", priv.selection_mode);
|
|
3632
|
+
}
|
|
3633
|
+
|
|
3508
3634
|
/************************************************************
|
|
3509
3635
|
* Select a SET of nodes: what a marquee and a shift-click do.
|
|
3510
3636
|
*
|
|
@@ -3563,10 +3689,10 @@ function toggle_in_selection(gobj, node_id)
|
|
|
3563
3689
|
{
|
|
3564
3690
|
let priv = gobj.priv;
|
|
3565
3691
|
|
|
3566
|
-
/* The union of the two views of the same thing
|
|
3567
|
-
* G6's state
|
|
3568
|
-
*
|
|
3569
|
-
* ring. */
|
|
3692
|
+
/* The union of the two views of the same thing: either can hold
|
|
3693
|
+
* an id the other lost -- G6's state is what a drag moves, the
|
|
3694
|
+
* painted set is what the reader can see -- and a card on screen
|
|
3695
|
+
* wearing a ring belongs to the selection whichever view has it. */
|
|
3570
3696
|
let current = new Set(selected_node_ids(gobj));
|
|
3571
3697
|
for(let id of (priv._selected_paint_ids || [])) {
|
|
3572
3698
|
current.add(id);
|
|
@@ -7000,11 +7126,7 @@ function ac_load_data(gobj, event, kw, src)
|
|
|
7000
7126
|
log_error(`${gobj_short_name(gobj)}: cannot fit the graph: ${e}`);
|
|
7001
7127
|
});
|
|
7002
7128
|
}
|
|
7003
|
-
|
|
7004
|
-
graph_add_plugin(gobj, "history");
|
|
7005
|
-
} else {
|
|
7006
|
-
graph_remove_plugin(gobj, "history");
|
|
7007
|
-
}
|
|
7129
|
+
sync_history_plugin(gobj);
|
|
7008
7130
|
/* Nodes exist and are positioned now: apply a focus
|
|
7009
7131
|
* requested before the data was ready (deep link). */
|
|
7010
7132
|
if(priv._pending_focus_topic !== null) {
|
|
@@ -7462,6 +7584,55 @@ function ac_set_operation_mode(gobj, event, kw, src)
|
|
|
7462
7584
|
gobj_write_attr(gobj, "operation_mode", kw.operation_mode);
|
|
7463
7585
|
configure_behaviour(gobj);
|
|
7464
7586
|
update_toolbar(gobj);
|
|
7587
|
+
|
|
7588
|
+
/* `configure_behaviour` is what decides `edit_mode`, and the
|
|
7589
|
+
* history plugin belongs to that decision. */
|
|
7590
|
+
sync_history_plugin(gobj);
|
|
7591
|
+
return 0;
|
|
7592
|
+
}
|
|
7593
|
+
|
|
7594
|
+
/************************************************************
|
|
7595
|
+
* Selection mode on/off, from the edit toolbar.
|
|
7596
|
+
*
|
|
7597
|
+
* Shift is what the selection is built on, and a telephone has
|
|
7598
|
+
* no Shift: the marquee and the add-to-selection click were a
|
|
7599
|
+
* desktop feature by construction. This makes that key a MODE
|
|
7600
|
+
* -- while it is on, a tap picks a card and a drag on the
|
|
7601
|
+
* background draws the band, so the same two gestures are
|
|
7602
|
+
* reachable with one finger.
|
|
7603
|
+
*
|
|
7604
|
+
* It costs panning while it is on, and deliberately: G6 binds
|
|
7605
|
+
* both to a plain drag, and a gesture cannot be two things.
|
|
7606
|
+
* That is why it is a button and not a heuristic -- the reader
|
|
7607
|
+
* turns it off to move the camera, and the toolbar says which
|
|
7608
|
+
* of the two the graph is listening for.
|
|
7609
|
+
************************************************************/
|
|
7610
|
+
function ac_toggle_selection_mode(gobj, event, kw, src)
|
|
7611
|
+
{
|
|
7612
|
+
let priv = gobj.priv;
|
|
7613
|
+
|
|
7614
|
+
if(!priv.edit_mode) {
|
|
7615
|
+
log_error(`${gobj_short_name(gobj)}: selection mode asked outside edition`);
|
|
7616
|
+
return 0;
|
|
7617
|
+
}
|
|
7618
|
+
|
|
7619
|
+
priv.selection_mode = !priv.selection_mode;
|
|
7620
|
+
|
|
7621
|
+
if(priv.selection_mode) {
|
|
7622
|
+
/* A set has no handles, no ports and no popover: those hang
|
|
7623
|
+
* off `_selected_node_id`, the node OPENED for editing, and
|
|
7624
|
+
* in this mode a tap no longer opens one. The selection
|
|
7625
|
+
* itself stays -- entering the mode is not a way to lose it. */
|
|
7626
|
+
deselect_port(gobj);
|
|
7627
|
+
hide_node_icon(gobj);
|
|
7628
|
+
hide_node_popover(gobj);
|
|
7629
|
+
hide_resize_handles(gobj);
|
|
7630
|
+
priv._selected_node_id = null;
|
|
7631
|
+
}
|
|
7632
|
+
|
|
7633
|
+
configure_behaviour(gobj);
|
|
7634
|
+
update_selection_mode_button(gobj);
|
|
7635
|
+
|
|
7465
7636
|
return 0;
|
|
7466
7637
|
}
|
|
7467
7638
|
|
|
@@ -7564,11 +7735,13 @@ function ac_node_click(gobj, event, kw, src)
|
|
|
7564
7735
|
record: nodedata.data.record
|
|
7565
7736
|
});
|
|
7566
7737
|
|
|
7567
|
-
if(priv.edit_mode && kw.evt.shiftKey) {
|
|
7738
|
+
if(priv.edit_mode && (kw.evt.shiftKey || priv.selection_mode)) {
|
|
7568
7739
|
/* Shift+click extends the selection, the way it does
|
|
7569
|
-
* everywhere
|
|
7570
|
-
*
|
|
7571
|
-
*
|
|
7740
|
+
* everywhere -- and so does a plain tap while the
|
|
7741
|
+
* toolbar's selection mode is on, which is that key
|
|
7742
|
+
* for a finger. It never looks for a port: a port is
|
|
7743
|
+
* a one-node affordance, and this gesture is about
|
|
7744
|
+
* the set. */
|
|
7572
7745
|
toggle_in_selection(gobj, node_id);
|
|
7573
7746
|
} else if(priv.edit_mode) {
|
|
7574
7747
|
// Check if click hits a port
|
|
@@ -7873,6 +8046,7 @@ function create_gclass(gclass_name)
|
|
|
7873
8046
|
["EV_FULLSCREEN", ac_fullscreen, null],
|
|
7874
8047
|
["EV_SET_LAYOUT", ac_set_layout, null],
|
|
7875
8048
|
["EV_SET_OPERATION_MODE", ac_set_operation_mode, null],
|
|
8049
|
+
["EV_TOGGLE_SELECTION_MODE", ac_toggle_selection_mode, null],
|
|
7876
8050
|
["EV_SAVE_GRAPH", ac_save_graph, null],
|
|
7877
8051
|
["EV_HISTORY_UNDO", ac_history_undo, null],
|
|
7878
8052
|
["EV_HISTORY_REDO", ac_history_redo, null],
|
|
@@ -7923,6 +8097,7 @@ function create_gclass(gclass_name)
|
|
|
7923
8097
|
["EV_FULLSCREEN", 0],
|
|
7924
8098
|
["EV_SET_LAYOUT", 0],
|
|
7925
8099
|
["EV_SET_OPERATION_MODE", 0],
|
|
8100
|
+
["EV_TOGGLE_SELECTION_MODE", 0],
|
|
7926
8101
|
["EV_HISTORY_UNDO", 0],
|
|
7927
8102
|
["EV_HISTORY_REDO", 0],
|
|
7928
8103
|
["EV_SAVE_GRAPH", 0],
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/***********************************************************************
|
|
2
|
+
* g6_brush_select_owned.js
|
|
3
|
+
*
|
|
4
|
+
* The rubber band, for a graph whose FSM owns the selection.
|
|
5
|
+
*
|
|
6
|
+
* Why this exists
|
|
7
|
+
* ----------------
|
|
8
|
+
* G6 v5 `brush-select` does two things: it draws the band and
|
|
9
|
+
* it keeps the `selected` element state. The second one is
|
|
10
|
+
* not ours to give away -- `C_G6_NODES_TREE` owns the
|
|
11
|
+
* selection, sets it in `set_selection()` and clears it in
|
|
12
|
+
* `deselect_node()`, both with the history recorder paused,
|
|
13
|
+
* because a selection is not an edit.
|
|
14
|
+
*
|
|
15
|
+
* The built-in disagrees on one path: on EVERY canvas click
|
|
16
|
+
* it calls `clearElementsStates()`, which writes the state of
|
|
17
|
+
* every node and every edge of the graph -- whether or not
|
|
18
|
+
* any of them carried it -- outside our pause. G6's history
|
|
19
|
+
* then records the redraw as a command whose `original` and
|
|
20
|
+
* `current` are identical: an undo entry that undoes nothing,
|
|
21
|
+
* and a Save button lit on a graph nobody has touched. One
|
|
22
|
+
* click on the background was enough.
|
|
23
|
+
*
|
|
24
|
+
* So this subclass drops that half and keeps the band. The
|
|
25
|
+
* selection still clears on a canvas click -- through
|
|
26
|
+
* `EV_CANVAS_CLICK`, where the gclass has always cleared it.
|
|
27
|
+
*
|
|
28
|
+
* Registered under its OWN id: the built-in `brush-select` is
|
|
29
|
+
* right for a graph that does not own its selection, and no
|
|
30
|
+
* other consumer of this library asked for this.
|
|
31
|
+
*
|
|
32
|
+
* Copyright (c) 2026, ArtGins.
|
|
33
|
+
* All Rights Reserved.
|
|
34
|
+
***********************************************************************/
|
|
35
|
+
import {
|
|
36
|
+
BrushSelect,
|
|
37
|
+
ExtensionCategory,
|
|
38
|
+
register,
|
|
39
|
+
} from '@antv/g6';
|
|
40
|
+
|
|
41
|
+
/************************************************************
|
|
42
|
+
* Same band, no state bookkeeping behind the gclass's back
|
|
43
|
+
************************************************************/
|
|
44
|
+
class BrushSelectOwned extends BrushSelect {
|
|
45
|
+
clearElementsStates() {
|
|
46
|
+
/*
|
|
47
|
+
* Deliberately empty. The gclass clears the selection from
|
|
48
|
+
* its own EV_CANVAS_CLICK action, with history paused.
|
|
49
|
+
*/
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/************************************************************
|
|
54
|
+
* Register once, under our own id
|
|
55
|
+
************************************************************/
|
|
56
|
+
const BRUSH_SELECT_OWNED = 'yui-brush-select';
|
|
57
|
+
|
|
58
|
+
let __brush_select_registered__ = false;
|
|
59
|
+
|
|
60
|
+
function ensure_brush_select_owned()
|
|
61
|
+
{
|
|
62
|
+
if(__brush_select_registered__) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
register(ExtensionCategory.BEHAVIOR, BRUSH_SELECT_OWNED, BrushSelectOwned);
|
|
66
|
+
__brush_select_registered__ = true;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export { ensure_brush_select_owned, BRUSH_SELECT_OWNED };
|
package/src/lib_icons.js
CHANGED
|
@@ -127,6 +127,19 @@ const ICONS = `<svg xmlns="http://www.w3.org/2000/svg">
|
|
|
127
127
|
<symbol id="g6-icon-toolbar-hide" viewBox="0 0 384 512">
|
|
128
128
|
<path fill="currentColor" d="M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3 297.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256 342.6 150.6z"/>
|
|
129
129
|
</symbol>
|
|
130
|
+
<!-- dashed marquee (selection mode).
|
|
131
|
+
The band ITSELF, because that is what the button turns on: a
|
|
132
|
+
drag on the canvas draws one and a tap picks a card. Not the
|
|
133
|
+
fit-to-selection glyph next to it in the other toolbar -- that
|
|
134
|
+
one is solid brackets around a solid object and means "put the
|
|
135
|
+
camera on what is picked", which is the opposite end of the
|
|
136
|
+
gesture. Dashes: 16 segments of 59 with gaps of 36 over a
|
|
137
|
+
perimeter of 1520, so they land on the corners. -->
|
|
138
|
+
<symbol id="g6-icon-select-mode" viewBox="0 0 512 512">
|
|
139
|
+
<rect x="46" y="86" width="420" height="340" fill="none"
|
|
140
|
+
stroke="currentColor" stroke-width="40"
|
|
141
|
+
stroke-dasharray="59 36"/>
|
|
142
|
+
</symbol>
|
|
130
143
|
<!-- floppy-disk (save) -->
|
|
131
144
|
<symbol id="g6-icon-save" viewBox="0 0 448 512">
|
|
132
145
|
<path fill="currentColor" d="M64 32C28.7 32 0 60.7 0 96L0 416c0 35.3 28.7 64 64 64l320 0c35.3 0 64-28.7 64-64l0-242.7c0-17-6.7-33.3-18.7-45.3L352 50.7C340 38.7 323.7 32 306.7 32L64 32zm32 96c0-17.7 14.3-32 32-32l160 0c17.7 0 32 14.3 32 32l0 64c0 17.7-14.3 32-32 32l-160 0c-17.7 0-32-14.3-32-32l0-64zM224 288a64 64 0 1 1 0 128 64 64 0 1 1 0-128z"/>
|